从 ChatGPT 到真正可用的 AI 产品:会调 API,只是第一步
引言:API 调通之后,真正的差距才刚开始
 返回的文本直接展示给用户。演示阶段效果往往不错——老板点头、同事觉得「可以啊」。但上线第一周,问题通常会集中爆发:
- 同一问题多次提问,输出不一致,用户质疑系统可靠性
- 涉及内部制度、产品文档的问题回答错误——模型并未读取企业私有资料
- 涉及实时数据的需求(如查询工单状态)出现幻觉(Hallucination),模型编造了不存在的结果
- 高峰期响应变慢、Token 费用超预期,且日志简陋,故障无法追溯
上述问题,往往不是「换一个更强的模型」就能解决的。它说明系统在产品能力上仍有明显缺口:会调 API,只是第一步。
本文将按以下结构展开:先分析典型 Demo 的能力边界,再说明核心术语与 LLM 固有限制,继而介绍从 Demo 到产品所需的四层能力(其中 RAG 会重点讲解原理、实现与优化),最后讨论 AI 应用与传统应用的架构差异,以及常见的认知误区。
如果你已能调通 API,但不确定「还差什么才能上线」,可以从第 1 节对照自查。

1. 典型 Demo 的能力边界
1.1 最小实现
from openai import OpenAI
client = OpenAI()
def ask(user_inpt: str) -> str:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": user_input}],
)
return response.choices[0].message.content
这是最常见的起点:一个 user 消息,一次 API 调用,原样返回。
1.2 Demo 能验证什么
- 模型 API 连通性与基本问答能力
- 业务场景是否值得继续投入
1.3 Demo 通常尚未覆盖的产品能力
| 能力项 | 说明 | 缺失后的典型后果 |
|---|---|---|
| System Prompt | 定义角色、边界与输出规范 | 风格漂移、越权回答 |
| 多轮上下文管理 | 维护对话历史(messages 中的 assistant 轮次) | 多轮后遗忘前文 |
| 流式输出(Stream) | 边生成边返回 | 长回答等待久,体验差 |
| 结构化输出(JSON) | 可解析的固定格式 | 后端流程无法稳定对接 |
| 私有知识接入 | RAG 或数据库查询 | 内部问题依赖幻觉 |
| 可观测性与治理 | 日志、限流、降级 | 故障不可追溯,成本不可控 |
简而言之,Demo 验证的是「模型能不能答」;产品要验证的是「系统能不能稳定、可控、持续交付价值」。
1.4 为什么 ChatGPT 网页版感觉更强?
业务方常会问:「ChatGPT 网页版能答对,为什么我们的 API 版不行?」
网页版背后通常不只有裸 LLM,还可能包含:联网检索、文档上传与 RAG、内置工具、产品级的 Prompt 与护栏、以及更完善的多轮管理。而很多团队的 Demo 只有「用户输入 → 单次 API 调用 → 展示输出」。
因此,差距往往不在「模型型号」,而在 系统能力层 是否补齐。
2. 核心术语说明
| 术语 | 英文 / 缩写 | 含义说明 |
|---|---|---|
| ----- | ||
| 大语言模型 | LLM | 基于海量文本训练的生成式模型,如 GPT-4、Claude、通义千问 |
| API | Application Programming Interface | 模型服务商提供的编程接口 |
| Prompt | — | 输入给模型的指令与上下文(角色、任务、参考资料) |
| Token | — | 模型处理文本的计量单位;影响费用、延迟与上下文上限 |
| 幻觉 | Hallucination | 模型生成看似合理但实际错误的内容 |
| RAG | Retrieval-Augmented Generation | 检索增强生成:先检索资料,再基于资料生成答案 |
| Embedding | 向量嵌入 | 将文本转为数值向量,用于语义相似度计算 |
| 向量数据库 | Vector Database | 存储向量并支持相似检索,如 Milvus、Qdrant、pgvector |
| Agent | 智能体 | 可规划任务并调用外部工具的 AI 系统 |
| Function Calling | 函数调用 | 模型输出工具调用请求,由应用代码执行 |
| MCP | Model Context Protocol | 工具接入的标准化协议 |
记住: LLM 具备通用语言能力,但不天然拥有企业私有数据与系统操作权限。
3. LLM 的能力边界
3.1 擅长
- 自然语言理解与生成
- 文本摘要、翻译、改写
- 在 Prompt 给定上下文 内推理
- 配合 Function Calling 触发外部能力(需工程实现)
3.2 需要工程补足
| 限制 | 产品侧应对 |
|---|---|
| 缺乏私有知识 | RAG 或 API/数据库查询 |
| 输出有随机性 | 降低 temperature、结构化输出、回归测试 |
| 幻觉风险 | 引用约束、拒答策略 |
| 上下文有限 | 文档切块 + 检索 |
| 无法直接执行操作 | Agent + Function Calling |
| 依赖外部 API SLA | 重试、降级、多模型路由 |
建议在项目早期向业务方明确上述边界,有助于管理预期,减少后续「AI 为何还会错」的沟通成本。
4. 纯 LLM、RAG、Agent:怎么选?
在进入具体实现之前,有必要先厘清三者的适用边界——很多项目过早引入 Agent,或该用 RAG 时仍在裸调 LLM,往往源于选型不清。
很多初学者会把三者混为一谈。可以用下面的判断逻辑:
| 场景特征 | 推荐方案 | 原因 |
|---|---|---|
| 开放式问答、文案生成、不要求事实绝对准确 | 纯 LLM + 好的 Prompt | 实现简单,成本低 |
| 答案存在于企业文档、制度、手册、知识库 | RAG | 需要可追溯的私有知识 |
| 答案存在于实时系统(订单、工单、数据库) | Agent + Function Calling | 需要查询或操作外部系统 |
| 既要查文档,又要查业务数据 | RAG + Agent 组合 | 两类知识源并存 |
第 01 篇重点在建立整体地图;RAG 与 Agent 的专项实战分别在系列第 9~13 篇、第 14~17 篇展开。
5. 从 Demo 到产品的四层能力
下面四层能力构成一条常见的产品化路径。实际项目中不一定严格串行,但任何一层长期缺失,都会在对应场景下成为瓶颈。
5.1 第一层:稳定的模型调用
目标: 获得可预期、可解析、可复用的输出。
消息结构(Messages)
messages = [
{
"role": "system",
"content": (
"你是企业知识库助手。只根据【参考资料】回答;"
"资料未提及则回答「暂无相关信息」。不要编造。"
),
},
{"role": "user", "content": f"【参考资料】\n{context}\n\n【问题】\n{question}"},
]
- system:角色、边界、输出格式(长期生效,便于统一维护)
- user:当前问题与数据
- assistant:多轮历史回复(维护对话连贯性)
不要把所有规则堆入 user 消息——否则每次请求都要重复传递,既浪费 Token,也不利于版本管理。
关键参数
| 参数 | 作用 | 建议 |
|---|---|---|
| temperature | 输出随机性 | 客服/抽取:0~0.3;写作:0.6~0.8 |
| max_tokens | 生成长度上限 | 必须设置,防止费用失控 |
| stream | 流式返回 | 对话 UI 建议开启 |
流式输出能明显改善等待体验。后端伪代码示意:
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content or ""
yield delta # 推送给前端 SSE/WebSocket
结构化输出
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
temperature=0.2,
response_format={"type": "json_object"},
)
data = json.loads(response.choices[0].message.content)
建议增加 schema 校验(必填字段、枚举合法性)。
异常与降级
- 超时:有限重试 + 指数退避
- 主模型 503:切换备用模型
- JSON 解析失败:记录原文,修复 Prompt 或人工兜底
5.2 第二层:RAG(检索增强生成)
目标: 使回答有据可依,降低幻觉。ToB 场景中,RAG 常是能否上线的关键。
5.2.1 RAG 是什么
RAG 即在生成前,先从知识库 检索 相关片段,将其 增强 为上下文,再由 LLM 生成 答案。核心思路:只给与问题相关的片段,而非全量文档。

