跳转至

05. AI 应用工程

五、AI 应用工程

AI 应用最容易把人带偏的地方,是它表面上看起来像在学模型,实际在做的却还是系统工程。你面对的不是一个单独的推理接口,而是一条会引入不确定性、时间维度和真实副作用的服务链。用户提问只是入口,后面还要经过任务定义、上下文装配、模型决策、工具执行、状态更新、结果收口和评测回归。只要这条链里任何一段没有站稳,系统就会表现成“模型不够聪明”,但真正的问题往往根本不在模型本身。

所以这一章不把 Prompt、memory、streaming、后台任务、幻觉、安全这些词拆成互不相干的清单,而是把它们放回同一条工程主线里。读完以后,最关键的收获不是会多背几个概念,而是能把一次 AI 请求从进入系统到最终收口完整讲出来,知道每一层到底在解决什么问题,出问题时先查哪里,为什么很多线上故障其实不是 prompt 文案写坏了,而是上下文、状态和治理边界先失控了。

flowchart LR A["用户请求"] --> B["任务定义与权限边界"] B --> C["上下文装配"] C --> D["模型决策 / 工具建议"] D --> E["工具执行与结果标准化"] E --> F["状态更新 / 摘要沉淀"] F --> G["流式返回或后台收口"]

总判断:AI 应用是多了概率节点的后端系统

把 AI 应用看稳的一句话,是它本质上还是后端系统,只是中间多了一段概率推理。普通后端的主干是请求、状态、数据和返回。AI 应用没有脱离这条主干,只是把一部分理解、生成和局部决策交给了模型。问题也正出在这里。模型擅长根据上下文给出自然语言判断,却不天然可靠、不天然可解释,也不天然知道你的权限、租户、版本和业务边界。一旦把它接进服务,你的工作重点就不再是“怎样让它显得更聪明”,而是“怎样让系统在它答偏、超时、重复、误调工具时依然可控”。

所以真正决定系统能不能上线的,往往不是模型参数量,而是结构化约束、状态分层、取消传播、错误分类、人工接管、trace 和评测闭环。只要这套工程框架没有立起来,AI 能力越强,系统只会越容易把错误放大成真实事故。相反,如果边界和治理做得扎实,模型偶尔不够理想,系统也还有足够多的收口手段。

复杂度按这条线升级最稳:单次模型调用,接着是检索和结构化输出,再往上才是多步 workflow,最后才轮到真正的 agent runtime。很多团队一上来就把问题抬到 Agent,结果缺的其实只是更干净的上下文、一个可校验的 schema,或者一条能解释清楚的轻量 workflow。

AI 框架分层:Spring AI、LangChain、LangGraph、Eino 各在接哪一层复杂度

框架选型如果只按“社区热度”来比,几乎一定会答偏。更直接的问法仍然是:这套框架在替我接哪一层复杂度。Spring AI 更像 SpringBoot 生态里的模型适配与应用集成层。它把 ChatClientAdvisor、结构化输出、Tool Calling、VectorStore 和观测钩子这些对象显式化,最适合已经有成熟 Spring 宿主服务、配置中心、依赖注入和治理基线的团队。LangChain 更像能力拼装层,擅长把 prompt、retriever、tool、parser 和链式组合快速接起来,适合原型期或能力探索期,但一旦状态持久化、checkpoint、interrupt/resume 成为主问题,单纯的链式抽象就不够了。LangGraph 继续往上接的是显式状态图和 durable execution,适合多步长任务、人工插入点和恢复路径都必须正式建模的场景。Eino 则更像 Go 生态里的组件抽象加运行时分层,强调 Componentscompose、agent runtime、callback 和 interrupt/resume 的分工,适合已经确定宿主是 Go 服务、又不想把模型调用、工作流和 Agent loop 混成一层的系统。

