跳到正文
Elaine Blog
返回

生产中的上下文工程:设计一个可追溯的上下文管理模块

更新于:
Context Engineering

到这里,我们已经知道如何选择信息、保存状态、读取记忆和压缩历史。但把这些函数散放在每个业务接口里,生产系统仍然很难维护:客服接口用一种预算,后台 Agent 用另一种摘要,某个工具又绕过授权直接拼接了结果。

可以把上下文准备设计成一个有明确输入输出的模块。它可以先是应用内的一组组件,无需一开始拆成独立微服务。关键是让调用方通过同一套契约取得本次模型输入,并能知道它是怎样产生的。

先确定模块不替代谁

业务数据库负责订单事实,身份服务负责主体身份,授权服务决定访问范围,工作流负责业务阶段,模型适配器负责 API 协议。上下文模块协调这些输入,形成当前调用需要的视图。

比如它可以带入“订单 revision 12,质量待核实”,但不能因为模型生成了“已核实”就修改订单数据库。它可以给出工具定义,但是否执行退款仍由业务执行端决定。

这条边界让模块失败时更容易定位:候选没取到,找信息提供器;候选取到了但丢了条件,找选择策略;上下文正确但模型推错,找模型和提示;退款重复执行,检查业务幂等与恢复。

一次请求的契约应该是什么

输入可以包含可信主体、任务 ID、当前问题、模型能力与本次预算。调用方提供的 task_id 仍需要核验归属;模型配置应由应用选定,不能让任意客户端声明一个虚假的大窗口绕过预算。

输出可以用 ContextPackage 表达:

{
  "request_id": "req-92",
  "strategy_version": "consultation-v3",
  "task_revision": 4,
  "messages": "符合目标接口的消息结构",
  "tools": "本阶段允许交给模型的工具定义",
  "sources": [{"id": "P7-v2", "version": "v2"}],
  "selection_trace": [{"id": "old-chat", "reason": "irrelevant"}],
  "input_estimate": {"value": 6200, "unit": "token", "estimator": "adapter-x"},
  "status": "ready"
}

数字为示意。正式结构还需要能够表达 missing_required_databudget_exceededsource_conflict 等状态。失败不能被包装成一个空资料包再交给模型假装任务可以完成。

输出中的 trace 不必全部交给模型。给模型的证据来源与给运维的选择过程可以使用不同结构,避免诊断字段占用输入空间或暴露内部权限细节。

上下文从可信输入经过提供器、策略预算和请求组装,再到调用与持续维护

五个组件如何协作

信息提供器读取任务状态、历史、记忆、检索证据和工具目录。各提供器接收受限查询范围,返回带来源、版本、读取时间和大小估计的条目。它们不直接写最终 Prompt,避免每个来源自己决定角色和位置。

策略组件描述任务需要什么。例如咨询运费需要适用条款与核实状态,准备申请草稿还需要可用取件时间,而提交申请必须由执行流程取得对应确认记录。策略可以调用检索器或相关性模型,但必须项和授权条件由程序保证。

预算分配器先检查必需内容,再选择可选信息,识别不可拆分包和依赖。无法满足时返回明确失败或请求上层改用分步流程。它不能为了“总能给结果”静默删除规则。

请求组装器把选中条目放进目标模型支持的结构,维持合法消息顺序和工具调用关联,并对最终结构重新计数。不同模型的角色名称、图片表示和工具协议不一定相同,因此应通过适配器处理。

过程记录器保存策略版本、依赖版本、选中 ID、排除原因和用量。不应默认记录所有敏感正文;需要完整快照时使用独立的受控存储和保留策略。

这五个组件可以先用普通 Python 函数表达。抽象来自变化点:以后更换模型,主要修改适配器;更换记忆存储,主要修改提供器;调整历史选择,主要修改策略,而不必重写整条业务链。

固定流程与可配置策略怎样分开

顺序相对稳定:接收可信身份、确定任务、获取允许的数据、检查有效性、处理冲突和依赖、选择、渲染、最终校验、记录。授权与最终预算校验不能因某个策略“不需要”而被关闭。

可配置的是任务需要哪些来源、必需字段、允许的降级方式、历史保留范围、压缩条件和补查次数。例如:

{
  "name": "after_sales_consultation",
  "version": 3,
  "required": ["task_state", "order_delivery", "applicable_policy"],
  "optional": ["recent_dialogue"],
  "allowed_tools": ["lookup_order", "search_policy"],
  "on_missing_order": "general_policy_only",
  "max_extra_reads": 2
}

general_policy_only 需要有实际处理逻辑:不再回答该订单是否符合,只说明通用条款和缺失信息。它不能仅仅变成日志里的一个字符串,然后继续输出订单级结论。

配置本身也要校验。若 required 中的来源没有对应提供器,发布时应发现,而不是线上某次请求才悄悄省略。用户新建的模型角色也不应自动拥有修改所有策略的权限。

看一次正常请求如何经过模块

