Skip to content
返回项目教程

AI 聊天机器人

构建生产级 AI 聊天机器人,配备 RAG、函数调用和边缘部署。

设计与架构

选择模型、设计 RAG 检索、函数调用 schema 和会话状态。

为什么

聊天机器人架构决策是粘性的:检索索引、工具 schema、状态形状都耦合模型的上下文窗口和 API。错误的检索策略(仅语义 vs 关键词+语义)会把回答准确率卡在约 60%,无论提示多好。先设计数据流再设计提示。

何时使用

在写聊天端点之前。1-2 周在真实问题上验证检索质量,再建 UI。

如何做

1. 选择模型 + 提供商 - OpenAI gpt-4o / Anthropic Claude / 开源 Llama 3 经 Together - 流式输出 token(SSE)降低感知延迟;规划上下文窗口 - 按任务选:推理(Claude)、工具使用(gpt-4o)、成本(Llama) 2. 设计 RAG 检索 - 文档分块(500-1000 token,50 token 重叠) - 嵌入 + 存入向量库(pgvector、Pinecone、Qdrant) - 检索 top-k(5-10),用交叉编码器重排 - 混合:BM25 关键词 + 语义——在精确术语上胜过纯语义 3. 设计函数调用(工具) - 每个工具定义 JSON schema(name、description、params) - 模型可调用的工具:search_docs、get_order、create_ticket - 工具描述要精确——模型读它来决策 4. 设计会话状态 - 消息存数据库(非仅会话内存)便于审计 - 接近上下文上限时摘要旧轮次 - 追踪工具调用 + 结果,便于调试失败 5. 规划评估 - 从真实用户建 50-100 对黄金 Q&A - 衡量检索召回 + 回答忠实度(RAGAS / TruLens) - 上线前评估——"凭感觉"测试会漏回归

示例

架构: 用户消息 -> retrieve(k=8) -> 重排 -> 构建提示 -> 流式 LLM -> tool_call? -> 执行 -> 回填 向量库(pgvector): docs (id, content, embedding vector(1536), metadata jsonb) 索引:embedding 上 ivfflat 工具 schema(OpenAI 格式): { "type": "function", "function": { "name": "get_order", "description": "按 ID 查用户订单", "parameters": { "type": "object", "properties": { "order_id": { "type": "string" } }, "required": ["order_id"] } } } 黄金评估集:eval/golden.jsonl 中 80 对 Q&A,每个 PR 跑 RAGAS

常见问题

  • ⚠仅语义检索——漏精确匹配(错误码、产品 ID);加 BM25
  • ⚠无重排——余弦 top-k 含近重复;交叉编码器重排提升 10-20% 准确率
  • ⚠凭感觉评估——demo 看着行,索引或提示变更时悄悄回归

最佳实践

  • ✓用混合检索(BM25 + 语义)并交叉编码器重排——这是最大的准确率杠杆
  • ✓工具 schema 像类型化函数一样精确——模糊描述导致错误工具调用
  • ✓UI 前先建黄金评估集;CI 跑 RAGAS,让检索回归失败构建

实现与流式

构建聊天端点,配备 SSE 流式、工具执行循环和护栏。

为什么

用 SSE 流式输出 token,把感知延迟从 5 秒降到 <500ms——这是'感觉聪明'和'感觉坏了'的差别。工具调用循环(模型调工具 -> 你执行 -> 回填结果)是大多数聊天机器人 bug 所在:死循环、未校验工具参数、上下文溢出。

何时使用

检索质量在黄金集验证后。先建流式端点 + 工具循环,再建 UI。

如何做

1. 用 SSE 流式响应 - res.setHeader('Content-Type', 'text/event-stream') - token 到达即流式发送;末尾发 [DONE] - 前端:EventSource 或 fetch + ReadableStream 2. 实现工具调用循环 - 循环:调模型 -> 若 tool_calls,逐个执行 -> 追加结果 -> 再调模型 - 限制迭代次数(最多 5)防死循环 - 执行前用 zod 校验每个工具参数 3. 加护栏 - 输入:检索前过滤提示注入 / PII - 输出:检查回答基于检索上下文(无幻觉) - 按用户限流;每轮限 token 4. 管理上下文窗口 - 每条消息算 token;超 70% 上限时摘要 - 始终保留系统提示 + 最近 2 轮原文 - 丢弃未进入回答的检索块(省成本) 5. 持久化 + 可观测 - 每轮存数据库(消息、工具调用、检索文档) - 日志到 LangSmith / Langfuse 供追踪和评估 - 追踪:进出 token、每轮延迟、工具调用成功率

