05. AI 应用工程
五、AI 应用工程¶
在软件工程体系中,人工智能(AI)及大语言模型(LLM)应用的开发本质上是在传统确定性后端系统中引入概率性推理节点的系统集成工程。AI 应用并非单一的模型推理接口调用,而是一条涉及非确定性输入输出、时序状态流转、高延迟网络 I/O 及物理副作用的复杂服务链。一次完整的 AI 请求需要经历请求治理、上下文动态装配、概率决策与规划、确定性工具执行、状态机更新、流式响应输出及运行指标沉淀等多个阶段。因此,AI 应用工程的核心目标是通过健壮的软件架构与工程化约束,将模型的非确定性行为收敛在安全的业务边界之内。
总判断:AI 应用是多了概率节点的后端系统¶
AI 应用的底层逻辑未脱离“请求(Request)- 状态(State)- 数据(Data)- 响应(Response)”的传统后端主线,其特殊性在于将部分逻辑理解、语义泛化及局部决策职能委托给概率性的模型推理。模型的局限性在于其输出天然缺乏确定性保证、可解释性弱,且无法自主感知多租户权限边界。因此,系统设计的重心在于如何构建防御性系统架构,确保当模型发生偏离、超时、重复执行或工具误调用时,系统级防御机制依然能够保障核心业务的健壮度。
在架构设计上,AI 应用系统的复杂度演进路线应遵循递进原则: 1. 单次模型调用(Single Inference):纯文本生成或基础翻译。 2. 检索增强与结构化输出(RAG & Structured Output):引入外部证据与 schema 校验约束。 3. 确定性工作流(Deterministic Workflow):通过逻辑分支控制多步执行。 4. 动态代理运行时(Dynamic Agent Runtime):赋予模型基于环境反馈进行闭环自主规划的能力。
过早引入复杂的自主 Agent 架构通常是工程反模式,应优先通过优化上下文装配、强化 Schema 校验或构建轻量工作流节点来收敛系统行为。
AI 框架分层:Spring AI、LangChain、LangGraph 与 Eino 的复杂度承载¶
框架选型应基于业务系统所在的宿主生态、状态复杂度、中断恢复需求及运行时治理边界进行理性评估:
- Spring AI:专为 Java 与 Spring 生态设计的企业级模型适配层。它将 ChatClient、Advisor、结构化 Parser、Tool Calling 及 VectorStore 抽象为 Spring 标准 Bean,适合已有成熟 Spring 工程基线、强依赖依赖注入(DI)与配置中心治理的企业级团队。
- LangChain:擅长快速组装 Prompt、Retriever、Parser 等组件的能力组装层。适合原型开发与探索性链路构建,但在面对复杂状态持久化及长周期任务中断恢复时,其线性链式抽象(LCEL)往往受限。
- LangGraph:针对复杂多步长任务设计的状态图运行时。引入 Checkpoint 和持久化状态机机制,支持动态循环、人工介入(Human-in-the-Loop)以及运行中断与恢复(Interrupt & Resume),适合对执行路径有严苛状态流转要求的场景。
- Eino:Go 语言生态的高性能组件抽象与图形化编排框架。它通过强类型的 Components 抽象、Compose 运行时及完善的 Callback 钩子,为高并发 Go 后端服务提供了原生、低延迟的模型编排与 Agent 运行支撑,避免了多语言拼接带来的运维成本。
多模型 provider adapter 与多租户模型路由¶
为防止底层模型厂商(Provider)的专属 SDK 及 API 规范对业务层造成代码污染,架构设计上必须抽象出统一的模型适配层(Provider Adapter),将模型能力收敛为高度统一的底层契约接口:
- Generate(ctx, req):标准文本/结构化生成。
- Stream(ctx, req):流式增量生成。
- Embed(ctx, req):多模态向量化。
- RunTools(ctx, req):工具编排调用。
适配层之上应架设多租户模型路由器(Multi-Tenant Model Router)。路由决策键应由 tenant_id(租户)、user_tier(用户等级)、task_type(任务类型)、risk_level(安全风险级)等维度复合构成。为保障高并发下的稳定性,租户路由策略应在请求入口处被冻结为只读的 Policy Snapshot(策略快照) 并随 context.Context 传播,实现在途请求与热更新配置的逻辑隔离,防止配置漂移导致瞬态不一致。
多模态接入为什么不等于直接上多模态大模型¶
多模态大模型的引入会显著增加系统的 Token 消耗、推理时延(Latency)及不确定性。在工业级非结构化文档处理(如票据抽取、合同比对)中,默认方案不应一上来就调用多模态模型,而应采用“传统 CV/NLP 工具链 + 文本语义理解”的分层策略: - 第一阶段(前置抽取):文件或图像首先写入对象存储,通过专业 OCR 引擎、版面分析工具(Layout Analysis)或表格提取组件,将非结构化数据转化为带物理坐标、高度保真的结构化文本与字段候选。 - 第二阶段(模型精读与消歧):当传统抽取组件遇到歧义、跨区域关联或深层语义推理(如“根据上下文分析该条款的免责边界”)时,再将前置抽取的结构化片段作为上下文,送入文本或多模态大模型进行高精度消歧(Disambiguation),实现精度、性能与成本的最佳折中。
主链路:一次 AI 请求从哪里开始,到哪里收口¶
工业级 AI 服务链路必须对输入输出的生命周期进行严格分层治理: 1. 统一入口层(Ingress / Gateway):拦截请求并注入 Trace ID,进行多租户鉴权、流量限速、敏感词前置审计及请求超时(Timeout)设定。 2. 依赖注入与装配层(Dependency Assembly):装配本轮请求所需的特定模型客户端、特定租户的检索器(Retriever)、当前会话的状态上下文及注册工具表。 3. 上下文动态组织层(Context Assembly):根据本轮交互的槽位缺失状态,动态合并系统设定、历史工作记忆、外部检索证据及工具返回结果,计算并分配 Token 预算。 4. 决策规划与执行层(Planning & Execution):模型生成结构化指令或工具调用建议,服务端拦截工具请求并补齐安全凭证,执行物理副作用操作并进行标准响应解析。 5. 收口与度量层(Observability & Settlement):以流式(Streaming)或异步后台任务形式返回结果,执行在途状态 Checkpoint 持久化,异步沉淀会话摘要,打点 Token 计费、时延 trace 监控及评测样本收集。
任务定义:Prompt Engineering、结构化输出和边界控制¶
在企业级后端开发中,Prompt Engineering 的工程实质是声明式任务契约定义(Declarative Task Contract Definition),而非文学性的辞藻修饰。一个合格的任务契约必须严密界定以下四个维度: - 任务目标与角色(Objective & Role):明确当前节点的单一职责。 - 事实边界与证据分级(Fact Boundaries & Evidence Grading):指定可信材料的范围,防止模型越权解读。 - 停机准则与拒绝机制(Stop Criteria & Refusal Handling):明确定义证据不足时的标准阻断语与降级输出。 - 物理契约(Output Schema Contract):强制要求符合特定的 JSON/Protobuf Schema 格式。
1. 控制线解耦:Prompt vs Context vs Rules¶
- Prompt(解释制度):定义静态推理规则、处理逻辑与输出格式契约。
- Context(物理材料):提供动态装配的租户数据、历史会话片段及外置检索片段。
- Rules / Workflows(执行边界):业务代码实现的确定性拦截逻辑,例如多租户数据访问控制(ACL)、工具调用参数的二次强校验及物理副作用审计。
当线上系统发生行为偏移时,排障与止损应遵循 “先校验规则拦截层,再排查 Context 污染度,最后修改 Prompt 契约” 的防线级联顺序,避免使用不确定的 Prompt 来修补系统底层安全漏洞。
2. 结构化输出(Structured Output)的工程意义¶
结构化输出(如使用 JSON Schema 或 JSON Mode)绝非仅为数据解析方便,其底层工程意义在于为概率性的语言模型输出提供可被宿主语言(如 Go/Java)静态校验、类型断言与异常捕获的硬接口。利用宿主语言的反射与反序列化机制,可实现如下系统闭环防护: $\(\text{Output Model} \xrightarrow{\text{Parse}} \text{Go Struct} \xrightarrow{\text{Validator}} \text{Database / Workflow}\)$ 若反序列化失败或字段校验违背约束(如超出枚举值),服务端应自动拦截并触发自愈重试(Self-Correction Protocol)(将 Error Trace 回馈给模型促其修正)或平滑切换至人工兜底流。
上下文组织:长对话的核心不是截断,而是状态建模¶
长对话及多步复杂任务的上下文工程(Context Engineering)绝非无脑向大模型堆砌历史 Chat History,而是一项精密的运行时内存管理与状态建模工程。输入 Token 空间的膨胀不仅带来线性的算力成本上升,更会因长上下文注意力分散(Lost in the Middle)引发严重的幻觉偏移。
1. 上下文层级管理设计¶
上下文组织应采用“冷热分离、分层归集”的架构模型:
- 短期工作记忆(Hot Memory):最近 \(N\) 轮会话的原始消息(Raw Message)与最近一次工具调用的原始物理返回,用于保持当前上下文的物理连贯性。
- 运行摘要(Warm Memory):对更早的历史消息进行滑动窗口式压缩,保留核心事实发展线索,剥离冗余的寒暄与废话。
- 结构化状态(Structured State):将会话中确认的核心槽位值(如 invoice_id、date_range、current_approval_node)剥离出来,写入强类型数据库或 Session 上下文,成为在途流程的唯一真实状态源。
- 长期检索记忆(Cold Memory):将用户画像、常用术语、历史关联方案等低频静态背景,写入知识库,仅在模型触发特定条件时通过语义搜索精准召回。
2. Token 动态预算与压缩管线¶
为防止 Token 溢出,上下文装配管线必须在运行时执行基于优先级的 Token 预算抢占。预算降级分配顺序如下: $\(\text{System Constraints} > \text{Structured State} > \text{Raw Messages} > \text{Retrieved Fragments} > \text{Background Materials}\)$ 当上下文空间触及阈值时,自动触发滑动压缩管道: 1. 去重与语义聚合:清除重复的实体提问与冗余解释。 2. 快照归档(Checkpointing):对于需要跨生命周期、长达数天或需要人工接手的复杂任务,将当前执行图的状态序列化为 Checkpoint,后续执行节点通过反序列化 Checkpoint 恢复运行时上下文,彻底摆脱对海量原始历史的依赖。
执行组织:流式、后台任务、长输出和续跑¶
长生命周期的大模型生成任务对传统的同步 HTTP 线程池模型提出了严峻挑战。架构师必须根据输出体积与生命周期特征进行并发模式隔离:
- 流式响应(Streaming Output):针对即时对话场景,采用服务器发送事件(SSE, Server-Sent Events)实现高吞吐单向推送。相较于双向 WebSocket,SSE 原生基于标准 HTTP/1.1 或 HTTP/2,能更平滑地穿透企业级 API 网关、WAF 及负载均衡器,且原生支持 Ingress 层的鉴权、流控与 Tracing 传递。
- 异步后台长任务(Async Background Job):对于分析报告生成、长文档切片及长周期 Agent 执行,强制切换为异步任务模型。客户端通过投递任务创建物理实体,由后台协程池或分布式任务调度系统推进,客户端基于 Task ID 进行轮询或注册 Webhook 回调。
- 断点续跑(Checkpoint Resume):当生成内容超过模型单次推理上限(Max Generation Tokens)时,系统应拦截截断信号(如 Finish Reason 为 length),将已生成的片段大纲及未完成的槽位状态序列化,并重新发起调用,实现无缝拼接生成,避免模型因迷失空间感导致重复或死循环。
运行治理:并发、降级、重试、观测和成本¶
在大规模高并发环境下,多下游(模型推理、多源检索、Rerank 服务)的并发编排模式直接决定了系统的时延表现(P99 Latency)与容灾弹性。
1. 编排拓扑选型¶
- 全量收敛拓扑(Collect-All Topology):适用于对答案质量、风控安全有严苛要求的路径(如合规审查)。系统并发请求多路检索,必须等待所有子通道完整返回并完成去重后,再送入模型。其系统开销受限于最慢的长尾下游(Tail Latency)。
- 先到先得拓扑(Race-to-First Topology):适用于延迟敏感度极高的 C端会话。并发调用多个检索通道或不同维度的模型,利用
context.WithCancel控制器,在首路可用数据返回时,即刻发起模型流式输出并主动取消在途的其他分支请求,实现吞吐放大。 - 异步 I/O 并发模型(Non-blocking Async I/O):针对涉及大量网络等待的检索与 API 交互,Go 后端应坚决废弃一协程一物理阻塞的设计,采用基于 select 多路复用、Channel 背压与 errgroup 边界限制的非阻塞异步编排,最大化压低协程上下文切换开销与栈内存占用。
2. 系统可观测性(Observability)三元组¶
- 分布式 Tracing:将 Trace ID 贯穿 “Gateway -> App -> Retriever -> Rerank -> Model API”,清晰度量并可视化每一阶段的时延占比。
- 语义级日志(Semantic Logging):记录包含
model_version、prompt_tokens、completion_tokens、tool_invocations的结构化指标,用于后续成本精准核算及灰度路由分析。 - 离线评测采样(Feedback Loop):将线上真实交互样本脱敏后归集至评测数据集,作为系统回归测试、Few-Shot 样本迭代及微调(Fine-Tuning)的权威基料。
风险治理:幻觉、注入、越权、工具失败和人工接管¶
大模型概率节点的安全防御绝不能依赖脆弱的提示词防御,必须在确定性系统边界内实现闭环风控。
1. 幻觉与安全漏洞的分层防御机制¶
- 前置硬规则(Rule-based Guardrails):使用高性能确定性正则、敏感词典(Trie 树结构)或确定性权限校验器,对输入输入执行低成本、强一致的前置拦截。
- 语义分类器(Classifier Models):使用轻量分类模型对 Prompt 注入攻击(Prompt Injection)和越权欺骗进行语义分析。
- 人工干预(Human-in-the-Loop):对产生真实物理副作用的敏感高风险动作(如删除数据、支付、对外发送邮件),强制设置业务确认中断,必须由授权自然人审核后再物理执行。
- 后置审计与对齐(Post-hoc Auditing):离线定时异步抽检生成日志,利用裁判模型评估幻觉率与响应偏移。
2. 工具调用(Tool Calling)的失效模式与故障隔离¶
当模型调用外部 API(Tool)失败时,服务端必须执行严格的错误分类与降级隔离: - 瞬态抖动类错误(如 429 限流、网络超时):触发带退避时间(Backoff)与最大步数的指数避让重试机制,由服务端独立收口,不污染模型上下文。 - 参数缺失与格式错误(Schema Mismatch):转换为包含具体报错 Trace 的结构化错误消息回喂给模型,触发模型的自愈推理。 - 权限不足与硬状态冲突(ACL Deny / Business Logic Block):属于系统级强边界,必须立刻切断调用路径并终止生成,回退至标准化降级文案,绝对禁止自动重放。
评估与取舍:什么时候该做成 AI,什么时候不该¶
架构设计的核心智慧在于克制。AI 技术的高昂成本、时延长尾及不可靠性意味着它并非普适的技术底座。
- 不应上 AI 的红线场景:
- 核心逻辑基于严格的数学计算与等价变换(如财务对账、税率计算)。
- 执行路径要求强审计追踪、强状态机一致性约束与零错容忍度(如系统权限分配、数据库物理事务控制)。
- 延迟敏感度极高(如高频交易、网关级高并发拦截)。
- 应引入 AI 的增量场景:
- 传统自然语言理解(NLU)难以处理的泛化语义分析与歧义消歧。
- 从海量、异构非结构化文本中进行长时序信息组织、大纲提炼与综合分析。
- 需要在不确定性场景下根据多源环境反馈进行多步自主规划与任务分解(Agent 调度)。
在工程开发中,必须在架构层面坚持“确定性业务框架为主,概率性大模型为辅”的系统设计原则。准确界定概率算力与传统确定性后端架构之间的接口契约,是构建企业级、生产可用 AI 应用系统的终极保障。