引言:API 调通之后,真正的差距才刚开始

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/51372519c40249f3befa9dd8b7188af4.png#pic_center

很多团队的第一个 AI 应用,形态都很相似:前端一个对话框,后端调用 chat.completions 一类的 API,把 LLM(Large Language Model,大语言模型) 返回的文本直接展示给用户。演示阶段效果往往不错——老板点头、同事觉得「可以啊」。但上线第一周,问题通常会集中爆发:

  • 同一问题多次提问,输出不一致,用户质疑系统可靠性
  • 涉及内部制度、产品文档的问题回答错误——模型并未读取企业私有资料
  • 涉及实时数据的需求(如查询工单状态)出现幻觉(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 生成 答案。核心思路:只给与问题相关的片段,而非全量文档。

RAG工作原理

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,需用户确认后执行
设计原则
  1. 最小权限:只开放完成任务所需的工具,能只读就不给写
  2. 写操作需确认:涉及状态变更、消息发送时,引入人工或二次确认
  3. 全程可审计:记录工具选择、参数与 API 返回,便于事后追溯
  4. 失败可解释:工具超时或异常时,向用户返回明确提示,避免 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 应用的底层逻辑不同,如果思维不切换,容易在设计和排期上吃亏。

AI 应用 vs 传统应用架构对照

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(主 / 备)
                      └─ 日志 / 评估 / 限流 / 缓存

如果你正在画系统架构图,可以先问自己四个问题:

  1. 答案从哪里来?(模型内置 / RAG / 工具查询)
  2. 输出怎么约束?(Prompt / Schema / 拒答)
  3. 出错怎么查?(request_id / 检索回放)
  4. 成本怎么控?(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 分钟:

  1. 基础:为现有 Demo 补充 System Prompt,将 temperature 设为 0.2,同一问题提问 5 次,观察输出稳定性变化
  2. 基础:在日志中记录每次请求的 Token 用量、延迟与完整 messages(注意脱敏)
  3. 推荐:整理 10 条真实业务问题作测试集,保存为 eval_questions.json,改 Prompt 前后各跑一遍并记录差异
  4. 进阶:选取一份真实 PDF,按 5.2.3 节流程实现最小 RAG,检查 Top-5 检索结果是否与问题相关

9. 下篇预告

第 02 篇:AI 应用技术栈全景图 —— 梳理模型层、编排层(LangChain / LlamaIndex 等)、数据层与应用层的组件选型与组合方式,帮你画出自己的系统架构图。


关注作者,获取后续更新

本系列《AI 应用开发实战课》将在以下平台同步更新,欢迎关注追更:

  • 小红书:@水无月sama
  • 知乎:@水无月sama
  • CSDN:@再让我睡两分钟
  • 微信公众号:微信搜索「介就是AI」

10. 讨论

你当前项目主要卡在哪一层?稳定输出 / RAG / Agent / 工程化?欢迎在评论区说明,后续案例将优先覆盖高频场景。

#AI应用开发 #大模型 #RAG #Agent #LLM #程序员

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