TanStackAI(供应商无关的LLMSDK) tanstack-ai

TanStack AI 是一个供应商无关的大型语言模型软件开发工具包,提供类型安全的聊天功能,支持流式传输,可适配多种AI提供商如OpenAI、Anthropic等。它用于构建聊天应用、前端界面、工具调用、代理循环等,具有工具批准、多模态输入等功能。关键词:TanStack AI,供应商无关,类型安全,流式传输,AI SDK,聊天,工具定义,代理循环。

AI智能体 0 次安装 0 次浏览 更新于 3/7/2026

名称: tanstack-ai 描述: TanStack AI(alpha)供应商无关的类型安全聊天与流式传输,支持OpenAI、Anthropic、Gemini、Ollama。用于聊天API、React/Solid前端与useChat/ChatClient、同构工具、工具批准流程、代理循环、多模态输入或故障排除流式传输和工具定义。

关键词: TanStack AI, @tanstack/ai, @tanstack/ai-react, @tanstack/ai-client, @tanstack/ai-solid, @tanstack/ai-openai, @tanstack/ai-anthropic, @tanstack/ai-gemini, @tanstack/ai-ollama, toolDefinition, client tools, server tools, tool approval, agent loop, streaming, SSE, connection adapters, multimodal, type-safe models, TanStack Start, Next.js API, toStreamResponse, fetchServerSentEvents, chat, useChat, ChatClient, needsApproval 许可证: MIT

TanStack AI(供应商无关的LLM SDK)

状态: 生产就绪 ✅
最后更新: 2025-12-09
依赖: Node.js 18+, TypeScript 5+; React 18+ 用于 @tanstack/ai-react; Solid 1.8+ 用于 @tanstack/ai-solid
最新版本: @tanstack/ai@latest (alpha), @tanstack/ai-react@latest, @tanstack/ai-client@latest, 适配器: @tanstack/ai-openai@latest @tanstack/ai-anthropic@latest @tanstack/ai-gemini@latest @tanstack/ai-ollama@latest


快速开始(7分钟)

1) 安装核心 + 适配器

pnpm add @tanstack/ai @tanstack/ai-react @tanstack/ai-openai
# 根据需要交换适配器: @tanstack/ai-anthropic @tanstack/ai-gemini @tanstack/ai-ollama
pnpm add zod              # 推荐用于工具模式

为什么重要:

  • 核心是框架无关的;React绑定只是包装了无头客户端。 citeturn1search3
  • 适配器抽象了提供商的特性,以便更换模型而无需重写代码。 citeturn1search3

2) 部署流式聊天端点(Next.js 或 TanStack Start)

// app/api/chat/route.ts (Next.js) 或 src/routes/api/chat.ts (TanStack Start)
import { chat, toStreamResponse } from '@tanstack/ai'
import { openai } from '@tanstack/ai-openai'
import { tools } from '@/tools/definitions' // 仅定义

export async function POST(request: Request) {
  const { messages, conversationId } = await request.json()
  const stream = chat({
    adapter: openai(),
    messages,
    model: 'gpt-4o',
    tools,
  })
  return toStreamResponse(stream)
}

关键:

  • 传递工具 定义 到服务器,以便LLM可以请求它们;实现位于其运行时中。 citeturn0search7
  • 始终使用流式传输;分块响应保持UI响应并减少令牌浪费。 citeturn0search1

3) 使用 useChat + SSE 连接客户端

// components/Chat.tsx
import { useChat, fetchServerSentEvents } from '@tanstack/ai-react'
import { clientTools } from '@tanstack/ai-client'
import { updateUIDef } from '@/tools/definitions'

const updateUI = updateUIDef.client(({ message }) => {
  alert(message)
  return { success: true }
})

export function Chat() {
  const tools = clientTools(updateUI)
  const { messages, sendMessage, isLoading, approval } = useChat({
    connection: fetchServerSentEvents('/api/chat'),
    tools,
  })

  return (
    <form onSubmit={e => { e.preventDefault(); sendMessage(e.currentTarget.prompt.value) }}>
      <textarea name="prompt" disabled={isLoading} />
      {approval?.pending && (
        <button type="button" onClick={() => approval.approve()}>
          批准工具
        </button>
      )}
    </form>
  )
}

关键:

  • 使用 fetchServerSentEvents(或匹配的适配器)来镜像流式响应。 citeturn0search0
  • 保持客户端工具名称与定义相同,以避免“工具未找到”错误。 citeturn0search7

四步设置过程

步骤 1: 安全选择提供商 + 模型

  • 添加正确的适配器并设置匹配的API密钥(OPENAI_API_KEYANTHROPIC_API_KEYGEMINI_API_KEY 或 Ollama 主机)。
  • 优先使用适配器提供的每模型选项类型,以避免无效选项(例如,仅视觉字段)。 citeturn1search3

步骤 2: 定义工具一次,按运行时实现

