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 流式——延迟是聊天机器人第一指标