也正因为它们站位不同,默认切换顺序通常不是“哪个更强就上哪个”,而是“问题先卡在哪一层”。如果你只是要在现有 Spring 服务里接模型、结构化输出和轻量 Tool Calling,Spring AI 往往已经够用。如果你需要把大量 AI 原语快速拼装成多种原型链路,LangChain 的表达力更高。如果真正难点变成显式状态、checkpoint 和中断恢复,就该往 LangGraph 或 Go 侧的图运行时靠。如果你的主宿主就是 Go 服务,希望模型、工具、graph 和回调都留在 Go 的工程边界里,Eino 往往比临时跨语言拼接更稳。面试里只要先把“宿主生态、状态复杂度、恢复需求、治理边界”这四件事讲清,框架题就不会再像站队题。

多模型 provider adapter 与多租户模型路由

多模型支持真正要先做的,不是堆一串 SDK,而是先抽一层 provider adapter,把上层真正需要的能力压成稳定接口,例如 GenerateStreamEmbedRunToolsModerate。这样业务层看到的是“我现在要流式生成”或“我现在要做 embedding”,而不是某一家厂商的请求体字段。一旦这层没收住,后面做模型切换、灰度和成本治理时,系统里会到处散着 provider 方言,最后连 trace 和错误分类都很难统一。

多租户场景里,这层还要继续变成模型路由器。更直接的路由键通常至少包含 tenant_iduser_tiertask_typerisk_levelmodality。租户 A 可以默认走高质量闭源模型,租户 B 可能要求私有化部署,某些高风险工具调用前还要强制切到更直接的分类或审核模型。这里最容易犯的错,是把“当前默认模型”写成全局可变变量,然后让所有租户共用同一份运行时配置。更成熟的实现通常会让每个请求在入口处拿到一份只读 policy snapshot,把租户可用模型、限额、工具权限和缓存策略一起冻进本次请求。配置热更新时,只替换新请求读取到的快照,在途请求继续沿旧快照执行。这样才能真正做到“热切换互不影响”,而不是某个租户改了模型,其他租户的在途请求也跟着漂移。

多模态接入为什么不等于直接上多模态大模型

很多人一听到图像识别、图文问答或票据理解,就条件反射地说“直接用多模态大模型”。这在小规模、低吞吐、强调开放式理解的场景里当然可行,但工业系统默认不这么起步,原因很现实。第一,多模态模型成本更高、延迟更长。第二,结构化字段抽取、稳定引用和批量离线建索引并不一定比 OCR/版面理解/结构抽取 + 文本检索 更稳。第三,很多业务真正要的是“把图片里的字段、表格、编号和位置保真地还原出来”,而不是让模型自由描述图像内容。更直接的链路通常是:文件或图片先进入对象存储和媒体元数据层,再走 OCR、版面解析、表格结构抽取或专用 CV 模块,把可检索的文本、字段和区域框先提出来。只有在开放式视觉理解、跨模态推理或者局部歧义仍然很强时,才在后面补多模态模型做精读或 disambiguation。

主链路:一次 AI 请求从哪里开始,到哪里收口

一条能上线的 AI 请求,至少要经过五个连续阶段。第一阶段是入口治理。系统先做鉴权、限流、trace、租户识别、幂等和请求级超时,再决定这次请求属于同步对话、流式返回还是后台长任务。第二阶段是请求装配。横切逻辑适合放在中间件里,例如鉴权、日志、trace、限流。模型客户端、检索器、租户上下文、当前用户身份、工具注册表这类请求级依赖,则更适合放在显式装配层或依赖注入层。这样做的意义不是追求框架技巧,而是把治理边界和业务依赖拆开,便于后面定位问题到底坏在入口层还是坏在业务链本身。

第三阶段是上下文组织。系统要决定本轮真正该给模型看什么:用户原话、最近几轮高相关消息、检索片段、结构化状态、工具返回和稳定规则各占多大比重。第四阶段才轮到模型和工具。模型负责理解任务、给出结构化输出或调用建议。服务端决定是否执行工具、怎样补齐可信字段、超时和重试策略怎么配、返回结果如何标准化。第五阶段是收口。这里包括流式返回、后台任务状态回写、摘要沉淀、引用兜底、trace 打点、成本归因和离线评测样本沉淀。少了最后这一步,系统就很难从一次执行里学到什么,只会重复犯同样的错误。