5.2.2 工作原理
(1)切块(Chunking)
长文档切为 300~800 Token 的片段。整库塞入 Prompt 会超上下文、费用高、检索不准。
(2)向量化(Embedding)
每段文本通过 Embedding 模型转为向量;语义相近的文本,向量距离更近,实现 语义检索。
(3)检索 + 生成
【离线建库】文档 → 解析 → 切块 → Embedding → 向量库(含元数据)
【在线问答】问题 → Embedding → Top-K 检索 → 拼入 Prompt → 生成 → 展示引用
5.2.3 最小实现(四步)
# Step 1:读取并切块
raw_text = load_pdf("
员工手册.pdf")
chunks = split_by_heading(raw_text, max_tokens=500)
# Step 2:Embedding 入库
for i, chunk in enumerate(chunks):
vector = embed(chunk["text"])
vector_db.upsert(
id=f"chunk-{i}",
vector=vector,
payload={"text": chunk["text"], "source": "员工手册.pdf", "page": chunk["page"]},
)
# Step 3:检索
def retrieve(question: str, top_k: int = 5):
return vector_db.search(vector=embed(question), limit=top_k)
# Step 4:生成
def answer(question: str) -> str:
docs = retrieve(question)
context = "\n\n".join(
f"[{d['source']} P{d['page']}]\n{d['text']}" for d in docs
)
messages = [
{"role": "system", "content": "只根据【参考资料】回答。无依据则说明不知道。"},
{"role": "user", "content": f"【参考资料】\n{context}\n\n【问题】\n{question}"},
]
return client.chat.completions.create(
model="gpt-4o-mini", messages=messages, temperature=0.2
).choices[0].message.content
跑通后,用 10~20 个真实业务问题验证检索相关性。
5.2.4 典型反模式
将数百页 PDF 整份放入 Prompt → 截断丢内容、Token 暴涨、模型在无关文本中迷失。应切块 + 检索。
5.2.5 上线后的优化方向
| 优化手段 | 针对问题 | 做法 |
|---|---|---|
| 切块策略 / Overlap | 粒度不当、边界断句 | 按标题切分;相邻块重叠 50~100 Token |
| 元数据过滤 | 检索到过期/错部门文档 | 标注部门、版本、日期,检索前 filter |
| Hybrid 混合检索 | 向量对编号、专有名词不敏感 | BM25 关键词 + 向量,结果合并 |
| Rerank 重排序 | Top-K 相关性不足 | 二次打分取最优 3~5 段 |
| Query 改写 / Multi-Query | 用户提问过短或口语化 | 改写或生成多 query 合并检索 |
| 强制引用 | 模型未严格依资料作答 | 要求标注引用,无引用拒答 |
| 缓存 | 重复检索成本高 | 热门问题缓存检索结果 |
| 评估集 | 调参效果不可量化 | 定期跑召回率与忠实度 |
5.2.6 如何评估 RAG 效果
建议维护测试集,并关注两类指标:
- 召回(Retrieval):正确段落是否出现在 Top-K 检索结果中
- 忠实度(Faithfulness):生成答案是否严格基于检索内容,有无编造
排查路径:
- 检索无正确段落 → 优化切块、Hybrid、Rerank、Query 改写
- 检索正确但答案偏离 → 加强 Prompt、降 temperature、强制引用
- 检索到过期文档 → 元数据过滤
系列第 9~13 篇将分模块实战 RAG 全链路。
5.3 第三层:Agent 与 Function Calling
目标:
在授权范围内查询、计算与执行操作。
适用场景
答案不在文档而在实时系统中:查工单状态、汇总数据库指标、发送通知等。RAG 解决静态知识;Agent 解决动态数据与操作。
典型流程
用户提问 → LLM 输出 Function Calling(工具名 + 参数)
→ 应用代码执行 API/查询 → 结果回填 → LLM 组织自然语言回复
工具定义示例
{
"name": "get_ticket_status",
"description": "根据工单号查询状态(只读)",
"parameters": {
"type": "object",
"properties": {
"ticket_id": {"type": "string", "description": "工单号"}
},
"required": ["ticket_id"]
}
}
模型只生成调用意图,执行权在应用代码——便于权限、审计与限流。
多步 Agent 示意
用户:「对比工单 8891 和 8892 的状态,把差异发给负责人。」
1. 调用 get_ticket_status("8891")
2. 调用 get_ticket_status("8892")
3. 模型对比结果,生成摘要
4. (可选)调用 send_notification,需用户确认后执行
设计原则
- 最小权限:只开放完成任务所需的工具,能只读就不给写
- 写操作需确认:涉及状态变更、消息发送时,引入人工或二次确认
- 全程可审计:记录工具选择、参数与 API 返回,便于事后追溯
- 失败可解释:工具超时或异常时,向用户返回明确提示,避免 silent fail
MCP(Model Context Protocol) 是工具层的标准协议,便于多套 Agent 客户端复用同一工具服务,减少重复集成。系列第 16 篇将做专题讲解。
5.4 第四层:工程化与可运维
目标: 可观测、可控制、可迭代。
常见问题
| 现象 | 建设项 |
|---|---|
| 响应变慢 | 历史裁剪、缓存、异步 |
| 成本上升 | Token 监控、限流、热门问题缓存 |
| 答案被投诉 | 反馈入口 + request_id 追溯 |
| 模型故障 | 多模型路由、降级文案 |
| 调参无依据 | 固定回归测试集 |
建议日志字段
{
"request_id": "uuid",
"model": "gpt-4o-mini",
"prompt_tokens": 1200,
"completion_tokens": 340,
"latency_ms": 2300,
"retrieval_ids": ["chunk-12", "chunk-45"],
"tool_calls": []
}
上线前自检清单(简版)
- System Prompt 与拒答规则已定义
- 对话类场景已开启 stream
- Token 用量与费用有监控/告警
- 每个请求有 request_id,可回放 messages 与检索结果
- 有 10+ 条业务回归测试集
- 主模型不可用时有降级方案
- 涉及写操作的 Agent 工具有人工确认
6. AI 应用 vs 传统应用:架构思维为什么要换
很多开发者第一次做 AI 产品时,会不自觉沿用传统 Web 应用的思路——写一堆 if/else 兜底、指望「测试通过就能稳跑一年」。但 AI 应用的底层逻辑不同,如果思维不切换,容易在设计和排期上吃亏。

6.1 核心差异:从「确定性」到「概率性」
传统应用:结构化输入 → 确定性业务逻辑 → 确定性输出
AI 应用: 自然语言输入 → 概率性模型推理 → 可变自然语言输出
用一个具体例子感受差异:
场景: 用户查询「差旅报销上限」
| 维度 | 传统应用 | AI 应用(裸 API) |
|---|---|---|
| 输入 | 固定表单字段(类型、金额、部门) | 自然语言,问法多样 |
| 处理 | 查数据库 SELECT limit FROM policy WHERE dept=? |
LLM 根据训练数据推理 |
| 输出 | 固定格式,同一输入同一结果 | 措辞可变,可能编造 |
| 出错时 | 堆栈指向某行代码 | 很难说清是 Prompt、检索还是模型本身 |
传统应用的 bug 是「逻辑写错了」;AI 应用的「bug」可能是「检索没召回到正确段落」「Prompt 约束不够」「模型幻觉」—— 排查链路完全不同。
6.2 同一功能,实现路径差在哪里
以「智能客服」为例,对比两种架构:
传统路径:
用户点选意图(退款/物流/发票)→ 规则引擎匹配 FAQ ID → 返回预设答案
优点:可控、可测、成本低。缺点:用户必须按菜单操作,覆盖面受限于人工维护的 FAQ 条目数。
AI 路径:
用户自然语言提问 → LLM 理解意图 →(可选)RAG 检索知识库 → 生成回答
优点:表达自由、维护 FAQ 的人力成本下降。缺点:需要处理幻觉、检索质量、输出一致性,且 Token 按次计费。
实际产品中常见做法是 混合架构:高频、高风险、需精确合规的问答仍走规则;长尾、表述多样的问题走 AI + RAG。这不是「全 AI」或「全传统」的二选一,而是按场景分层。
6.3 为什么需要额外五层能力
正因为输出具有概率性,AI 产品不能只有「前端 + LLM API」两层,通常要叠加:
| 层级 | 作用 | 缺少时会怎样 |
|---|---|---|
| 约束层 | Prompt、JSON Schema、拒答规则 | 输出格式漂移,不该答的也答 |
| 证据层 | RAG 引用、工具返回的原始数据 | 用户无法核对,投诉时无法自证 |
| 行动层 | Function Calling、Agent、MCP | 只能聊天,无法查实时业务数据 |
| 护栏层 | 权限、人工确认、敏感词、审计 | 模型误调写接口,造成真实业务损失 |
| 观测层 | 日志、追踪、评估、成本看板 | 出问题只能盲改 Prompt,无法量化迭代 |
可以把它理解成:传统应用靠 业务代码 保证正确性;AI 应用靠 模型 + 多层工程约束 把概率性输出「收敛」到可接受范围。
6.4 对测试与排期的影响
测试方式变了。 传统功能测「输入 A 必得输出 B」;AI 功能需要 回归测试集 + 抽样评估,关注「大多数情况是否可接受」,而非 100% 逐字匹配。
排期也要重新估。 「接个 API 两天搞定」往往只覆盖了 Demo;若包含 RAG 建库、Agent 工具对接、日志与监控,周期通常按周甚至按月计。向业务方同步预期时,建议明确:模型能力 ≠ 产品交付周期。
运维职责也在扩展。 除了服务存活监控,还要盯 Token 用量、检索命中率、模型供应商 SLA、Prompt 版本变更——这些在传统 CRUD 应用里往往不存在。
6.5 一个简化的架构对照
【传统 Web 应用】
用户 → API 网关 → 业务服务 → 数据库 → 固定响应
【AI 应用(典型生产形态)】
用户 → API 网关 → 应用服务
├─ Prompt 组装 / 上下文管理
├─ RAG 检索(向量库)
├─ Agent 工具调用(业务 API)
├─ LLM API(主 / 备)
└─ 日志 / 评估 / 限流 / 缓存
如果你正在画系统架构图,可以先问自己四个问题:
- 答案从哪里来?(模型内置 / RAG / 工具查询)
- 输出怎么约束?(Prompt / Schema / 拒答)
- 出错怎么查?(request_id / 检索回放)
- 成本怎么控?(Token 监控 / 缓存 / 限流)
四个问题有明确答案,才接近「可上线」而非「能演示」。
7. 常见认知误区:为什么 Demo 顺利、上线却翻车
下面这些误区在实际项目中反复出现。它们不一定来自技术能力不足,很多时候是 对 AI 产品形态的预期偏差。
误区 1:「接入 API = 完成 AI 产品」
典型想法: 聊天界面已经做好,API 也调通了,产品就完成了。
实际情况: 聊天 UI 只是交互层。企业场景还需要:私有知识(RAG)、实时数据(Agent)、权限与审计(护栏层)、日志与成本治理(观测层)。缺少这些,系统只能算「能对话的 Demo」,无法承接真实业务流量。
正确做法: 用本文的四层能力框架做差距分析,按业务场景优先级逐项补齐,而不是在 UI 上继续打磨。
误区 2:「Prompt 调一次就好,后面不用管」
典型想法: 上线前花两天写好 System Prompt,测试几个样例没问题,就可以冻结了。
实际情况: 用户表达方式极其多样。同一个意图,可能有几十种问法;业务文档更新后,原先合适的 Prompt 可能引导模型引用过期信息。没有 回归测试集,Prompt 的每次修改都是「凭感觉」。
正确做法:
- 维护 10~50 条真实业务问题作为测试集
- 每次改 Prompt、换模型、调 RAG 参数后批量跑一遍
- 记录通过率变化,而不是只凭几个手动挑选的样例下结论
Prompt 不是「写完的文档」,而是需要 版本管理和持续评估 的配置项。
误区 3:「文档上传完成,RAG 就做好了」
典型想法: 把 PDF 扔进知识库,向量化完成,RAG 功能就上线了。
实际情况: 上传只是起点。实践中常见问题包括:
- PDF 解析丢表格、丢标题层级,切块后语义断裂
- 向量检索对工单号、SKU 等精确词不敏感,检不到正确段
- Top-K 召回了相关段,但模型未严格依此作答(生成层问题)
正确做法: 按 5.2.5 节的优化清单逐项排查;用 召回率 和 答案忠实度 两个指标量化效果,而不是用「感觉还行」来判断。
误区 4:「Agent 自主性越高越好」
典型想法: 给模型足够多的工具,让它自己规划、自己执行,才体现 AI 能力。
实际情况: 生产环境需要的是 可控的自动化。模型可能选错工具、传错参数、在权限边界外执行写操作。一旦涉及改订单、发邮件、调支付接口,后果是真实的业务损失,而不是「回答不好看」那么简单。
正确做法:
- 遵循最小权限:能只读就不给写
- 写操作必须人工或二次确认
- 每次工具调用记审计日志
- 限制单轮可调用的工具数量与循环次数
Agent 的价值在于 减少人工操作步骤,不在于 把决策权完全交给模型。
误区 5:「先上线抢时间,工程化以后补
典型想法: 先把功能推出去占坑,监控、限流、成本告警以后再加。
实际情况: AI 应用的「后期补课」成本往往更高:
- 没有 Token 监控,一次推广活动或爬虫刷接口可能让账单暴涨
- 没有 request_id 追溯,用户投诉「答错了」时无法复盘,只能反复改 Prompt 碰运气
- 没有 限流,单个异常用户或死循环 Agent 调用可能拖垮下游 API
正确做法: 至少在第一版上线时具备:基础日志(含 request_id)、
Token 用量统计、主模型降级方案、10 条以上回归测试集。完整监控可以迭代,但 不可观测 和 不可追溯 不应成为默认状态。
误区 6:「模型越强,产品体验越好」
典型想法: 回答不好就换更大的模型,问题自然解决。
实际情况: 很多线上问题出在检索、Prompt、工具对接,而非模型智商。一个常见排查顺序是:
回答错误 → 检索结果是否包含正确段落?
→ 有:检查 Prompt 约束与 temperature
→ 无:检查切块、Hybrid、Rerank、Query 改写
→ 仍不行:再考虑换 Embedding 或生成模型
盲目升级模型会显著抬高 Token 成本 和 延迟,但未必解决根因。先用日志和测试集定位问题层级,再决定要不要换模型。
8. 本篇练习建议
建议按难度递进完成,预计耗时 30~60 分钟:
- 基础:为现有 Demo 补充 System Prompt,将
temperature设为 0.2,同一问题提问 5 次,观察输出稳定性变化 - 基础:在日志中记录每次请求的 Token 用量、延迟与完整 messages(注意脱敏)
- 推荐:整理 10 条真实业务问题作测试集,保存为
eval_questions.json,改 Prompt 前后各跑一遍并记录差异 - 进阶:选取一份真实 PDF,按 5.2.3 节流程实现最小 RAG,检查 Top-5 检索结果是否与问题相关
9. 下篇预告
第 02 篇:AI 应用技术栈全景图 —— 梳理模型层、编排层(LangChain / LlamaIndex 等)、数据层与应用层的组件选型与组合方式,帮你画出自己的系统架构图。
关注作者,获取后续更新
本系列《AI 应用开发实战课》将在以下平台同步更新,欢迎关注追更:
- 小红书:@水无月sama
- 知乎:@水无月sama
- CSDN:@再让我睡两分钟
- 微信公众号:微信搜索「介就是AI」
10. 讨论
你当前项目主要卡在哪一层?稳定输出 / RAG / Agent / 工程化?欢迎在评论区说明,后续案例将优先覆盖高频场景。
#AI应用开发 #大模型 #RAG #Agent #LLM #程序员
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)