// tools/definitions.ts
import { z, toolDefinition } from '@tanstack/ai'

export const getWeatherDef = toolDefinition({
  name: 'getWeather',
  description: '获取当前城市的天气',
  inputSchema: z.object({ city: z.string() }),
  needsApproval: true,
})

export const getWeather = getWeatherDef.server(async ({ city }) => {
  const data = await fetch(`https://api.weather.gov/points?q=${city}`).then(r => r.json())
  return { summary: data.properties?.relativeLocation?.properties?.city ?? city }
})

export const showToast = getWeatherDef.client(({ city }) => {
  console.log(`显示 ${city} 的提示`)
  return { acknowledged: true }
})

关键点:

  • needsApproval: true 强制对敏感操作进行明确的用户批准。 citeturn0search1
  • 保持工具单用途且幂等;返回结构化对象而不是抛出错误。 citeturn0search1

步骤 3: 创建连接适配器 + 聊天选项

  • 服务器:toStreamResponse(stream) 用于HTTP流式传输;toServerSentEventsStream 助手用于服务器发送事件。 citeturn0search3turn0search4
  • 客户端:fetchServerSentEvents('/api/chat') 或自定义适配器用于websockets(如果需要)。 citeturn0search0
  • 配置 agentLoopStrategy(例如,maxIterations(8))以限制工具递归。 citeturn1search4

步骤 4: 添加可观察性 + 护栏

  • 记录工具执行和流块以进行调试;alpha版本暴露钩子,而开发工具正在进行中。 citeturn0search1
  • 使用Zod验证输入;快速失败并返回类型化错误对象。
  • 在外部API调用中强制超时,以防止代理循环卡住。

关键规则

始终执行

✅ 流式传输响应;避免等待完整完成。 citeturn0search1
✅ 传递 定义 到服务器, 实现 到正确的运行时。 citeturn0search7
✅ 使用Zod模式进行工具输入/输出,以保持跨提供商的类型安全。 citeturn0search1
✅ 使用 maxIterations 限制代理循环,以防止失控工具调用。 citeturn1search4
✅ 对于破坏性或计费敏感的工具,要求 needsApproval。 citeturn0search1

永远不要执行

❌ 在单个请求中混合提供商适配器—每个调用实例化一个适配器。
❌ 从工具抛出原始错误;返回结构化错误载荷。
❌ 发送客户端工具 实现 到服务器(仅定义)。
❌ 硬编码模型能力;依赖适配器类型进行每模型选项。 citeturn0search1
❌ 跳过API密钥检查;在服务器上快速失败并给出有用的消息。 citeturn0search1


已知问题预防

此技能防止 3 个记录的问题:

问题 #1: “工具未找到” / 静默工具失败

原因: 定义未传递给 chat();仅实现存在本地。
预防: 单独导出定义并在服务器 tools 数组中包含它们;保持名称稳定。 citeturn0search7

问题 #2: UI中的流式传输停滞

原因: 服务器响应类型与客户端适配器不匹配(HTTP分块 vs SSE)。
预防: 在服务器使用 toStreamResponse + 在客户端使用 fetchServerSentEvents(或匹配的适配器)。 citeturn0search1turn0search0

问题 #3: 模型选项验证错误

原因: 特定于提供商的选项(例如,视觉参数)发送到不受支持的模型。
预防: 使用适配器提供的类型;依赖每模型选项类型在编译时发现无效字段。 citeturn1search3


配置文件参考

.env.local(完整示例)

OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=
GEMINI_API_KEY=
OLLAMA_HOST=http://localhost:11434
AI_STREAM_STRATEGY=immediate

为什么这些设置:

  • 保持非活动提供商为空,以避免意外多提供商调用。
  • AI_STREAM_STRATEGY 被示例客户端读取以选择块策略(立即 vs 缓冲)。

常见模式

模式 1: 带有限工具的代理循环

import { chat, maxIterations } from '@tanstack/ai'
import { openai } from '@tanstack/ai-openai'

const stream = chat({
  adapter: openai(),
  messages,
  tools,
  agentLoopStrategy: maxIterations(8), // 硬限制
})

何时使用: 任何LLM可以跨工具递归的流程(搜索 → 总结 → 获取详情)。 citeturn1search4

模式 2: 混合服务器 + 客户端工具

// 服务器: 数据获取
const fetchUser = fetchUserDef.server(async ({ id }) => db.user.find(id))

// 客户端: UI更新
const highlightUser = highlightUserDef.client(({ id }) => {
  document.querySelector(`#user-${id}`)?.classList.add('ring')
  return { highlighted: true }
})

chat({ tools: [fetchUser, highlightUser] })

何时使用: 当模型必须在单个循环中同时获取数据和突变UI状态时。 citeturn0search1


使用捆绑资源