真实项目里,很多问题之所以难排查,就是因为团队脑子里没有这条完整链路。回答偏了时,他们会直接去改 prompt。流式断了时,他们只盯前端。长任务超时了,又只怀疑模型太慢。实际上更直接的思路是按链路拆:入口有没有正确传递取消信号,请求装配有没有把租户和权限带对,上下文是不是已经被旧状态污染,工具返回是不是没有结构化,最后模型是不是只是在坏材料上认真总结。只要顺着这条链拆层,排查就会稳定得多。

任务定义:Prompt Engineering、结构化输出和边界控制

Prompt Engineering 在工程里真正解决的,是任务定义,而不是修辞优化。一个成熟 prompt 至少要回答四件事:这次任务到底要做什么,哪些事实优先级最高,证据不足时应该怎样停下来,输出必须遵守什么契约。这里最重要的不是写得多像人,而是任务边界清不清楚,结果能不能被系统稳定承接。制度问答、意图分类、工具路由、结构化抽取看起来都是“问模型一个问题”,但它们需要的任务定义完全不同。如果没有先把目标、可用证据和停止条件写清楚,后面再堆多少 few-shot 和风格约束都只是补丁。

这也是 Prompt Engineering 和 Context Engineering 必须分开的原因。Prompt 负责规则、事实优先级和输出契约,决定模型该按什么制度回答、该不该拒答、结构化字段长什么样。Context 负责材料装配,决定这轮到底给模型喂哪些检索片段、摘要、状态和工具结果。线上很多问题看起来像 prompt 没写好,实际是 context 喂法出了问题。比如模型一直引用旧版制度,往往不是因为 prompt 没写“请使用最新版”,而是上下文里先把旧版本条款喂进去了。再比如模型总在回答里重复已经过期的中间结论,也常常不是 prompt 不够强,而是旧状态被原样带回了上下文。

如果要把这三层控制线讲得更硬一点,可以直接记成:Prompt 决定解释制度,Context 决定输入材料,规则/工作流决定执行边界。Prompt 的失效常表现为格式跑偏、拒答条件不稳、事实优先级没立住。Context 的失效常表现为证据喂错、旧状态残留、检索片段顺序不对。规则层的失效则表现为越权、误执行、审批漏拦和高风险动作没有被挡在语言层之外。很多团队线上排障喜欢先改 prompt,真正更直接的顺序通常是先查规则层,再查 context,最后才查 prompt。本质原因很简单:越往下越靠近系统真实边界,错误代价越高,也越不该交给语言层补丁。

结构化输出则是任务定义落地到系统边界的形式。只要模型输出需要进入工作流、数据库、工具调用、审计或评测链路,自由文本就不够稳了。更好的做法通常是把结果压成 schema 可校验的对象,例如把意图识别做成 intentneed_toolconfidence,把工具建议做成明确字段,而不是让模型说一段“我觉得用户想查报销单”。结构化输出的意义,不是为了让 JSON 好看,而是为了让服务端能拒绝、修复、重放和审计。越靠近系统边界,越不应该只相信模型“应该会按要求来”。

把 Prompt、Context 和规则或工作流约束放在一起比较,体系感会更清楚。Prompt 解决的是“模型该按什么制度思考和表达”,Context 解决的是“模型这一轮到底看见什么材料”,规则或工作流约束解决的则是“哪些边界根本不该交给模型裁量”。低风险、只读、结果主要用于展示的链路,通常可以先从 prompt 加 context 起步。一旦错误开始触碰权限、副作用、审批、金额、租户隔离或强审计要求,就应该把约束往确定性规则和工作流节点上提,而不是继续堆 prompt 文案。很多线上问题之所以越改 prompt 越乱,根因就是团队把本该写进状态机、校验器或审批层的硬边界,误放进了语言层提示里。

