当前位置: 首页 > news >正文

Spring AI Alibaba 1.x 系列【76】上下文工程(Context Engineering)

文章目录

  • 1. 概述
    • 1.1 为什么 Agent 会失败
    • 1.2 什么是上下文工程
  • 2. Agent 循环与上下文类型
    • 2.1 Agent 循环
    • 2.2 三种上下文类型
    • 2.3 三种数据源
  • 3. 模型上下文
    • 3.1 系统提示(System Prompt)
      • 3.1.1 基于状态的动态提示
      • 3.1.2 基于存储的个性化提示
    • 3.2 消息历史(Messages)
      • 3.2.1 消息过滤 —— 限制上下文长度
      • 3.2.2 瞬态更新 VS 持久更新
    • 3.3 工具选择(Tools)
    • 3.4 模型选择(Model)
    • 3.5 响应格式(Response Format)
  • 4. 工具上下文
    • 4.1 工具中读取状态
    • 4.2 工具中修改状态
  • 5. 生命周期上下文
    • 5.1 Hook 位置
    • 5.2 日志 Hook
    • 5.3 消息摘要 Hook
  • 6. 完整示例:综合上下文工程
  • 7. Hook 与 Interceptor 选择指南
  • 8. 瞬态 vs 持久 决策树

1. 概述

1.1 为什么 Agent 会失败

构建Agent的难点在于使其足够可靠。虽然写一个Demo很容易,但要在生产环境中稳定运行并不简单。

Agent失败通常有两个原因:

原因说明
底层 LLM 能力不足模型本身无法完成复杂推理任务
没有传递"正确"的上下文指令、工具、消息等上下文信息不匹配当前任务

大多数情况下是第二个原因——上下文工程不是附加功能,而是AI工程师的首要工作Spring AI AlibabaHookInterceptor抽象专门为此设计。

1.2 什么是上下文工程

上下文工程是以正确的格式提供正确的信息和工具,使LLM能够完成任务。

┌─────────────────────────────────────────────────────┐ │ 上下文工程 │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌────────────┐ │ │ │ 模型上下文 │ │ 工具上下文 │ │ 生命周期 │ │ │ │ (瞬态) │ │ (持久) │ │ 上下文 │ │ │ │ │ │ │ │ (持久) │ │ │ │ · SystemPrompt│ │ · 读 State │ │ · 摘要 │ │ │ │ · Messages │ │ · 写 State │ │ · 护栏 │ │ │ │ · Tools │ │ · 读 Store │ │ · 日志 │ │ │ │ · Model │ │ · 写 Store │ │ │ │ │ │ · Response │ │ │ │ │ │ │ └──────────────┘ └──────────────┘ └────────────┘ │ └─────────────────────────────────────────────────────┘

2. Agent 循环与上下文类型

2.1 Agent 循环

┌──────────────────────────────────┐ │ Agent 循环 │ │ │ │ ┌─────────┐ ┌─────────┐ │ │ │ 模型调用 │ ──→ │ 工具执行 │ │ │ │ (Think) │ ←── │ (Act) │ │ │ └─────────┘ └─────────┘ │ │ │ │ │ │ └── 任务完成 → 退出 ─┘ │ └──────────────────────────────────┘

2.2 三种上下文类型

上下文控制内容生命周期实现机制
模型上下文LLM 单次调用看到什么瞬态(单次调用)ModelInterceptor
工具上下文工具能访问和产生什么持久(跨轮次)ToolContext
生命周期上下文模型和工具调用之间发生什么持久(跨轮次)AgentHook/ModelHook

2.3 三种数据源

┌──────────────────────────────────────────────────┐ │ 数据源 │ │ │ │ 运行时上下文 State Store │ │ (静态配置) (短期记忆) (长期记忆) │ │ 会话范围 会话范围 跨会话 │ │ │ │ · 用户 ID · 当前消息 · 用户偏好 │ │ · API Key · 上传文件 · 历史数据 │ │ · 权限设置 · 认证状态 · 提取的 │ │ · 环境变量 · 工具结果 见解 │ │ · 数据库连接 │ └──────────────────────────────────────────────────┘

3. 模型上下文

控制每次模型调用中包含的内容——指令、可用工具、使用哪个模型以及输出格式。

3.1 系统提示(System Prompt)

3.1.1 基于状态的动态提示

根据对话长度自动调整指令风格:

