公司动态
AI增强不是自动化:编排层才是大模型落地的关键
如果只能用一个词概括 AI 落地的现状我会选“割裂”。一方面聊天式 AI 的惊艳表现让所有人都觉得“智能已经来了”另一方面真正敢把大模型接进核心业务系统的团队仍然很少。原因并不复杂——聊天窗口承担不了业务规则一次 Prompt 跑完也没有过程可审计。我们缺的不是更强的模型而是一套能把模型能力安全、可控、可观测地嵌入业务流程的机制。这就是 AI Enhancement也就是“AI 增强”要解决的问题。Adima AI 这个题目里的“The Future of AI Enhancement”说白了一句话AI 增强的未来不在模型层而在编排层。模型的推理能力只是发动机真正决定业务能不能落地的是发动机周围的工作流、确认机制、评估体系和可观测性。这篇文章想把这件事讲透先给出核心判断再拆解技术分层最后带你把一个支持工具调用、人工确认、执行回填的最小 AI 增强工作台跑起来。读完你既能理解趋势也能拿到一份可以直接改造成业务的代码骨架。1. AI 增强的本质不是替代而是加杠杆很多人一听到“AI 增强”第一反应是“AI 帮我自动干活”。这个理解不能说错但容易把人带偏。自动化的目标是减少人的参与AI 增强的目标恰恰相反——它要让人的每一次决策都变得更有价值而不是把人踢出流程。传统自动化和 AI 增强之间有一条清晰的分界线。过去我们做客服工单自动分类用的是规则引擎加关键词匹配。规则覆盖到的地方机器处理又稳又快规则覆盖不到的地方直接转人工。这种模式的问题是规则写不完长尾场景永远在漏。后来大家尝试用大模型直接端到端生成答案效果确实好但新问题来了模型答案不可控出了错没人知道是哪一步出的错。AI 增强走的是第三条路。它不要求模型一次性输出最终答案而是把任务拆成“模型能做的”和“模型不应该擅做主张的”两类。模型负责理解意图、拆分步骤、生成候选方案人在关键节点确认、纠偏、拍板工具负责执行那些确定性强的操作比如查库存、更新状态、发通知。用一句话概括传统自动化是把人从流程里抽走AI 增强是把人的判断力放大。这才是“增强”两个字的核心语义。模型不是替代你而是给你加杠杆。你原来一个人一天处理 20 个售后工单现在同样的时间可以处理 80 个因为脏活累活被模型和工具消化掉了你只需要在真正需要判断的地方出手。这个定位决定了 AI 增强系统的设计原则永远要让人能介入永远要能解释系统为什么这么做永远要为每个结果留痕。我们在后文实现工作台时会反复回到这三条原则。2. AI 增强的核心概念与技术分层既然 AI 增强的重点在编排层那么它依赖哪些关键技术概念我梳理了五个基本覆盖了一个 AI 增强系统的全部要素。上下文工程Context Engineering模型本身不记忆任何东西它只看你这次请求给它的文本。如何把业务数据、历史记录、用户信息、系统约束组织成模型能理解且不过载的上下文就是上下文工程。很多团队模型选得不错效果却差问题往往出在上下文拼装太粗糙。一个合格的 AI 增强系统必须把上下文组装当成一等公民来设计。工具调用Tool Calling / Function Calling模型擅长生成文本不擅长执行确定性操作。工具调用就是让模型在生成过程中声明“我需要调用哪个工具参数是什么”然后由系统执行工具把结果回填给模型。这是从“只会说”到“能做事”的关键一步。人在环中Human-in-the-Loop这是“增强”和“自动化”的最大区别。系统在关键节点暂停把候选动作交给人来确认。设计得好人不会成为效率瓶颈设计得不好人会烦死。所以在工程上需要区分哪些操作必须确认、哪些可以放行这就是审批策略。评估与可观测性Evaluation Observability用传统软件工程的眼光看 AI 系统最难受的就是“不好测”。Prompt 调了一版业务说效果变差了差在哪没有评估体系就答不上来。AI 增强系统至少要做到每个请求有唯一 ID、每次工具调用有日志、每个最终回答可以回放最好再有一套离线评测集来判断 Prompt 和模型版本变更的影响。状态与编排State Orchestration多轮工具调用意味着系统的执行不是“一次请求一次响应”而是一个有中间状态的过程。订单查询可能先要调用用户身份接口、再调订单服务、最后生成汇总。编排器负责管理这个过程的状态流转、轮次控制、异常恢复和最终收口。这五个概念对应的技术分层可以用一张表来看分层职责典型问题模型层文本生成、推理、意图识别幻觉、格式不稳定、知识过时上下文层组织用户输入、业务数据、历史消息上下文超长、关键信息丢失、注入攻击工具层封装业务动作如查询、写入、通知越权调用、参数校验不足、副作用失控编排层决定调用顺序、轮次、确认节点、异常分支死循环、状态丢失、确认超时体验层面向最终用户的展示与交互响应太慢、回答看不懂治理层审计、评估、权限、限流、灰度无法追溯、评估缺失、权限过宽这张表也解释了为什么 AI 增强系统的架构难度不在模型选型而在模型之外的系统工程。模型再强治理层不做系统照样不敢上生产。3. 为什么“增强”是当前最值得落地的切入方式三个原因容错、成本、合规。先看容错。全自动 AI 系统要求模型每一步都对错误率会随着步骤数量指数级上升。一个 5 步的任务如果单步准确率是 95%最终准确率只有约 77%。这在业务里完全不可接受。AI 增强的策略是让模型只做低风险判断高风险动作全部交给人确认。人虽然慢但准确率接近 100%整体流程的可靠性就补回来了。再看成本。模型调用是有成本的全自动任务一旦出错多轮重试的成本很高。增强模式下人工确认相当于在关键路径上加了“闸门”错误的工具调用在产生实际副作用之前就被拦下避免后续补偿动作的成本。最后是合规。很多行业要求关键操作有审批记录、有操作人。纯自动化系统很难回答“这个操作是谁授权的”这种问题。AI 增强天然把人放在流程里每一步决策都有确认记录审计追溯顺理成章。这不是说全自动永远不会来。当模型能力持续提升、评估体系足够完善某些环节会逐渐从“人工确认”变成“事后抽检”。但今天对于大多数业务系统增强是最稳妥的切入点。4. 环境准备与项目结构设计下面开始动手。我们的目标不是做一个生产级平台而是用一个最小实现把 AI 增强的核心机制跑通模型调工具、工具执行、人工确认、结果回填、最终回答。建议环境Python 3.10 及以上版本。一个 OpenAI 兼容的模型 API。所谓“兼容”是指接口路径是/v1/chat/completions且支持tools参数。当前主流模型厂商基本都已经兼容这个协议。操作系统不限Linux、macOS、Windows 都可以。创建虚拟环境并安装依赖mkdir ai-enhancement-lab cd ai-enhancement-lab python -m venv .venv source .venv/bin/activate # Windows 使用 .venv\Scripts\activate# requirements.txt fastapi0.110 uvicorn[standard]0.29 pydantic2.6 httpx0.27 python-dotenv1.0pip install -r requirements.txt项目结构ai-enhancement-lab/ ├── requirements.txt ├── .env.example └── app/ ├── __init__.py ├── config.py ├── schemas.py ├── llm_client.py ├── tools.py ├── orchestrator.py └── main.py需要说明的是这个结构是通用的 AI 增强参考实现不是某个特定产品的源码。具体产品的 API 和内部实现以官方文档为准但架构思路可以复用。5. 核心流程拆解从用户任务到可干预的 AI 执行在写代码之前先把流程理清。一个 AI 增强任务的完整生命周期是接收用户任务比如“查询订单 20250708 的状态”。组装上下文把系统提示词、用户任务、历史消息拼成模型输入。模型决策模型判断需要调用哪个工具并输出结构化工具调用参数。人工确认系统进入等待状态把候选工具调用交给用户审批。这一步是“增强”和“自动化”的分水岭。工具执行用户批准后系统调用真实工具拿到结果。结果回填工具结果追加到消息历史模型继续推理。循环直到模型认为不再需要工具输出最终答案。过程留痕完整记录工具调用、确认结果和最终回答供审计和评估。这个流程最容易被新手忽略的地方是人工确认。很多人实现到“模型能调用工具”就觉得完事了直接放生产结果模型调了一个删除接口酿成事故。真正做 AI 增强系统必须从设计上给危险操作加闸门。另一个容易踩坑的是轮次控制。模型在少数情况下会反复调用同一个错误参数形成死循环。设计上必须设定最大轮数到点强制收口。我们接下来实现的编排器就围绕这两个点展开。6. 完整示例实现一个最小 AI 增强工作台6.1 配置文件与依赖.env.example文件# .env.example LLM_BASE_URLhttps://api.openai.com/v1 LLM_API_KEYsk-your-key LLM_MODELgpt-4o-mini LLM_TIMEOUT60配置文件app/config.pyimport os from dotenv import load_dotenv load_dotenv() LLM_BASE_URL os.getenv(LLM_BASE_URL, https://api.openai.com/v1).rstrip(/) LLM_API_KEY os.getenv(LLM_API_KEY, ) LLM_MODEL os.getenv(LLM_MODEL, gpt-4o-mini) LLM_TIMEOUT float(os.getenv(LLM_TIMEOUT, 60))这个配置模块很简单但它在真实项目中会扩展出大量内容模型路由、多 Key 负载均衡、超时重试、调用预算控制。我们在最小实现里先不展开。6.2 数据模型定义app/schemas.pyfrom typing import Any, Literal, Optional from pydantic import BaseModel, Field class ToolCall(BaseModel): 模型发起的一次工具调用请求 tool_name: str arguments: str {} tool_call_id: str class ToolResult(BaseModel): 工具执行结果会回填给模型 tool_name: str ok: bool data: dict[str, Any] Field(default_factorydict) error: Optional[str] None class LLMResult(BaseModel): LLM 客户端统一返回结构 content: str raw_tool_calls: list[dict[str, Any]] Field(default_factorylist) tool_calls: list[ToolCall] Field(default_factorylist) class EnhancementRequest(BaseModel): task: str user_id: str anonymous need_confirm: bool True max_turns: int 5 class ConfirmDecision(BaseModel): tool_name: str approved: bool class ConfirmRequest(BaseModel): session_id: str decisions: list[ConfirmDecision] class EnhancementResponse(BaseModel): session_id: str status: Literal[done, need_confirm, exhausted, error] answer: str pending_calls: list[ToolCall] Field(default_factorylist) tool_results: list[ToolResult] Field(default_factorylist)这些模型并不复杂但它们是整个系统的契约。尤其是EnhancementResponse.status它把“需要人工确认”作为一个显式状态暴露出来前端可以据此展示审批界面而不是把等待状态混在普通响应里。6.3 工具注册表与执行器app/tools.pyimport json from typing import Any from .schemas import ToolCall, ToolResult TOOL_REGISTRY: dict[str, dict[str, Any]] {} def register_tool(name: str, description: str, parameters: dict[str, Any]): 注册一个可被模型调用的工具 def decorator(func): TOOL_REGISTRY[name] { description: description, parameters: parameters, function: func, } return func return decorator register_tool( namequery_order_status, description查询订单当前状态适合客服、售后、物流场景, parameters{ type: object, properties: { order_id: {type: string, description: 订单号} }, required: [order_id], }, ) async def query_order_status(order_id: str) - dict[str, Any]: # 真实项目中替换为内部订单系统的接口调用 return { order_id: order_id, status: 已发货, tracking: SF1234567890, } async def execute_tool(call: ToolCall) - ToolResult: 执行工具调用并对异常做收敛处理 info TOOL_REGISTRY.get(call.tool_name) if not info: return ToolResult( tool_namecall.tool_name, okFalse, errorf未注册工具: {call.tool_name}, ) try: args json.loads(call.arguments) if call.arguments else {} data await info[function](**args) return ToolResult(tool_namecall.tool_name, okTrue, datadata) except Exception as exc: return ToolResult( tool_namecall.tool_name, okFalse, errorstr(exc), )这里的工具注册器是演示用的简化版本。生产环境中工具层要考虑权限校验、参数约束、调用审计、超时控制、幂等性以及最重要的每个工具都要声明自己的“危险等级”危险等级高的工具必须进入人工确认流程。6.4 LLM 客户端封装app/llm_client.pyimport httpx from .schemas import LLMResult, ToolCall class OpenAICompatibleClient: OpenAI 兼容协议客户端支持 tools 参数 def __init__(self, base_url: str, api_key: str, model: str, timeout: float 60.0): self.base_url base_url self.api_key api_key self.model model self.timeout timeout async def chat_with_tools( self, messages: list[dict], tools: list[dict], ) - LLMResult: payload { model: self.model, messages: messages, tools: tools, tool_choice: auto, } headers {Authorization: fBearer {self.api_key}} async with httpx.AsyncClient(timeoutself.timeout) as client: resp await client.post( f{self.base_url}/chat/completions, jsonpayload, headersheaders, ) resp.raise_for_status() data resp.json() message data[choices][0][message] content message.get(content) or raw_tool_calls message.get(tool_calls) or [] tool_calls [] for raw in raw_tool_calls: fn raw.get(function, {}) tool_calls.append( ToolCall( tool_namefn.get(name, ), argumentsfn.get(arguments, {}), tool_call_idraw.get(id, ), ) ) return LLMResult( contentcontent, raw_tool_callsraw_tool_calls, tool_callstool_calls, )封装 LLM 客户端的目的是把第三方依赖隔离在一个模块里。未来想换模型提供商或者加缓存、加重试、加预算控制只改这一个文件就行。6.5 编排器实现人机协作主循环接下来是核心编排器。它是整个 AI 增强工作台的大脑。app/orchestrator.pyimport json import uuid from .llm_client import OpenAICompatibleClient from .schemas import ( ConfirmRequest, EnhancementRequest, EnhancementResponse, ToolCall, ToolResult, ) from .tools import TOOL_REGISTRY, execute_tool SYSTEM_PROMPT ( 你是 AI 增强工作台中的智能助理。 当用户需要查询订单等实时数据时必须先调用工具获取真实结果 不能凭记忆编造数据。 ) def build_tool_schemas() - list[dict]: schemas [] for name, tool in TOOL_REGISTRY.items(): schemas.append( { type: function, function: { name: name, description: tool[description], parameters: tool[parameters], }, } ) return schemas class Orchestrator: def __init__(self, client: OpenAICompatibleClient): self.client client self.tool_schemas build_tool_schemas() self.sessions: dict[str, dict] {} async def start(self, request: EnhancementRequest) - EnhancementResponse: session_id uuid.uuid4().hex self.sessions[session_id] { request: request, messages: [ {role: system, content: SYSTEM_PROMPT}, {role: user, content: request.task}, ], tool_results: [], } return await self._step(session_id) async def confirm(self, req: ConfirmRequest) - EnhancementResponse: session self.sessions.get(req.session_id) if not session: return EnhancementResponse( session_idreq.session_id, statuserror, answer会话不存在或已结束, ) pending session.pop(pending, None) if not pending: return EnhancementResponse( session_idreq.session_id, statuserror, answer当前没有待确认的工具调用, ) assistant_msg pending[assistant_msg] parsed_calls: list[ToolCall] pending[parsed_calls] session[messages].append(assistant_msg) for call, decision in zip(parsed_calls, req.decisions): if decision.approved: result await execute_tool(call) else: result ToolResult( tool_namecall.tool_name, okFalse, data{approved: False}, error用户拒绝执行, ) session[tool_results].append(result) session[messages].append(self._tool_message(call, result)) return await self._step(req.session_id) async def _step(self, session_id: str) - EnhancementResponse: session self.sessions.get(session_id) if not session: return EnhancementResponse( session_idsession_id, statuserror, answer会话不存在, ) request session[request] for _ in range(request.max_turns): try: llm_result await self.client.chat_with_tools( session[messages], self.tool_schemas, ) except Exception as exc: self.sessions.pop(session_id, None) return EnhancementResponse( session_idsession_id, statuserror, answerf模型调用失败: {exc}, ) assistant_msg { role: assistant, content: llm_result.content or , } if llm_result.raw_tool_calls: assistant_msg[tool_calls] llm_result.raw_tool_calls # 模型认为不需要工具直接返回最终结论 if not llm_result.tool_calls: session[messages].append(assistant_msg) resp EnhancementResponse( session_idsession_id, statusdone, answerllm_result.content or , tool_resultssession[tool_results], ) self.sessions.pop(session_id, None) return resp # 需要人工确认时挂起流程等待审批 if request.need_confirm: session[pending] { assistant_msg: assistant_msg, parsed_calls: llm_result.tool_calls, } return EnhancementResponse( session_idsession_id, statusneed_confirm, answer等待人工确认以下工具调用, pending_callsllm_result.tool_calls, tool_resultssession[tool_results], ) # 不需要确认时直接执行工具并回填 session[messages].append(assistant_msg) for call in llm_result.tool_calls: tool_result await execute_tool(call) session[tool_results].append(tool_result) session[messages].append(self._tool_message(call, tool_result)) # 达到最大轮数强制收口 self.sessions.pop(session_id, None) return EnhancementResponse( session_idsession_id, statusexhausted, answer达到最大轮数任务已终止, tool_resultssession[tool_results], ) def _tool_message(self, call: ToolCall, tool_result: ToolResult) - dict: return { role: tool, tool_call_id: call.tool_call_id or call.tool_name, content: json.dumps(tool_result.dict(), ensure_asciiFalse), }这段代码的核心是_step和confirm的配合。当模型发起工具调用并且need_confirmTrue时系统不会立即执行工具而是生成need_confirm状态返回给前端把assistant_msg保存在 session 的pending字段里。用户确认或拒绝后调用confirm接口系统才把工具结果回填给模型继续推理。这样就形成了一个完整的人机协作闭环。这里要特别说明一点示例用内存 dict 保存会话状态只适合演示。生产环境必须用 Redis 等外部存储因为多实例部署时内存状态无法共享进程重启也会导致会话丢失。6.6 FastAPI 接入层app/main.pyfrom fastapi import FastAPI from .config import LLM_API_KEY, LLM_BASE_URL, LLM_MODEL, LLM_TIMEOUT from .llm_client import OpenAICompatibleClient from .orchestrator import Orchestrator from .schemas import ConfirmRequest, EnhancementRequest, EnhancementResponse app FastAPI(titleAI Enhancement Lab, version0.1.0) orchestrator Orchestrator( OpenAICompatibleClient( base_urlLLM_BASE_URL, api_keyLLM_API_KEY, modelLLM_MODEL, timeoutLLM_TIMEOUT, ) ) app.post(/api/v1/enhance, response_modelEnhancementResponse)