更直接一点说,复杂度升级最好遵循一条稳定控制线:单次模型调用 -> 结构化输出或检索增强 -> 顺序 workflow -> 动态 agent。如果问题只是“怎样让模型在稳定边界内输出更可承接的结果”,那就不该过早升级到 agent。只有当多步之间真的需要根据观察结果动态决定下一步,workflow 才会自然过渡到 agent runtime。

上下文组织:长对话的核心不是截断,而是状态建模

一旦请求不是单轮问答,而是多轮会话、长任务或带工具执行的流程,上下文工程就会比 prompt 更重要。最常见的误区,是把“上下文变长”理解成“把历史原样继续往里塞”。这样做短期内最省事,长期几乎一定失控。上下文越长,输入 token 越贵。无关历史越多,模型越容易被噪声带偏。旧状态如果不清理,还会在后续轮次持续污染结果。所谓长上下文会“遗忘”,很多时候不是模型忽然失忆,而是当前窗口里混入了太多旧结论、重复描述和不再相关的材料,重要的是证据被噪声淹没了。

更成熟的做法是把信息分层。最近几轮里和当前任务直接相关的消息与工具结果属于短期工作记忆。已经确认过、但不需要逐句保留的内容适合压成摘要。像当前单据号、最近一次工具结果、权限范围、当前审批节点这类事实,更适合提炼成结构化状态。用户长期稳定的偏好、术语映射和企业知识则应当持久化并按需检索,而不是每轮都常驻上下文。只有把“完整历史持久化”和“本轮可见记忆”分开,你才有可能同时保住可回放性和上下文干净度。

上下文压缩也应该讲成方法链,而不是一句“做个摘要”就结束。更直接的顺序通常是:先保留最近几轮和当前步骤强相关的原始消息,再把更早对话压成运行摘要,再把单号、审批节点、最近一次工具结果、未完成事项这类事实提炼成结构化状态,然后把稳定偏好、历史案例和长期知识回写到可检索记忆里,最后再对重复表达做去重和语义合并。如果中途还需要人工接手,最好额外保留一份面向交接的快照,把当前目标、已完成步骤、卡点和待确认事项单独写出来。这样压缩保留的是业务事实和执行状态,而不是机械省 token。

一个很实用的上下文预算顺序是:规则和系统约束 > 当前目标与结构化状态 > 最近强相关消息 > 检索证据 > 可选背景材料。这不是绝对公式,但它能逼你回答“如果 token 不够,到底谁先被删”。在真实系统里,最不该被摘要吞掉的通常是硬约束、权限边界、当前目标和未完成步骤。最先该被压缩的通常是寒暄、重复描述和已经被结构化状态覆盖的中间文本。只要把优先级反过来,模型就会在看起来“信息很多”的上下文里丢掉真正最关键的控制条件。

长文材料进入上下文时,也最好按“稳定度”和“执行价值”来装配,而不是按来源顺序整段塞进去。更直接的顺序通常是:先放系统规则和当前目标,再放结构化状态和最近一步的关键观察,再放与当前问题直接相关的检索证据,最后才补背景材料、历史说明和可选参考。只要把旧对话、大段网页、冗长工具结果和低价值日志和关键约束放在同一层竞争,模型的注意力就会被无关噪声吃掉,后面再强的长上下文能力也很难真正稳定。

把原样截断、摘要压缩、结构化状态、长期记忆检索和 checkpoint 放在同一层比较,会更容易知道什么时候该切方案。原样截断最轻,适合轮次不多、上下文仍然干净的对话。摘要压缩适合保留语义连续性,但一旦约束条件很多、摘要已经开始吞掉字段和边界,就该升级成结构化状态。长期记忆检索适合沉淀稳定偏好、术语映射和历史案例,不适合承载本轮临时中间态。checkpoint 则不是另一种摘要,而是为跨请求、长任务、人工接管和失败恢复准备的运行时快照。更直接的默认路线通常是先保最近轮次,再加摘要,再把高约束事实抬成结构化状态。只有当任务跨会话、跨执行周期或需要恢复点时,才应该从“堆历史”真正切到“建状态和 checkpoint”。