classStateAwarePromptInterceptorextendsModelInterceptor{@OverridepublicModelResponseinterceptModel(ModelRequestrequest,ModelCallHandlerhandler){List<Message>messages=request.getMessages();StringbasePrompt="你是一个有用的助手。";if(messages.size()>10){basePrompt+="\n这是一个长对话 - 请尽量保持精准简捷。";}SystemMessageenhancedMessage=request.getSystemMessage()==null?newSystemMessage(basePrompt):newSystemMessage(request.getSystemMessage().getText()+"\n\n"+basePrompt);ModelRequestenhancedRequest=ModelRequest.builder(request).systemMessage(enhancedMessage).build();returnhandler.call(enhancedRequest);}}

3.1.2 基于存储的个性化提示

从长期记忆加载用户偏好,构建个性化System Prompt

classPersonalizedPromptInterceptorextendsModelInterceptor{privatefinalUserPreferenceStorestore;@OverridepublicModelResponseinterceptModel(ModelRequestrequest,ModelCallHandlerhandler){StringuserId=request.getContext().get("user-id");// 从运行时上下文获取UserPreferencesprefs=store.getPreferences(userId);// 从 Store 加载偏好StringBuilderprompt=newStringBuilder("你是一个有用的助手。");if(prefs.getCommunicationStyle()!=null){prompt.append("\n沟通风格:").append(prefs.getCommunicationStyle());}if(prefs.getLanguage()!=null){prompt.append("\n使用语言:").append(prefs.getLanguage());}SystemMessageenhancedMessage=buildEnhancedMessage(request,prompt.toString());returnhandler.call(ModelRequest.builder(request).systemMessage(enhancedMessage).build());}}

调用时通过RunnableConfig传递用户 ID:

RunnableConfig.builder().metadata("user-id","user123").build()

3.2 消息历史(Messages)

3.2.1 消息过滤 —— 限制上下文长度

classMessageFilterInterceptorextendsModelInterceptor{privatefinalintmaxMessages;@OverridepublicModelResponseinterceptModel(ModelRequestrequest,ModelCallHandlerhandler){List<Message>messages=request.getMessages();if(messages.size()>maxMessages){// 保留 SystemMessage + 最近的消息List<Message>filtered=newArrayList<>();messages.stream().filter(m->minstanceofSystemMessage).findFirst().ifPresent(filtered::add);intstart=Math.max(0,messages.size()-maxMessages+1);filtered.addAll(messages.subList(start,messages.size()));messages=filtered;}returnhandler.call(ModelRequest.builder(request).messages(messages).build());}}

3.2.2 瞬态更新 VS 持久更新

方式机制影响范围示例
瞬态ModelInterceptor仅本次 LLM 调用消息过滤
持久MessagesModelHook+UpdatePolicy.REPLACE修改 State 中的消息对话摘要

3.3 工具选择(Tools)

按用户角色动态分配工具集:

classContextualToolInterceptorextendsModelInterceptor{privatefinalMap<String,List<ToolCallback>>roleBasedTools;@OverridepublicModelResponseinterceptModel(ModelRequestrequest,ModelCallHandlerhandler){StringuserRole=request.getContext().getOrDefault("user-role","user");List<ToolCallback>allowedTools=roleBasedTools.getOrDefault(userRole,List.of());returnhandler.call(ModelRequest.builder(request).dynamicToolCallbacks(allowedTools).build());}}// 配置Map<String,List<ToolCallback>>roleTools=Map.of("admin",List.of(readTool,writeTool,deleteTool),"user",List.of(readTool),"guest",List.of());ReactAgentagent=ReactAgent.builder().interceptors(newContextualToolInterceptor(roleTools)).build();

3.4 模型选择(Model)

根据任务复杂度动态切换模型——简单任务用小模型降成本,复杂任务用大模型保质量:

classDynamicModelInterceptorextendsModelInterceptor{privatefinalChatModelsimpleModel;privatefinalChatModelcomplexModel;@OverridepublicModelResponseinterceptModel(ModelRequestrequest,ModelCallHandlerhandler){booleanisComplex=analyzeComplexity(request.getMessages());ChatModelselectedModel=isComplex?complexModel:simpleModel;returnhandler.call(ModelRequest.builder(request).model(selectedModel).build());}privatebooleananalyzeComplexity(List<Message>messages){returnmessages.size()>5;// 长对话视为复杂任务}}

3.5 响应格式(Response Format)

Agent创建时指定结构化输出:

ReactAgentagent=ReactAgent.builder().name("structured_agent").model(chatModel).outputType(MyResponseClass.class)// 或 .outputSchema(jsonSchema).build();

4. 工具上下文

控制工具对State(短期记忆)和Store(长期记忆)的读写权限。

4.1 工具中读取状态

classStatefulToolimplementsFunction<StatefulTool.Request,StatefulTool.Response>{publicrecordRequest(Stringquery){}publicrecordResponse(Stringresult){}@OverridepublicResponseapply(Requestrequest,ToolContexttoolContext){// 读取当前 Agent StateOverAllStatestate=(OverAllState)toolContext.getContext().get("state");Optional<Object>messages=state.value("messages");// 读取运行时配置RunnableConfigconfig=(RunnableConfig)toolContext.getContext().get("config");Optional<Object>userCtx=config.metadata("user_context_key");returnnewResponse(processWithContext(request.query(),messages,userCtx));}}

4.2 工具中修改状态

classStateModifyingToolimplementsFunction<StateModifyingTool.Request,StateModifyingTool.Response>{publicrecordRequest(Stringdata){}publicrecordResponse(Stringstatus){}@OverridepublicResponseapply(Requestrequest,ToolContexttoolContext){// extraState 中的值会被持久化到 State,后续 Loop 可见Map<String,Object>extraState=(Map<String,Object>)toolContext.getContext().get("extraState");Stringprocessed=process(request.data());extraState.put("processed_data",processed);// 持久化到 StatereturnnewResponse("数据已处理并保存到状态");}}

5. 生命周期上下文

使用HookAgent生命周期的关键节点执行操作。

5.1 Hook 位置

Spring AI Alibaba支持四个Hook位置:

BEFORE_AGENT AFTER_AGENT │ ▲ ▼ │ ┌──────────────────────────────────────────┴──┐ │ Agent 执行过程 │ │ │ │ ┌──────────┐ ┌──────────┐ │ │ │ 模型调用 │───→│ 工具执行 │───→ ... │ │ └──────────┘ └──────────┘ │ │ ▲ │ │ │ │ │ BEFORE_MODEL AFTER_MODEL │ └──────────────────────────────────────────────┘
Hook 位置时机常用于
BEFORE_AGENTAgent 启动前查询增强、上下文预加载
AFTER_AGENTAgent 结束后结果后处理、清理
BEFORE_MODEL每次 LLM 调用前检索、消息摘要、日志
AFTER_MODEL每次 LLM 调用后响应验证、日志

5.2 日志 Hook

classLoggingHookextendsModelHook{@OverridepublicHookPosition[]getHookPositions(){returnnewHookPosition[]{HookPosition.BEFORE_MODEL,HookPosition.AFTER_MODEL};}@OverridepublicCompletableFuture<Map<String,Object>>beforeModel(OverAllStatestate,RunnableConfigconfig){List<?>messages=(List<?>)state.value("messages").orElse(List.of());System.out.println("[BEFORE_MODEL] 消息数: "+messages.size());returnCompletableFuture.completedFuture(Map.of());}@OverridepublicCompletableFuture<Map<String,Object>>afterModel(OverAllStatestate,RunnableConfigconfig){System.out.println("[AFTER_MODEL] 响应已生成");returnCompletableFuture.completedFuture(Map.of());}}

5.3 消息摘要 Hook

当对话过长时自动生成摘要,压缩上下文:

@HookPositions({HookPosition.BEFORE_MODEL})classSummarizationHookextendsMessagesModelHook{privatefinalChatModelsummarizationModel;privatefinalinttriggerLength;@OverridepublicAgentCommandbeforeModel(List<Message>previousMessages,RunnableConfigconfig){if(previousMessages.size()<=triggerLength){returnnewAgentCommand(previousMessages);// 未超阈值,不处理}// 1. 生成摘要Stringsummary=generateSummary(previousMessages);// 2. 保留 SystemMessage + 摘要 + 最近消息List<Message>newMessages=newArrayList<>();previousMessages.stream().filter(m->minstanceofSystemMessage).forEach(newMessages::add);newMessages.add(newUserMessage("【上下文摘要】之前的对话摘要:"+summary));intrecentCount=Math.min(5,previousMessages.size());newMessages.addAll(previousMessages.subList(previousMessages.size()-recentCount,previousMessages.size()));returnnewAgentCommand(newMessages,UpdatePolicy.REPLACE);}}

6. 完整示例:综合上下文工程

将多种上下文工程手段组合到一个Agent中:

@ConfigurationpublicclassContextEngineeringConfig{@BeanpublicReactAgentcontextEngineeredAgent(ChatModelchatModel,ChatModelsummaryModel,UserPreferenceStorestore){returnReactAgent.builder().name("context_engineered_agent").model(chatModel).description("综合上下文工程示例").instruction("你是一个智能助手,会根据用户偏好调整回复风格。")// 个性化 System Prompt.interceptors(newPersonalizedPromptInterceptor(store),// 从 Store 加载偏好newMessageFilterInterceptor(20),// 限制消息数量newContextualToolInterceptor(getRoleTools()),// 按角色分配工具newAnswerValidationInterceptor()// 答案验证)// 生命周期 Hook.hooks(newSummarizationHook(summaryModel,15),// 长对话摘要newLoggingHook()// 日志).saver(newMemorySaver()).enableLogging(true).build();}}

7. Hook 与 Interceptor 选择指南

需求使用原因
修改单次 LLM 调用的内容ModelInterceptor瞬态,不影响 State
持久修改消息列表MessagesModelHook+REPLACE修改 State 中的消息
Agent 开始前预处理AgentHook/BEFORE_AGENT只执行一次
按角色/用户动态调整ModelInterceptor+ 读取request.getContext()访问运行时上下文
工具读写 StateToolContext工具内访问持久状态
对话摘要/压缩MessagesModelHook+REPLACE持久更新消息列表
日志/监控ModelHook/AgentHook不修改上下文,只观察

8. 瞬态 vs 持久 决策树

要修改的内容需要在后续的 Agent 推理轮次中可见吗? │ ├── 否(只影响本次 LLM 调用)→ 使用 ModelInterceptor │ 示例:消息过滤、动态工具选择、动态 Prompt │ └── 是(需要持久保存)→ 使用 Hook + REPLACE 或 ToolContext 示例:对话摘要、工具写入状态

http://www.jsqmd.com/news/989977/

相关文章:

  • 如何用3步解决Windows和Office激活难题?
  • make-sense.ai:革命性的浏览器端AI图像标注工具
  • Revit2GLTF:BIM模型到Web3D的高性能转换架构与实施策略
  • 惠普OMEN游戏本终极性能控制工具:OmenSuperHub完整指南
  • 揭秘微信数据安全:3步掌握聊天记录备份的核心方法
  • 2026舞狮表演优质机构推荐:庆典公司/开工仪式/投产仪式/摄影摄像公司/模特公司/活动策划公司/执行保障力突出 - 优质品牌商家
  • qobuz-dl终极指南:快速打造你的无损高解析度音乐收藏库
  • 2026年靠谱的粉末成型压机/电动工具齿轮粉末成型压机/宁波家电电机齿轮粉末成型压机/宁波气门导管座圈粉末成型压机厂家精选合集 - 品牌宣传支持者
  • 如何用WeChatMsg构建个人AI记忆库:三步实现聊天数据价值挖掘
  • 还在用 Anaconda?Miniforge:conda-forge 官方极简安装器,内置 Mamba,6 大架构全覆盖,5 分钟从零搭建 Python 环境
  • 啤酒设备行业主流供应商综合能力分析及选择参考(2026版) - 优质品牌商家
  • 3步完成黑苹果配置:OpCore-Simplify让OpenCore EFI生成如此简单
  • 做GEO优化多久可以看到获客效果
  • 2026年AI写作辅助平台推荐:9款高效AI工具终极指南
  • PoseLib:面向校准相机姿态估计的高性能最小求解器库
  • 数据的加密与解密(04:18)
  • 深入浅出吃透ARMS原理与实战用法
  • 收藏!普通人也能入局!国产AI大模型商业化落地,低门槛抓住红利机遇
  • 三维动画服务商综合能力分析:2026年行业格局与选型参考 - 优质品牌商家
  • 2026年知名的女装联营/临猗女装拿货加盟/零库存女装加盟/临猗女装整店输出品牌排行 - 行业平台推荐
  • 2026年热门的女装实体店合作/临猗女装集合店/临猗女装实体店合作哪个品牌好 - 行业平台推荐
  • 数据的加密与解密(04:26)
  • 2026年质量好的宜宾全屋定制装修/宜宾装修专业靠谱公司 - 行业平台推荐
  • FPGA项目实战:用Vivado ROM IP核在AX7A035开发板上实现一个简易正弦波信号发生器
  • GEO优化一般多久上百度首页
  • Python量化开发者的痛点:通达信数据如何与Python生态无缝对接?
  • AMD Ryzen处理器调试工具SMUDebugTool:深度掌控硬件性能的完整指南
  • 2026年知名的宜宾毛坯房装修/宜宾一站式整装装修/宜宾透明化装修服务好的公司 - 品牌宣传支持者
  • 2026年热门的宁波粉末成型伺服液压机/粉末成型伺服液压机/氧化铝陶瓷干压成型伺服液压机定制加工厂家推荐 - 行业平台推荐
  • 12501华夏之光永存:黄大年茶思屋榜文125期 第1题 弱网视频通话极低码率AI视频编解码