A1042 的咨询请求进入后,服务端得到 shop-a/user-417,读取 T9 revision 4,确认订单归属。订单与政策查询在条件独立时可以并行;若政策选择依赖订单商品类别,则必须先取得该字段。

提供器返回订单 r12、适用政策 v2、近期消息及无关历史。策略将“尚未核实”和完整条款列为必要证据包,预算器排除旧产品介绍,组装器生成问题与引用,并记录最终估算。

模型返回条件性回答。响应处理器检查引用是否来自本次证据,保存本轮消息;它不会把自然语言结论直接写成 quality_verified=true。用户之后补充资料,形成新的事件和新的状态,再准备下一次上下文。

这说明上下文工程是每轮都发生的工作。工具返回、新用户消息和业务事实变化都会改变下一次输入,不是启动 Agent 时拼一遍 Prompt 就结束。

资料来自不同时间怎么办

订单 r12、政策 v2 和权限 epoch 7 可能分别来自不同服务,无法共享数据库事务。记录版本能帮助发现变化,却不会自动创造全局一致快照。

对咨询任务,可以在明确时效范围内组合资料,并在回答中避免超出其依据。对执行任务,应在提交前重新检查影响合法性的订单状态、授权和操作参数,必要时拒绝并要求重新确认。

当读取的政策版本发生切换,需要按业务适用时间选择,不是统一改为最新版。缓存、检索结果和摘要都要关联这些依赖;如果它们引用的来源被撤回,组装器不能继续只看本地 TTL。

超时、超预算和冲突分别怎样降级

订单服务超时时,通用政策说明仍可能成立,但订单级判断缺少事实。应由上层切换为明确的通用解释任务,减少允许结论的范围。权限检查不可用则不能默认放行。

可选历史超预算时可以排除;必需政策包超预算时,应外置无关部分、改成分步读取、调整模型或明确停止。若条款本身不可拆分,不能随意截断其条件。

两个有效来源冲突时,可以返回 source_conflict,让上层核实或转人工。不要悄悄选一个最短来源,因为它更容易塞进窗口。

大型工具结果先受大小限制,再进入受控外置流程;缓存故障可以在授权范围内回源;记忆写入失败不能回复“已经永久记住”。这些故障的处理取决于任务语义,而不仅是统一重试三次。

并发与副作用需要留在哪一层

任务状态写入通过 revision 做条件更新,避免旧请求覆盖新状态。摘要生成记录覆盖事件范围,防止覆盖生成过程中到达的新消息。后台记忆整理以来源事件排序,并用事件 ID 防止重复处理。

外部副作用仍由执行服务提供幂等与回执查询。上下文模块可以带上已执行动作的说明,但说明不是执行账本。如果检查点恢复时无法确定动作结果,应查询业务服务,而不是让模型猜是否需要再试。

这也解释了为什么模块最好保持清楚的读取和写入阶段:准备输入不顺便提交退款,更新对话历史不顺便把所有内容写入长期记忆。副作用集中后,恢复路径才容易判断。

怎样追溯问题,又不复制所有隐私数据

一次诊断记录至少能连接 request_id、task_revision、strategy_version、模型配置和来源版本。候选记录区分没取到、无权访问、不适用、超预算、依赖缺失和最终选中。

对敏感记录,普通日志只保存允许暴露的内部引用与原因。受控快照可保存必要的最终请求用于排查,设置保留时间和访问审计。哈希能用于比对,不能还原内容,也不能自动保证匿名性。

重放也有不同含义:用相同版本资料重建输入,可以检查选择策略;重新请求模型不保证逐字相同;重放带副作用的工具调用更不能当成普通诊断。生产排查默认使用只读或模拟执行路径。

策略修改怎样逐步发布

先积累具体失败:条件被裁掉、旧偏好覆盖本轮要求、摘要漏掉限制。围绕原因修改策略,并保留旧版配置与依赖版本。

可以离线比较同一批允许保留的输入,也可以在获准范围内让新策略只生成选择清单、不调用外部写工具。比较必需证据保留、冲突识别、输入成本和后续任务完成情况。所谓影子运行仍可能产生额外模型费用和数据使用,不能当成零成本动作。

上线时记录版本,发现回归后恢复旧策略。回滚策略不会撤销已经写入的错误长期记忆,也不会撤销已执行的业务操作,因此它们需要各自的修复机制。

本篇给出的是可实施的设计,而非某个框架现成组件的功能清单。下一篇用小型 Python 模块落实正常路径与几种明确失败,帮助你看清哪些机制已经实现,哪些仍需要接入真实基础设施。

继续阅读

上一篇: 谁可以看到什么:上下文隔离、可信边界与多 Agent 交接

下一篇: 把上下文工程串起来:实现组装流程,并定位回答失败

完整文件、依赖与运行边界见配套指南下载


分享这篇文章:

上一篇
谁可以看到什么:上下文隔离、可信边界与多 Agent 交接
下一篇
把上下文工程串起来:实现组装流程,并定位回答失败