这里还有一个高频判断:用户问题含糊时,到底该先澄清,还是先检索再追问。更直接的标准不是交互习惯,而是缺失信息会不会改变执行风险和答案边界。如果缺的是对象身份、单号、时间范围、操作目标、租户范围这类关键槽位,猜错就可能误查、越权或误执行,那就应该先澄清。如果这轮本身是只读检索,系统又能低成本先缩小候选范围,例如先找相关制度版本、命中的知识库段落或可能对应的工单,再带着候选结果追问,体验通常更好。真正危险的是在缺失信息还会影响权限和动作边界时,系统依然直接往下执行。

代码理解类 Agent 会把这套上下文问题暴露得更明显。做 coding agent 时,真正有用的上下文通常不是把整个仓库原样拼给模型,而是把 AST、调用关系、依赖边界、数据库与 RPC 依赖、已有测试和运行入口这些结构信息提炼成更稳定的状态对象。否则模型看到的只是一堆长文本,很难稳定判断一个函数适不适合生成单测、应该在哪一层打 mock,或者某段逻辑到底依赖了哪些外部副作用。

执行组织:流式、后台任务、长输出和续跑

AI 请求一旦变成长响应或长任务,系统就不能再把它当普通同步接口处理。流式返回解决的是首字节体验和长生成过程的可见性,后台任务解决的是总时长和可靠恢复。像制度问答、摘要、简短解释这类单向输出,SSE 往往已经够用,因为它仍然是标准 HTTP,取消、鉴权和网关治理都更直接。只有在你明确需要前后端双向实时协作时,WebSocket 才会更合适。长文档分析、批量文件处理、多步 Agent 执行和长报告生成,则更适合放进后台任务系统,用任务 ID、状态回查、取消和恢复机制来治理,而不是死绑在一次同步请求里。

同步一次性返回、流式返回、后台任务和断点续跑,其实是在四种不同约束下做取舍。同步一次性返回最简单,适合延迟预算短、结果也短的链路。流式返回适合结果会持续展开、用户需要尽快看到第一段内容、但任务本身仍然绑定在一次请求里的场景。后台任务适合总时长长、涉及多步工具执行、可能等待外部事件或人工确认的任务。断点续跑则适合单次生成放不下、但任务目标本身仍可分段推进的场景。切换信号通常也很明确:如果用户最关心首字节体验,先上流式。如果任务会跨分钟甚至更久,或者需要恢复点与人工插入,就应该切后台。如果问题主要不是总时长,而是单次 token 上限,那就该优先设计可续跑的结构化进度,而不是把整条链升级成完整任务系统。

单次输出超过 max tokens 也不能只靠“让模型继续”一句话打发。默认做法是先把生成目标拆成可续跑的段落或章节,保存当前已经完成的结构化进度,例如大纲、已完成小节、引用候选、最后一段的逻辑位置,再带着这份状态继续生成。真正值得保存的不是最后几十个 token,而是“当前做到哪一步、还剩哪几段、已经用了哪些证据”。否则续跑时模型只会重复前文,或者因为缺乏位置感而接不上原有结构。

模型出现循环和重复回答时,也应该先按运行时思路排查。最常见的根因包括:目标不清,系统没有告诉模型什么时候该停。状态没有收束,同一条事实被多轮重新喂入。工具结果是自由文本,模型每一步都像在重新理解世界。停止条件太弱,导致“再查一次”总看起来像合理动作。或者输出里缺乏去重和分段约束,模型在局部上下文里不断自我接续。止损顺序通常也很固定:先明确停止条件和最大步数,再把关键中间结论收束成结构化状态,再对重复工具调用和重复内容做去重或相似度检查,最后才是通过 prompt 做语言层面的提醒。只要把顺序反过来,系统就会不停地用措辞问题掩盖运行时问题。