脚本 (scripts/)

  • scripts/check-ai-env.sh — 在运行开发服务器之前验证所需的提供商密钥是否存在。

示例用法:

./scripts/check-ai-env.sh

参考 (references/)

  • references/tanstack-ai-cheatsheet.md — 压缩的服务器/客户端/工具模式加故障排除提示。

当Claude应该加载这些时: 调试工具路由、流式传输问题或回忆确切的API调用时。

资产 (assets/)

  • assets/api-chat-route.ts — 复制/粘贴API路由模板与流式传输 + 工具。
  • assets/tool-definitions.ts — 准备使用的toolDefinition示例与批准 + zod模式。

何时加载参考

加载参考文件用于特定实现场景:

  • 适配器比较: 加载 references/adapter-matrix.md 当在OpenAI、Anthropic、Gemini或Ollama适配器之间选择时,或调试特定于提供商的特异性时。

  • React集成详情: 加载 references/react-integration.md 当实现useChat钩子、处理React组件中的SSE流或管理客户端工具状态时。

  • 路由设置: 加载 references/start-vs-next-routing.md 当在Next.js vs TanStack Start中设置API路由时,或故障排除流式响应设置时。

  • 流式传输问题: 加载 references/streaming-troubleshooting.md 当调试SSE连接问题、块传递问题或HTTP流式传输配置时。

  • 快速参考: 加载 references/tanstack-ai-cheatsheet.md 用于压缩的API模式、工具定义语法或快速故障排除提示。

  • 工具架构: 加载 references/tool-patterns.md 当实现复杂的客户端/服务器工具工作流、批准流或混合工具模式时。

  • 类型安全详情: 加载 references/type-safety.md 当使用每模型选项类型、多模态输入或跨适配器调试类型错误时。


高级主题

每模型类型安全

  • 使用适配器类型选择每模型的有效选项;避免在 chat() 上使用通用 any 选项。 citeturn1search3
  • 对于多模态模型,发送带有正确MIME类型的 parts;不支持的模态在编译时被捕获。 citeturn1search3

工具批准UX

  • 通过 useChat 中的 approval 对象暴露;呈现批准/拒绝UI并按工具调用持久化决策。 citeturn0search1
  • 对于可审计操作,记录批准决策与工具输入。

连接适配器

  • 默认使用 fetchServerSentEvents (SSE) 进行最小设置;切换到自定义适配器用于websockets或HTTP分块。 citeturn0search0
  • 在客户端使用 ImmediateStrategy 以发出每个块用于打字指示器UI。 citeturn0search0

依赖

必需:

  • @tanstack/ai@latest — 核心聊天 + 工具引擎
  • @tanstack/ai-react@latest — React绑定(无头使用跳过)
  • @tanstack/ai-client@latest — 无头聊天客户端 + 适配器
  • 适配器: 之一 @tanstack/ai-openai@latest | @tanstack/ai-anthropic@latest | @tanstack/ai-gemini@latest | @tanstack/ai-ollama@latest
  • zod@latest — 工具的模式验证

可选:

  • @tanstack/ai-solid@latest — Solid绑定
  • @tanstack/react-query@latest — 缓存工具内部获取的数据
  • @tanstack/start@latest — 与服务器函数共置AI工具

官方文档


包版本(已验证 2025-12-09)

{
  "dependencies": {
    "@tanstack/ai": "latest",
    "@tanstack/ai-react": "latest",
    "@tanstack/ai-client": "latest",
    "@tanstack/ai-openai": "latest"
  },
  "devDependencies": {
    "zod": "latest"
  }
}

故障排除

问题: UI从未接收到工具输出

解决方案: 确保工具实现返回可序列化对象;避免返回undefined。通过 clientTools(...) 注册客户端实现。

问题: “缺少API密钥”响应

解决方案: 运行 ./scripts/check-ai-env.sh 并在 .env.local 中设置相关的提供商密钥。在调用 chat() 之前在路由中快速失败。 citeturn0search1

问题: 流式传输在第一个块后停止

解决方案: 确认服务器返回 toStreamResponse(stream)(或SSE助手)并且任何反向代理允许分块传输。


完整设置检查清单

使用此检查清单验证您的设置:

  • [ ] 安装了核心 + 一个适配器和zod
  • [ ] API路由返回 toStreamResponse(stream),工具 定义 包含在内
  • [ ] 客户端使用 fetchServerSentEvents(或匹配的适配器)并注册客户端工具实现
  • [ ] needsApproval 路径呈现批准/拒绝UI
  • [ ] 代理循环限制(例如,maxIterations
  • [ ] 环境密钥用 check-ai-env.sh 验证
  • [ ] 多模态输入测试如果目标为视觉/音频模型

问题?问题?

  1. 加载 references/tanstack-ai-cheatsheet.md 获取更深入的示例
  2. 用单个提供商适配器重新运行快速开始步骤
  3. 查看上面的官方文档以获取API表面更新