示例

SSE 流式端点(Node): res.writeHead(200, { 'Content-Type': 'text/event-stream' }); const stream = await openai.chat.completions.create({ stream: true, ... }); for await (const chunk of stream) { res.write(`data: ${JSON.stringify(chunk.choices[0].delta)}\n\n`); } res.write('data: [DONE]\n\n'); res.end(); 工具调用循环(限次): for (let i = 0; i < 5; i++) { const res = await callModel(messages); if (!res.tool_calls?.length) return res.content; for (const call of res.tool_calls) { const args = schema.parse(JSON.parse(call.arguments)); // 校验 messages.push({ role: 'tool', tool_call_id: call.id, content: await runTool(call.name, args) }); } }

常见问题

  • ⚠工具循环无迭代上限——模型重复调同一工具直到超时
  • ⚠发送前缓冲完整响应——5 秒白屏,用户以为坏了
  • ⚠无落地检查——模型自信地从训练数据而非检索文档回答

最佳实践

  • ✓从首个 token 起用 SSE 流式——感知延迟是聊天机器人第一 UX 指标
  • ✓工具调用循环限次(最多 5)并用 schema 校验每个工具参数再执行
  • ✓检查回答落地于检索上下文;标记未落地声明而非展示它

部署与监控

部署到 Vercel/Cloudflare,配备流式、成本追踪和质量告警。

为什么

聊天机器人成本无上限——一个用户循环一小时可烧 $100 token。无按用户限流、成本看板和质量告警(幻觉率、工具失败率),聊天机器人会静默且昂贵地退化。边缘部署(Cloudflare Workers / Vercel)让全球流式延迟低。

何时使用

端点通过黄金评估集后。在功能开关后部署,逐步 10% -> 50% -> 100% 用户。

如何做

1. 选择平台 - Vercel(Next.js Route Handlers):简单,流式 SSE,可选 edge runtime - Cloudflare Workers:全球边缘,免费额度大,AI 绑定 - Fly.io:需长时运行 Python/Go 后端 + 向量库时 2. 流式部署 - edge runtime 最低延迟(但注意上下文窗口限制) - 保持 SSE 连接;处理客户端断开(中止模型调用) 3. 追踪每会话成本 - 每轮记进出 token;乘以模型单价 - 平均成本/会话飙升 > 2x 基线时告警 - 设按用户每日 token 预算;超限硬停或降级模型 4. 监控质量 - 抽样 5% 会话人工评审(或 LLM-as-judge) - 追踪幻觉率、工具调用失败率、用户点踩率 - 1 小时窗口点踩 > 10% 时告警 5. 安全迭代 - 对 10% 流量 A/B 测试提示/索引变更 - 每次部署重跑黄金评估集(回归则阻断) - 提示版本化(git),坏变更一行回滚

示例

Vercel Route Handler(edge + 流式): export const runtime = 'edge'; export async function POST(req) { const stream = await chat(req.body); // 返回 ReadableStream return new Response(stream, { headers: { 'Content-Type': 'text/event-stream' } }); } 成本追踪(每轮): const cost = (promptTokens * 0.005 + completionTokens * 0.015) / 1000; await db.turns.insert({ userId, cost, tokens: { in, out } }); // 告警:每用户每日 SUM(cost) > $2 -> 降级到 gpt-4o-mini 质量告警(Langfuse): thumbsDownRate(window=1h) > 0.10 -> PagerDuty -> 调查提示 diff

常见问题

  • ⚠无按用户成本上限——一个用户工具循环一下午烧光月度 API 预算
  • ⚠部署前未重跑黄金评估——提示微调导致检索回归并全量上线
  • ⚠等完整响应而非流式——延迟高,用户在答案前离开

最佳实践

  • ✓设按用户每日 token 预算,超限降级(非阻断)——保利润不毁 UX
  • ✓每次提示/索引变更把黄金评估集当 CI 门禁;回归则阻断部署
  • ✓部署到边缘(Vercel/Cloudflare)并从首个 token 流式——延迟是聊天机器人第一指标

完整开发者生命周期

从想法到维护的 14 阶段开发者路径图 — 可视化依赖关系、追踪进度。

下一步