运行治理:并发、降级、重试、观测和成本

线上 AI 服务真正烧钱、烧延迟的地方,往往不只在模型本身,还在编排方式。很多请求不是单下游调用,而是要同时查多个 embedding 服务、多个检索通道、一个 rerank 服务,再加上一到两次模型推理。这种场景里,并发模式本身就是工程判断的一部分。如果这条链要求证据必须齐全,例如多个知识源必须全部取齐后才能综合判断,那么更适合等全量结果再汇总。如果这条链允许部分降级、竞速或超时兜底,例如多个模型取最快者、多个检索通道先到先消费,那么谁先返回先用谁通常更合理。关键不在于具体语言 API,而在于你先想清楚这条链是“全量收敛型”还是“竞速降级型”。

把等全量结果、谁先返回先消费、部分降级和竞速模型放在同一层看,最重要的是先区分业务语义。等全量结果适合证据必须齐全、少一路都会改变结论的链路。谁先返回先消费适合存在明显长尾、而且先到结果本身就有独立价值的链路。部分降级适合主路径必须稳住,但某些次要能力可以缺席的场景,例如先给主答案、再异步补引用或补附加分析。竞速模型则更像在同一任务上做速度和质量的动态折中,适合多个模型能力相近、成本和时延差异明显的场景。很多系统延迟居高不下,不是模型太慢,而是把本来可以先到先用的链路硬做成了全量收敛型。

这类并发治理最好再落到两类典型主链上理解。证据收敛型链路最典型的是制度问答、风控判断和审批建议,这类场景里任意一路缺失都可能改变结论,所以即使慢一点也要优先保证齐全。竞速兜底型链路最典型的是候选生成、多模型草稿、补充解释和辅助摘要,这类场景里先到结果本身就有使用价值,所以更值得做 race-to-first、早停和部分降级。真正成熟的系统会把这两类链路拆开治理,而不是所有下游一律“并发然后等齐”。

同样的判断也体现在并发模型上。对 embedding、检索、rerank 这类主要在等网络的下游,I/O 异步模型通常比一请求一重线程更省资源,因为真正稀缺的往往不是 CPU,而是连接、文件描述符、上下游取消的一致性和背压能力。大量等待型请求如果都靠线程阻塞去撑,最终浪费的是栈内存、调度开销和连接管理复杂度。事件驱动的 I/O 并发则更容易把超时、取消和限流统一收住。这一条不需要扩展成语言教程,你只要明白它背后的工程原因就够了。

观测和成本治理也必须在这一层一起看。一个成熟的 AI 服务至少要能回答:慢请求慢在哪一段,单位请求花了多少 token 和多少钱,哪些工具最常失败,哪些提示词版本引起了行为回归,断连取消有没有真正传到底层。没有 trace,只能看见“这次慢了”。没有结构化日志,很难按租户、工具名、模型版本归因。没有成本归因,业务方只会觉得“AI 很贵”,却说不清到底贵在历史太长、模型选太重,还是工具循环太多。

风险治理:幻觉、注入、越权、工具失败和人工接管

幻觉是 AI 应用里最容易被问到、也最容易答浅的问题。更准确的说法不是“模型会胡说”,而是“系统在证据不足、证据错误或状态污染时,仍然要求模型给出一个完整结果”。所以幻觉从来不只是模型问题,它同时可能来自检索失真、旧状态残留、引用兜底缺失、结构化字段设计过满,或者工具结果被模型二次脑补。减少幻觉最稳的路线,也不是单靠一句“请不要编造”,而是给系统建立证据优先的执行原则:关键事实先走检索或工具查询,证据不足允许明确停下来,引用由后端兜底,结构化输出只要求模型填它真正知道的字段。

