本系列是《ByteFisher AI 编程实战》的工程化续篇。前一个系列讲的是”怎么用好 AI 编程工具”,从概念到工具再到 Agent 应用,覆盖了 21 个主题。但那些内容停留在”能用”的层面:调通一次 DeepSeek API、跑通一个 RAG 演示、写完一个 Agent 示例,距离”生产级”还差着十万八千里。
本系列 12 篇要解决的是另一类问题:当 AI 能力真正成为业务系统的一部分时,怎么把它做成可靠、可观测、可度量、可控成本的工程。
和纯理论文章不同,本系列全程以博客真实运行的 ByteBot(AI 问答助手)和 钓鱼日记自动生成流水线 作为落地案例。每篇文章都会拿着真实代码、真实数据说话,给出改造前后的对比。本篇是总纲,先把工程全景讲清楚。
一、LLM 应用工程的四层架构
任何一个把大语言模型接进生产环境的系统,无论业务形态如何,都可以抽象成四层:
1 | ┌────────────────────────────────────────────────┐ |
理解这四层,是工程化的第一步。绝大多数”AI 应用不稳定”的问题,根源都不在模型本身,而在四层的边界上:
- 模型层问题:Token 成本失控、超时、限流、偶发幻觉、长上下文丢信息。
- 编排层问题:Prompt 写死、检索质量差、上下文爆炸、Agent 死循环。
- 应用层问题:会话状态管理混乱、并发竞争、无降级方案、无埋点。
- 数据层问题:索引过期、无评测集、无法度量回答质量。
本系列 12 篇,本质上是自底向上 + 自顶向下各扫一遍:0203 篇修模型层和上下文,0405 篇做检索与评测,06 篇补本地推理,07~10 篇做编排与 Agent,11 篇加可观测性,12 篇收口成完整闭环。
二、ByteBot 现状架构解剖
先看博客里真正跑着的 ByteBot 是什么样子。它在生产环境由两部分组成。
2.1 前端:source/js/ai-assistant.js(999 行)
前端承担了三件事:UI 交互、本地会话管理、客户端检索兜底。
关键机制一览:
| 机制 | 代码位置 | 说明 |
|---|---|---|
| 会话管理 | maxHistoryTurns: 6 + sessionStorage |
每次请求只带最近 6 轮,防止上下文爆炸 |
| Token 预估 | estimateTokens() |
中文按 1.5 字/token、英文按 4 字符/token 估算 |
| 客户端 BM25 | rankArticles() |
本地用 BM25 算法给文章排序,k1=1.5, b=0.75 |
| 意图识别 | isBlogRelatedQuestion() |
关键词表 + 正则双重判定 |
| 降级兜底 | showFallbackRecommendations() |
API 挂了时,用本地索引推荐文章 |
| 链接校验 | validateLinks() |
回答里的链接必须存在于索引中,防幻觉链接 |
特别注意 truncateMessages():它从尾部往前累计 token,超过 3000 就截断,但永远保留第一组 user/assistant。这是最简单粗暴的”上下文工程”——后面第 03 篇会升级它。
2.2 后端:api/chat.js(526 行,Vercel Serverless)
后端是一个无状态的 serverless 函数,核心链路:
1 | 客户端 POST /api/chat |
最值得一提的设计是 buildAdaptiveSystemPrompt():system prompt 不是写死的,而是根据当前问题意图和检索结果动态拼接的——意图是博客相关时,注入文章候选列表并强调”严禁编造”;是闲聊时,则切换成”别强行推荐文章”模式。这已经算是非常朴素的”提示词路由”。
2.3 数据层:api/posts-index.json
Hexo 构建时生成的静态索引,共 260 篇文章,每篇含 title / url / date / tags / categories / headings / summary / textForSearch 等字段。前端和后端都依赖它做检索。
它的定位是一个轻量级 BM25 全文索引——把中文拆成 bi-gram 和 tri-gram 再算 IDF。这个方案对 260 篇的规模完全够用,但检索质量天花板很低,第 04/05 篇会把这里升级成真正的混合检索 + 向量方案。
三、逐层痛点诊断
对照四层架构,ByteBot 现状的每一层都有明确短板。把痛点列出来,就是整个系列要填的坑。
3.1 模型层
- 无重试机制:
fetch一次失败直接返回错误,Vercel 无冷启动重试、无 429 退避。高峰期 DeepSeek 偶发 429/5xx,用户只能手动点重试。 - 无缓存:相同问题每次都重新调用 API 付费。ByteBot 的高频问题(”有哪些 Unity 教程”)重复消费 Token。
- 超时一刀切:所有请求固定 30 秒,长回答(多篇文章推荐 + 解释)经常在流式中间被掐断。
- 成本不可见:没有任何埋点统计每轮对话消耗的 Token 和费用。无法度量就无法优化。
3.2 编排层
- Prompt 是”打补丁”式演进:
chat.js和ai-assistant.js里各维护一套 system prompt,逻辑重复且版本不可追溯。没有 Prompt 版本管理,改坏了无法回滚。 - 无结构化输出:DeepSeek 返回纯 Markdown 字符串,靠前端
marked + DOMPurify渲染。一旦模型输出格式漂移(比如链接写进代码块、标题层级错乱),前端就要打补丁——preLinkArticles()、validateLinks()、norm()这些函数都是为了”修正模型的乱输出”而存在。 - 检索是单路 BM25:无语义、无重排、无查询改写。”五子棋”搜”棋类游戏”永远搜不到。
3.3 应用层
- 会话记忆在 sessionStorage:换设备即失忆,无持久化。
- 无并发控制语义:
debounceInterval: 1000只是防抖,用户连点仍可能发出重复请求。 - 无埋点追踪:只有
localStorage里三个计数器(opens/sends/errors),看不到单次对话的质量。
3.4 数据层
- 无评测集:没有人记录”哪些问题是读者真实会问的”、期望答案是什么,回答质量完全不可量化。
- 索引与线上文章脱节:posts-index 是构建时快照,新增文章后依赖 CI 重建,期间 ByteBot 会推荐已下线的旧文章或漏掉新文章。
这些痛点不是 ByteBot 独有的,任何从 demo 走向生产的 AI 应用都会踩一遍。本系列 12 篇就是按上面 3.1~3.4 逐条修复。
四、编排框架选型
做 Agent/多 Agent 之前,必须先回答”要不要引入框架、引入哪个”。2026 年的生态下,主流选择有四类。
4.1 四类方案对比
| 方案 | 代表 | 编程模型 | 学习成本 | 可控性 | 适用规模 |
|---|---|---|---|---|---|
| 图编排框架 | LangGraph | 显式状态图(节点+边+检查点) | 高 | 高 | 复杂状态流、需持久化 |
| 角色协作框架 | CrewAI | 声明式(Role/Goal/Task/Crew) | 低 | 中 | 多角色协作、任务分解 |
| 低代码平台 | Dify / Coze | 可视化编排 + 内置 RAG | 低 | 低 | 快速搭建、非深度定制 |
| 自研编排 | 手写 async 流程 | 完全自由 | 中 | 最高 | 流程简单、强领域定制 |
4.2 选型决策树
1 | 流程是否需要显式状态管理 / 分支循环 / 断点续跑? |
我的判断:ByteBot 的核心流程(意图→检索→生成→渲染)目前是顺序结构,自研 + 轻量状态机完全够用,强行上 LangGraph 是过度设计;但博客的钓鱼日记流水线(策划→写作→校对→SEO 多角色)和多 Agent 协作场景,恰恰是 CrewAI/LangGraph 的主场。所以本系列 07~10 篇会把两个框架都剖析一遍,再回到”是否引入”的决策上。
4.3 一个容易被忽视的原则
框架只解决流程控制,不解决质量。 无论选哪个框架,检索质量、Prompt 质量、评测闭环仍然是决定性因素。框架选型的正确姿势是:先想清楚”流程图长什么样”,再选能把这个图画出来的最小框架——这个原则贯穿 07~10 篇。
五、本系列 12 篇改造路线图
| 篇 | 主题 | 对应痛点 | 落地案例 |
|---|---|---|---|
| 02 | 调用层工程化 | 3.1 全部 | ByteBot 接入 DeepSeek 的重试/缓存/成本 |
| 03 | 上下文工程与结构化输出 | 3.1/3.2 | 会话记忆升级 + 检索结果结构化 |
| 04 | RAG 优化(上):检索质量 | 3.2 检索 | 260 篇文章的混合检索知识库 |
| 05 | RAG 优化(下):评测迭代 | 3.4 无评测 | RAGAS + 真实评估集 |
| 06 | 本地模型量化与推理优化 | 3.1 降级 | 本地模型做 ByteBot 兜底 |
| 07 | LangGraph 源码剖析 | 编排选型 | 文章分析 Agent |
| 08 | CrewAI 源码剖析 | 编排选型 | 钓鱼流水线改写 |
| 09 | 自研 MCP Server | 工具层 | TiDB 鱼获查询 MCP |
| 10 | 多 Agent 编排工程化 | 编排工程化 | 钓鱼日记多 Agent 流水线 |
| 11 | 可观测性与评测 | 3.3 无埋点 | Langfuse 追踪 ByteBot |
| 12 | 综合实战:ByteBot v2 | 全量收敛 | 完整重构 + 前后对比数据 |
路线图的设计逻辑是先打地基再盖楼:0205 篇先把模型层、上下文、检索、评测这四块地基打牢;06 篇补兜底;0710 篇在中层做编排能力;11 篇从观测角度给前面所有工作装上”仪表盘”;12 篇一次性收口。
六、本章小结
- LLM 应用工程可抽象为应用层/编排层/模型层/数据层四层,90% 的不稳定问题出在层与层的边界,而非模型本身。
- ByteBot 的现状:客户端 BM25 检索 + 动态 system prompt + SSE 流式 + 会话截断,已经具备了朴素的工程雏形,但缺少重试/缓存/结构化输出/评测/观测这五块生产级拼图。
- 编排框架选型决策树:复杂状态流用 LangGraph,多角色协作用 CrewAI,简单顺序流程用自研,追求快速验证用 Dify。
- 框架只解决流程控制,不解决质量;质量来自检索、Prompt、评测三个闭环。
- 本系列 12 篇按”地基→中层→观测→收口”的顺序推进,每篇都绑定博客真实项目。
下一篇进入第一块地基:调用层工程化。我会基于 api/chat.js 的真实代码,把重试、限流、缓存、成本建模逐项落地,并给出”为什么 serverless 函数更需要这些”的分析。
本系列持续更新中,每周一篇。