LLM API 集成完全指南:从模型选型到流式输出的工程实践
把大模型接进产品,不是调通一个 SDK 就完了。本文从真实工程视角讲清模型选型、请求链路、重试与超时、流式响应、结构化输出、提示模板、观测与降本策略,帮你把 LLM API 集成做成稳定能力。
LLM API 集成完全指南:从模型选型到流式输出的工程实践
很多团队第一次做 AI 功能,路径都差不多:
- 申请一个模型 API Key
- 跑通一个 demo
- 聊天框里成功返回一句话
- 兴奋地说:“这不就接上了吗?”
真正上线以后,事情才开始变复杂。
你会很快遇到这些问题:
- 模型偶尔很聪明,偶尔非常跑偏
- 响应时延忽高忽低
- 成本比预期高很多
- 流式输出在前端体验上很丝滑,但服务端链路并不稳定
- 同一个提示词,换个模型结果差一截
- 明明只是“让 AI 帮我总结一下”,结果工程上要补一整套重试、限流、观测、fallback
这时候团队才会意识到:
把 LLM 接进产品,真正难的不是 first call,而是把它做成一个可运营、可观测、可迭代的能力。
这篇文章就从这个角度来讲。
不只是“怎么调用接口”,而是讲清楚:
- 模型怎么选,为什么不能只看排行榜
- 服务端如何封装统一 LLM Gateway
- 流式输出、结构化输出、提示模板该怎么落地
- 如何处理超时、重试、fallback、速率限制
- 怎样把一次“能跑通”变成“能上线”的工程系统
如果你准备把 AI 做进产品,这篇适合作为第一篇工程底稿。
一、先别急着写代码:你接的是“能力”,不是“模型”
很多团队集成 LLM 时,最先纠结的是:
- 选 OpenAI 还是国产模型
- 选大模型还是轻量模型
- 选通用模型还是推理模型
这些问题都重要,但更本质的一层是:
你到底想把哪种 AI 能力接进产品?
因为“LLM API 集成”不是一个需求,而是一类需求的总称。常见至少有四类:
- 聊天对话
- 文本生成 / 总结 / 改写
- 结构化抽取
- Agent / 工具调用
这四类需求,对模型的要求完全不同。
1.1 一个常见误区:直接拿最强模型打所有场景
这会带来三个问题:
- 成本高
- 延迟高
- 稳定性不一定最优
比如:
- 简单分类和抽取,用轻量模型就够
- 复杂长上下文推理,才值得上更强模型
- 实时聊天对延迟敏感,可能优先选响应更快的模型
1.2 先画能力矩阵,再选模型
一个更靠谱的做法是先列矩阵:
| 场景 | 目标 | 关键指标 | 模型要求 |
|---|---|---|---|
| AI 客服初答 | 快速、稳定 | 首 token 延迟、成本 | 速度优先 |
| 文档总结 | 准确、结构清晰 | 结果质量、长度控制 | 指令遵循优先 |
| 信息抽取 | 稳定 JSON | 结构正确率 | 结构化能力优先 |
| 复杂问答 | 推理完整 | 正确率、上下文能力 | 推理能力优先 |
先回答“要什么能力”,再谈“用哪个模型”。
二、模型选型:排行榜重要,但不是决策终点
2.1 选型时至少要看五个维度
| 维度 | 为什么重要 | 例子 |
|---|---|---|
| 质量 | 决定结果是否可用 | 回答准确率、幻觉率 |
| 时延 | 决定产品体验 | 首 token 时间、总耗时 |
| 成本 | 决定是否能规模化 | 输入输出 token 单价 |
| 稳定性 | 决定能否上线 | 限流、超时、成功率 |
| 能力特性 | 决定能否满足场景 | function calling、JSON mode、长上下文 |
2.2 不同场景适合不同模型层级
很多成熟产品会形成一个模型分层:
- 默认模型:覆盖 80% 常规请求
- 高质量模型:用于复杂任务或高价值用户
- 兜底模型:在主模型异常时保证可用性
这比“All in 一个最强模型”更稳,也更省钱。
2.3 一个简单的选型策略
先定义业务场景
↓
用同一套评测样本比质量
↓
测真实首 token 和总响应时延
↓
估算单位请求成本
↓
再决定默认模型 + fallback 模型
如果没有自己的评测集,只看公开 benchmark,很容易选到“比赛成绩好、实际产品体验一般”的模型。
三、统一 LLM Gateway:不要让业务代码到处直接调模型
这是 AI 集成里非常重要的一步。
如果每个业务团队都直接在代码里写:
- provider SDK 调用
- prompt 拼接
- token 统计
- 重试和超时
- 日志埋点
那么三个月后,整个仓库会充满“各自写了一套”的 AI 调用逻辑。
3.1 为什么需要统一网关层
统一 LLM Gateway 可以收口:
- 模型路由
- 密钥管理
- 超时与重试
- 流式响应封装
- token 统计
- 结果审计与观测
- fallback 策略
3.2 一个简化示例
type LLMRequest = {
task: 'chat' | 'summary' | 'extract'
messages: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>
stream?: boolean
temperature?: number
responseFormat?: 'text' | 'json'
}
type LLMResponse = {
content: string
model: string
usage?: {
promptTokens: number
completionTokens: number
}
}
export async function callLLM(input: LLMRequest): Promise<LLMResponse> {
const provider = routeModel(input)
const timeoutMs = input.task === 'chat' ? 12_000 : 20_000
return withRetry(
() => provider.generate(input, timeoutMs),
{ retries: 2, backoffMs: 500 },
)
}
这样业务层只需要表达“我要什么能力”,而不需要知道底层到底接的是哪个模型、哪个平台。
四、Prompt 不是字符串,而是产品接口的一部分
很多人写 prompt 的方式很像写注释:想到什么就往里塞一点。
这在 demo 阶段没问题,到产品阶段会出两个严重问题:
- prompt 版本不可追踪
- 不同团队各自魔改,结果质量不可控
4.1 建议把 prompt 模板显式版本化
export const SUMMARY_PROMPT_V3 = `
你是一个面向普通用户的内容总结助手。
请遵守以下规则:
1. 输出 3 条要点
2. 每条不超过 40 字
3. 不要编造原文没有的信息
4. 最终输出 JSON:{"bullets": string[]}
`
4.2 为什么 prompt 要版本化
因为它已经不是“临时文案”,而是决定结果质量的接口契约。
当你要评估:
- 为什么今天效果变差了
- 为什么某个 A/B 桶表现不同
- 为什么某些用户投诉答案跑偏
没有 prompt 版本和调用记录,你很难定位。
4.3 Prompt 设计的一个务实原则
不要让一个 prompt 同时承担太多目标。
例如:
- 既要总结
- 又要风格化
- 还要抽取结构化字段
- 顺便再生成标题和摘要
任务越杂,稳定性越差。工程上更稳的方式是拆任务。
五、结构化输出:比“写一段漂亮文字”更值钱
对真实产品来说,很多最有商业价值的场景不是聊天,而是:
- 从工单里抽意图
- 从简历里抽结构化字段
- 从用户问题里抽分类和优先级
- 从长文里抽标题、摘要、标签
这类场景最重要的不是“文字优美”,而是“结果结构稳定”。
5.1 一个 JSON 输出示例
const request = {
task: 'extract',
responseFormat: 'json',
messages: [
{
role: 'system',
content: '你是信息抽取助手,只输出 JSON。',
},
{
role: 'user',
content: '帮我从这段投诉文本中提取问题类型、紧急程度和是否涉及退款。',
},
],
}
5.2 工程上还要做 schema 校验
不要因为模型说“我会输出 JSON”,就相信它一定稳定。
更稳的做法是:
import { z } from 'zod'
const TicketSchema = z.object({
issueType: z.string(),
priority: z.enum(['low', 'medium', 'high']),
refundRelated: z.boolean(),
})
export function parseTicketResult(raw: string) {
const parsed = JSON.parse(raw)
return TicketSchema.parse(parsed)
}
这样做的价值非常大:
- 能快速识别异常输出
- 能做 fallback
- 能做统计,知道结构正确率到底是多少
六、流式响应:体验很香,但链路要先稳
流式输出是很多 AI 产品体验的关键。用户看到文本一边生成,会明显感觉“系统在工作”。
6.1 流式为什么值钱
因为它改善的不是总耗时,而是感知等待时间。
一个 8 秒总响应的请求:
- 如果 8 秒后一次性返回,体验很差
- 如果 800ms 后开始持续出字,用户容忍度会高很多
6.2 一个 SSE 示例
export async function streamChat(req, res) {
res.setHeader('Content-Type', 'text/event-stream')
res.setHeader('Cache-Control', 'no-cache')
res.setHeader('Connection', 'keep-alive')
for await (const chunk of llmProvider.stream(req.body.messages)) {
res.write(`data: ${JSON.stringify({ delta: chunk })}\n\n`)
}
res.write('event: done\ndata: {}\n\n')
res.end()
}
6.3 流式集成的三个真实坑
- 中途断流后前端如何恢复状态
- 网关、代理、CDN 是否支持长连接流式透传
- 如果模型侧超时,用户看到的是“停住了”还是明确失败
所以流式响应不只是前端效果,而是全链路兼容性问题。
七、超时、重试、fallback:AI 不稳定是常态,不是例外
这点必须讲清楚。
LLM API 和传统内部 RPC 最大不同之一,就是:
- 结果不完全确定
- 延迟波动更大
- provider 配额和限流更明显
- 某些失败并不是代码 bug,而是平台抖动
7.1 重试不能无脑做
如果一个请求:
- 已经很贵
- 已经很慢
- 失败原因是配额或参数问题
无脑重试只会更贵、更慢。
7.2 更合理的策略
| 场景 | 策略 |
|---|---|
| 网络抖动 / 短暂 5xx | 可有限重试 |
| 参数错误 / schema 错误 | 不重试,直接修输入 |
| 超时 | 看业务场景,必要时降级 |
| 配额限制 | 排队、限流或切换备用模型 |
7.3 一个 fallback 示例
export async function generateSummary(text: string) {
try {
return await callLLM({
task: 'summary',
messages: [{ role: 'user', content: text }],
})
} catch {
return await callBackupModel({
task: 'summary',
messages: [{ role: 'user', content: text }],
})
}
}
fallback 的目标不是保证“完全同质量”,而是保证核心能力不要整体失效。
八、观测体系:如果你看不见 token、时延和失败原因,就不算真正接入完成
很多团队接好后,只有“成功 / 失败”日志。
这远远不够。
8.1 至少应该记录这些指标
| 指标 | 作用 |
|---|---|
| 请求量 | 看使用规模 |
| 首 token 延迟 | 看体验 |
| 总响应时间 | 看吞吐与稳定性 |
| prompt tokens / completion tokens | 看成本 |
| 结构化输出成功率 | 看结果稳定性 |
| provider 错误码 | 看失败类型 |
| fallback 触发率 | 看主模型健康度 |
8.2 为什么这组指标很关键
因为 AI 产品优化时,很多问题不能只凭体感判断。
例如:
- 为什么最近费用变高了
- 为什么某个功能感觉更慢
- 为什么结构化结果出错更多
- 为什么用户抱怨“经常卡住”
这些都需要量化观察。
九、把 LLM 接到生产系统里,还需要哪些工程补丁
9.1 内容审查与安全兜底
即使不做复杂 AI 安全,至少也要:
- 对输入长度做限制
- 对输出做基础审查
- 对敏感业务场景做兜底文案
9.2 会话上下文管理
上下文越长,成本越高,响应越慢。
所以要考虑:
- 历史消息裁剪
- 摘要压缩
- 系统提示与用户消息分离
9.3 可回放的调试能力
遇到线上异常时,你最好能回放:
- 用了哪个模型
- 哪个 prompt 版本
- 输入大概是什么
- token 用量如何
- 为什么 fallback 了
没有这些信息,AI 问题会比普通接口问题更难定位。
十、一个团队级的接入顺序建议
第 1 步:先选一个低风险场景上线
比如:
- 文本总结
- 标签生成
- FAQ 初稿
不要一上来就把 LLM 放进最核心、最严格实时的链路。
第 2 步:统一调用层
不要让业务各自直连 provider。
第 3 步:补结构化输出和校验
这一步能把 AI 功能从“看起来能用”升级到“系统能消费”。
第 4 步:补流式体验和 fallback
让体验和稳定性一起提升。
第 5 步:把观测和成本统计纳入日常看板
否则你永远只能靠投诉发现问题。
十一、给团队的 LLM API 集成检查清单
模型与场景层
- 是否先定义能力场景,再决定模型
- 是否有默认模型和备用模型
- 是否用自有样本做过评测
接入层
- 是否有统一 LLM Gateway
- 是否统一处理超时、重试、fallback
- 是否支持流式与非流式两种模式
输出层
- 是否对结构化输出做 schema 校验
- 是否对 prompt 版本化管理
- 是否能追踪模型、prompt、结果与错误
运营层
- 是否监控 token 成本和时延
- 是否有限流和配额策略
- 是否有异常兜底和降级预案
总结
把 LLM API 集成讲透,可以收敛成 5 句话:
- 你接入的不是某个模型,而是一种产品能力。
- 模型选型要同时看质量、时延、成本和稳定性。
- 统一 Gateway 比每个业务自己直连 provider 更重要。
- 结构化输出、流式响应、fallback 和观测,决定它能不能上线。
- AI 集成的终点不是“能回答”,而是“可控、可测、可迭代”。
如果你只记住一句话,我希望是这一句:
一个真正能落地的 LLM 集成,不是把模型接进代码,而是把不确定性关进系统边界里。
否则 demo 一跑很惊艳,上线之后最先学会的通常不是智能,而是——
超时。