安全与副作用控制同样不能停留在 prompt 层。用户输入、检索文档、网页内容甚至工具返回都可能是不可信输入,它们可以进入推理,但不能直接掌握控制权。这意味着权限、工具白名单、参数校验、敏感字段脱敏、高风险动作确认和审计日志必须在服务端实现,而不是交给提示词兜底。真正危险的不是答得不够漂亮,而是模型把越权数据带进工具、把只该建议的动作推进成真实写操作,或者在长任务里无限消耗资源。

安全护栏也应该讲成分层选型,而不是一个抽象名词。关键词或规则过滤的优点是便宜、稳定、可解释,适合兜住明显禁词、固定模板和已知高风险模式。分类器或安全模型更适合处理语义变体、隐蔽表达和长上下文综合判断,但代价是更重、更贵,也更需要评测。approval 或 human-in-the-loop 最适合高风险真实副作用,因为它最稳,但延迟和人工成本最高。后处理审计则适合做追责、抽检和离线回放,不能替代前置拦截。更成熟的默认顺序通常是规则先兜底、模型补语义、审批守高风险、审计做回放。如果系统已经开始出现越权、误操作或安全漏拦,继续只加关键词通常就不够了,应该及时把防线提升到模型判别或人工确认层。

如果一定要把护栏机制压成一句工程判断,可以记成:规则挡确定风险,模型识别语义风险,审批挡副作用风险,审计复盘系统性风险。这四层并不是互相替代,而是在拦四种不同故障。规则失败通常表现为被轻易绕过。模型失败通常表现为误判和漏判。审批失败通常表现为流程上根本没有把高风险动作拎出来。审计失败则意味着事故发生后连复盘样本都留不下来。把这四层混成一句“做安全过滤”,会让很多风险讨论停在表面。

工具失败后的职责边界也要分清。模型提示词负责让模型读懂错误语义,例如识别“参数不完整”“权限不足”“下游短暂不可用”这些类型,并选择回问、解释或等待。服务端负责错误分类、重试预算、降级策略和人工接管。参数缺失、schema 不合法、找不到主键,这类问题通常应该修参数或回问用户。429、短暂超时、网络抖动才适合在预算内重试。权限拒绝、审批缺失、业务状态不允许则应该直接收口或转人工,绝不能自动重放。真正成熟的系统,不是失败后只会“再试一次”,而是知道这次失败到底属于哪一类系统问题。

评估与取舍:什么时候该做成 AI,什么时候不该

AI 应用不是功能一多就更高级。规则稳定、字段清晰、审计要求极强、错误代价极高的流程,很多时候仍然更适合确定性工作流或传统规则系统。AI 更适合放在语言理解、信息组织、局部决策和多源信息汇总这些环节,而不是把所有业务判断都一股脑儿交给模型。真正成熟的取舍,不是“哪里能上模型就上”,而是先问:这一步的不确定性能否被护栏收住,收益是否足够覆盖延迟、成本和治理复杂度。

评估也必须围绕整条链,而不是只看回答像不像。至少要同时看任务完成率、追问率、人工接管率、工具成功率、单位请求成本、超时和取消命中率,以及高风险动作是否都经过了正确审批。只有这些指标一起看,你才能分清一次改动到底是提升了系统,还是只是让回答听起来更像样。AI 应用真正成熟的标志,从来不是 prompt 写得多花,而是读者或用户面对一条复杂链路时,系统仍然知道怎样把证据、状态、动作和风险稳稳收住。

如果系统开始进入代码理解、用例生成和开发时辅助,这套评估标准还要再补一层任务质量指标。单测生成不能只看覆盖率,因为覆盖率高并不等于测试质量好。更直接的指标通常还包括断言有效性、是否真正覆盖了边界条件、mock 是否合理、测试是否稳定不脆弱、是否引入了对数据库和 RPC 的隐藏依赖,以及失败样本里是不是集中出现在本来就不适合做单测的函数上。把这些质量维度补进去,讲义里的上下文工程和运行治理才真正落到了 coding agent 这类高频应用上。