今日主题
LLM 集成:API 调用、RAG、Function Calling——让前端拥有"大脑"
为什么这项技能重要
前端架构师从"页面工匠"进化为"AI 产品架构师"的关键一步。大模型不再是后端专属——Edge Runtime 和浏览器端推理正在打破边界。
谁在用:- ChatGPT Web、Claude Web:流式 UI + Function Calling
- Vercel AI SDK:全栈 AI 应用的事实标准
- Cursor、Copilot:Agent 式开发工具
- 飞书智能伙伴、钉钉 AI:企业级 AI 集成
- 对延迟极度敏感的业务(LLM 推理 200ms-2s)
- 数据合规要求绝对本地化的场景
- 简单 CRUD 应用引入 LLM 属于过度设计
核心原理(通俗易懂版)
把 LLM 集成想象成餐厅点餐:
- API 调用 = 打电话给厨师下单。你告诉厨师要什么(prompt),厨师做好端给你(response)。
- Function Calling = 菜单上有固定菜品。顾客说"来份牛排",餐厅知道怎么执行(调厨房接口),而不是让顾客自己炒菜。
- RAG = 厨师手边有一本菜谱。遇到新菜,先查菜谱(向量检索),再结合自己的厨艺(模型能力)做出来。
`mermaid
sequenceDiagram
participant U as 用户
participant FE as 前端 (React)
participant BFF as BFF / Edge
participant LLM as LLM API
participant DB as 向量数据库
U->>FE: 提问"上个月销售额?"
FE->>BFF: POST /chat (streaming)
BFF->>LLM: 带 Function Calling schema
LLM-->>BFF: 决定调用 query_sales 函数
BFF->>DB: 执行 SQL 查询
DB-->>BFF: 返回数据
BFF->>LLM: 把数据喂回去
LLM-->>BFF: 自然语言回答
BFF-->>FE: SSE 流式推送
FE-->>U: 逐字显示 + 打字机效果
`
关键设计决策:
| 方案 | 延迟 | 成本 | 适合场景 |
|------|------|------|----------|
| 直接 API 调用 | 中 | 按 token 计费 | 通用对话 |
| Function Calling | 中高 | 额外函数执行 | 工具调用、数据查询 |
| RAG | 高 | 向量库+API | 企业知识库、私有数据 |
企业级最佳实践
1. 流式响应是标配,不是可选用户等待超过 200ms 就会感知到延迟。SSE (Server-Sent Events) 或 ReadableStream 让你能"边想边说"。
`
传统方式: 用户等待 3s → 一次性看到完整回答
流式方式: 200ms 看到第一个词 → 持续刷新 → 最终完整回答
`
2. Function Calling 的 Schema 设计是关键
- Schema 要精确但不冗余,太松模型会自由发挥,太紧模型不会用
- 始终提供 fallback:函数调用失败时回到普通对话
- 在 BFF 层做权限校验,不要把数据库直连暴露给 LLM
- Chunk 策略:按语义段落切分(300-800 token),而非固定长度
- 元数据过滤:先过滤再检索,减少 token 消耗
- 重排序(Rerank):初检召回 50 条,精排取 Top-5
- 忘记设置
max_tokens,导致无限续写 - 没有在 BFF 层做 rate limiting,被用户刷爆
- RAG 没有评估环节,不知道检索质量如何
示例代码
`typescript
// src/ai/llm-integration.ts
import { streamText } from 'ai'; // Vercel AI SDK v3+
/**
* 企业级 LLM 集成核心函数
* 职责:流式对话 + Function Calling + 错误恢复
*/
export async function handleAIRequest(
messages: AIMessage[],
tools?: Record<string, Tool>,
): Promise<ReadableStream<Uint8Array>> {
const result = streamText({
model: openai('gpt-4o'),
messages,
// Function Calling: 声明可用工具
tools,
maxTokens: 2048,
temperature: 0.7,
// 超时保护:5 秒内无响应则终止
abortSignal: AbortSignal.timeout(5000),
});
// 错误恢复:LLM 调用失败时优雅降级
try {
return result.textStream;
} catch (error) {
console.error('[AI] Stream failed, fallback to cached:', error);
return createFallbackStream(messages[messages.length - 1]?.content || '');
}
}
/**
* 示例:销售数据查询工具(Function Calling)
* Schema 设计原则:参数精确、描述清晰、边界明确
*/
const salesTool = {
querySales: {
description: '查询指定时间范围和产品的销售数据',
parameters: z.object({
startDate: z.string().describe('开始日期 YYYY-MM-DD'),
endDate: z.string().describe('结束日期 YYYY-MM-DD'),
productCategory: z.enum(['electronics', 'clothing', 'food']).optional(),
}),
execute: async ({ startDate, endDate, productCategory }) => {
// BFF 层执行真实查询,不暴露数据库结构
const data = await db.sales.query({
where: { date: { gte: startDate, lte: endDate }, category: productCategory },
});
return { totalRevenue: data.sum, orderCount: data.count };
},
},
};
`
学习路径建议
入门:- Vercel AI SDK 文档(https://sdk.vercel.ai)——最实用的前端 LLM 集成指南
- OpenAI Function Calling 文档 —— 理解工具调用的标准协议
- LangChain 源码阅读 —— 理解 RAG 管道的工程实现
- "Retrieval-Augmented Generation for LLMs" 论文 —— RAG 的理论基础
- 做一个"代码审查助手":集成 PR diff + Function Calling + 流式输出
- 做一个"企业知识库问答":Embedding + 向量检索 + 回答溯源
今日思考题
你负责一个金融类 Web 应用,需要集成 AI 功能让用户用自然语言查询账户数据和执行转账。Function Calling 的 schema 中是否应该包含"转账金额"和"收款账户"参数?为什么?考虑安全性、用户体验和模型能力三个维度做 trade-off 分析。
明日预告
Browser AI:WebGPU、WebNN、ONNX Runtime Web——让 AI 推理在浏览器端跑起来,数据不出域。