这是《LLM 应用开发 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 LLM 应用不是简单调用一次模型接口。一个可靠的生产系统需要处理 Prompt、上下文、结构化输出、检索、工具调用、评测、安全护栏、缓存、成本、延迟、可观测性和灰度回滚。
本章先建立 LLM 应用工程的全景图。
1.1 LLM 能做什么
常见能力:
| 能力 | 示例 |
|---|---|
| 文本生成 | 写邮件、总结、改写 |
| 信息抽取 | 从合同中抽字段 |
| 分类 | 工单分类、意图识别 |
| 代码生成 | 辅助编码、SQL 生成 |
| 问答 | 知识库问答 |
| 多轮对话 | 客服、助手 |
| 工具调用 | 查数据库、调 API |
| 规划 | 拆解任务并执行 |
但 LLM 也有边界:
- 可能生成错误内容;
- 不确定何时会失败;
- 上下文长度有限;
- 知识可能过期;
- 不擅长精确计算;
- 可能被注入攻击;
- 成本和延迟随 token 增长;
- 输出需要业务校验。
工程目标不是相信模型,而是设计一个即使模型犯错也不造成事故的系统。
1.2 一个最小调用
概念示例:
{
"model": "chat-model",
"messages": [
{
"role": "system",
"content": "你是订单客服助手,只根据提供的资料回答。"
},
{
"role": "user",
"content": "订单 10001 什么时候发货?"
}
],
"temperature": 0.2,
"max_tokens": 512
}
核心字段:
| 字段 | 说明 |
|---|---|
| model | 模型版本 |
| messages | 对话上下文 |
| system | 角色和约束 |
| temperature | 随机性 |
| max_tokens | 输出上限 |
| stream | 是否流式 |
| tools | 可调用工具 |
temperature 不是准确率参数。分类、抽取、问答通常用低温度;创意生成可以使用更高温度。
1.3 LLM 应用架构
一个生产级问答系统:
User
-> API Gateway
-> Auth / Rate Limit
-> Orchestrator
|-- Context Builder
|-- Retriever
| |-- Embedding
| +-- Vector DB
|-- Tool Executor
|-- Model Caller
|-- Guardrail
|-- Cache
+-- Evaluator
-> Response
| 模块 | 职责 |
|---|---|
| Context Builder | 控制输入内容、顺序和 token |
| Retriever | 找相关资料 |
| Tool Executor | 安全调用外部能力 |
| Model Caller | 处理重试、超时、降级 |
| Guardrail | 输入输出安全检查 |
| Cache | 降低成本和延迟 |
| Evaluator | 质量评估和回归 |
| Observability | 记录 trace、成本、延迟 |
1.4 Prompt 是接口
可以把 Prompt 当成系统接口设计:
角色
任务
输入
约束
输出格式
失败处理
示例
示例:
你是订单系统的意图识别器。
输入:用户消息
输出:JSON
可选意图:query_order, refund, complaint, other
要求:
1. 只输出 JSON;
2. 不确定时输出 other;
3. 不要解释。
用户消息:{message}
Prompt 工程要点:
- 明确任务边界;
- 给出输出 schema;
- 提供少量高质量示例;
- 指定不确定时的行为;
- 避免把秘密放进 Prompt;
- 版本化管理;
- 建立评测集;
- 每次修改都回归。
1.5 RAG 初步
当模型缺少业务知识时,需要检索增强生成。
用户问题
-> 改写
-> 检索
-> 重排
-> 构造上下文
-> 模型生成
-> 引用与校验
关键指标:
| 指标 | 说明 |
|---|---|
| Recall@K | 相关片段是否被召回 |
| Precision@K | 召回片段是否干净 |
| Faithfulness | 回答是否忠于资料 |
| Answer Relevance | 是否回答用户问题 |
| Citation Accuracy | 引用是否正确 |
| Latency | 总延迟 |
| Cost | token 成本 |
RAG 的质量往往先卡在文档解析和切块,而不是模型参数。
1.6 Agent 初步
Agent 是让模型在循环中调用工具、观察结果并继续决策的系统。
Goal
-> Plan
-> Tool Call
-> Observation
-> Next Step
-> Final Answer
最小 Agent 组件:
- 目标;
- 工具清单;
- 工具 schema;
- 状态;
- 记忆;
- 停止条件;
- 权限控制;
- 审计日志;
- 预算限制;
- 失败恢复。
Agent 风险:
- 无限循环;
- 调用高危工具;
- 泄露敏感数据;
- 误信工具结果;
- 成本失控;
- 难以复现。
1.7 结构化输出
业务系统通常需要 JSON:
{
"intent": "query_order",
"confidence": 0.87,
"entities": {
"order_id": "10001"
}
}
工程要求:
- 明确 schema;
- 服务端二次校验;
- 解析失败自动修复或重试;
- 字段枚举受限;
- 不把模型输出直接写入数据库;
- 保存原始输出用于排障;
- 关键动作需要人工或规则确认。
1.8 评测与安全
没有评测,Prompt 和模型的每次改动都是盲改。
评测集应包含:
- 常规问题;
- 边界问题;
- 模糊问题;
- 拒答问题;
- 注入攻击;
- 敏感信息;
- 历史坏案例;
- 不同用户角色。
安全护栏:
| 风险 | 处理 |
|---|---|
| Prompt 注入 | 输入隔离、权限最小化 |
| 敏感信息泄露 | 脱敏、输出过滤 |
| 有害内容 | 分类器、拒绝策略 |
| 越权调用 | 工具权限、人工确认 |
| 成本攻击 | 限流、token 预算 |
| 错误事实 | 引用、校验、置信度 |
1.9 LLM 应用与传统软件的区别
| 维度 | 传统软件 | LLM 应用 |
|---|---|---|
| 行为 | 确定性逻辑 | 概率性生成 |
| 测试 | 断言输入输出 | 评测集和指标 |
| 失败 | 异常和错误码 | 可能看似正确但错误 |
| 性能 | CPU / IO / 网络 | token、上下文长度、模型并发 |
| 变更 | 代码发布 | Prompt、模型、检索同时变 |
| 数据 | 数据库查询 | 向量和语义检索 |
| 安全 | 权限和输入校验 | 注入、幻觉、泄露 |
因此 LLM 应用更需要:
- 版本化;
- 可回放;
- 可评测;
- 可观测;
- 有预算;
- 有降级路径。
本章小结
LLM 应用工程的核心是把模型能力包装成可靠服务:控制上下文、增强检索、约束输出、调用工具、执行护栏、评测质量、观测成本并支持回滚。模型只是系统中的一个不确定组件,工程体系才是生产可用的关键。
思考题
- LLM 应用和传统软件的测试方式有什么不同?
- 为什么 Prompt 需要版本化管理?
- RAG 系统最先应该优化哪个环节?
- Agent 调用工具时如何控制权限和成本?
- 模型输出 JSON 后,服务端还应该做什么?