服务框架源码分析,上下文和工具如何分工

发布时间:2026/10/9 11:10:33

服务框架源码分析,上下文和工具如何分工 服务框架源码分析上下文和工具如何分工RAG 服务把检索结果、上下文和工具调用放进一次请求前先要厘清数据由谁负责、在哪一层限额、失败时怎样表达。本文以 Spring Boot 的接口边界为线索不把演练现象当作生产结论。拆开日志记录的 JSON 请求体一看里面包含了整套系统 32 个 Tool Calling 的 JSON Schema 定义加上前 15 轮没有过期的完整对话历史。大模型光是首字 Prefill 阶段就耗费了 4.8 秒。在 Spring Boot 中集成大模型能力时很多开发团队习惯把上下文Context和工具Tool/Function混在一起一股脑往 Prompt 里塞。上下文是给模型提供“状态与事实”的而工具是给模型提供“动作与能力”的。一旦两者的分工界限模糊不仅会让 Token 开销呈指数级暴涨更会导致模型因工具过多产生 Hallucination幻觉调用。# 过滤日志中单次 Tool Calling 相关的 Token 消耗量与耗时数据 grep -E TOKEN_USAGE|TOOL_INVOKE_TIME /var/log/spring-boot-ai.log | tail -n 20 # 使用 curl 测试 Agent 路由接口打印出响应头部与 HTTP 状态码 curl -i -X POST http://localhost:8080/v1/ai/context-orchestrate \ -H Content-Type: application/json \ -d {session_id:sess_99381,user_input:查询用户 10086 的未支付订单并发送催缴短信}动态上下文编排与工具分发流图要在 Spring Boot 内部优雅实现上下文与工具的分工必须在 Controller / Service 层之前增加一道上下文与工具编排器Orchestration Layer。整体流转的核心逻辑上下文Context做减法通过滑动窗口与滚动摘要机制将膨胀的对话历史严格压制在 Token 预算限制线以内。工具Tools做按需加载绝不注册全局全量 Tools而是通过意图路由Intent Matcher扫描当前 Request 依赖的最小工具子集实现毫秒级的工具注入。生产级上下文编排与工具分工器源码实现下面基于 Spring Boot 实现一套带 Token 预算控制与 Tool 按需过滤的编排器。package com.company.ai.boot.orchestrator; import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; Service public class AgentContextOrchestrator { private static final Logger log LoggerFactory.getLogger(AgentContextOrchestrator.class); private static final int MAX_CONTEXT_TOKENS 3000; private final MapString, ToolDefinition globalToolRegistry new ConcurrentHashMap(); private final ObjectMapper objectMapper; public AgentContextOrchestrator(ObjectMapper objectMapper) { this.objectMapper objectMapper; registerDefaultTools(); } private void registerDefaultTools() { globalToolRegistry.put(queryOrder, new ToolDefinition(queryOrder, 查询用户订单, {\type\:\object\,\properties\:{\user_id\:{\type\:\string\}}})); globalToolRegistry.put(sendSms, new ToolDefinition(sendSms, 发送短信通知, {\type\:\object\,\properties\:{\phone\:{\type\:\string\},\msg\:{\type\:\string\}}})); globalToolRegistry.put(queryStock, new ToolDefinition(queryStock, 查询商品库存, {\type\:\object\,\properties\:{\sku_id\:{\type\:\string\}}})); } public ExecutionPayload orchestrate(String userInput, ListChatMessage historyMessages) { log.info(开始编排上下文与工具当前历史消息条数: {}, historyMessages.size()); // 1. 上下文按 Token 预算从后往前截断Pruning ListChatMessage prunedHistory pruneContext(historyMessages, MAX_CONTEXT_TOKENS); // 2. 根据用户输入做工具意图路由Scoped Tools Loading ListToolDefinition matchedTools resolveRelevantTools(userInput); log.info(编排完成: 保留历史消息 {} 条, 注入工具 {} 个, prunedHistory.size(), matchedTools.size()); return new ExecutionPayload(userInput, prunedHistory, matchedTools); } private ListChatMessage pruneContext(ListChatMessage history, int maxTokenBudget) { ListChatMessage result new ArrayList(); int accumulatedTokens 0; // 从最近的消息开始倒序累加 for (int i history.size() - 1; i 0; i--) { ChatMessage msg history.get(i); int estimatedToken estimateToken(msg.content()); if (accumulatedTokens estimatedToken maxTokenBudget) { log.warn(触发 Token 预算墙截断第 0 到第 {} 条早期历史, i); break; } accumulatedTokens estimatedToken; result.add(0, msg); // 保持时间正序 } return result; } private ListToolDefinition resolveRelevantTools(String userInput) { ListToolDefinition selected new ArrayList(); // 简单意图路由规则生产环境可换为 Fast Embeddings 相似度匹配 if (userInput.contains(订单) || userInput.contains(买)) { selected.add(globalToolRegistry.get(queryOrder)); } if (userInput.contains(短信) || userInput.contains(通知)) { selected.add(globalToolRegistry.get(sendSms)); } if (userInput.contains(库存) || userInput.contains(货)) { selected.add(globalToolRegistry.get(queryStock)); } // 如果均未匹配只给默认查询类工具决不全量注入 if (selected.isEmpty()) { selected.add(globalToolRegistry.get(queryOrder)); } return selected; } private int estimateToken(String text) { if (text null || text.isBlank()) return 0; // 中文按 1 字符 ≈ 0.6 Token 粗略换算 return (int) (text.length() * 0.6); } public record ChatMessage(String role, String content) {} public record ToolDefinition(String name, String description, String jsonSchema) {} public record ExecutionPayload(String prompt, ListChatMessage history, ListToolDefinition tools) {} }上下文与工具接口契约设计规范在 Spring Boot Controller 提供给前端或下游微服务时错误语义与契约必须极其清晰。1. 明确区别“业务逻辑失败”与“Tool Calling 失败”模型调用工具失败时如queryOrder返回用户不存在这属于Tool Business Failure应当将错误信息原样作为 Tool Message 返回给 LLM 重新生成回答而不是在 HTTP 层直接抛出500 Internal Server Error。2. 状态隔离与错误语义定义在 RESTful API 返回时建议采用三级状态码区分问题属性{ code: TOOL_EXECUTION_TIMEOUT, message: 下游订单微服务响应超时1500ms, error_type: ENGINEERING_RETRYABLE, detail: { target_tool: queryOrder, elapsed_ms: 1502 } }MODEL_SCHEMA_INVALID模型生成的工具参数无法通过 JSON Validation网关可自动重试一次。ENGINEERING_RETRYABLE工具执行抛出网络超时重试闸门接管。CONTEXT_WINDOW_EXCEEDED对话历史超长强行触发压缩。分清了上下文的“记忆”角色与工具的“手脚”角色Spring Boot 应用在大模型交互中才能保持高吞吐和低耗时。
延伸阅读

更多相关文章

2026/10/7 17:46:15

用系统语言重写服务前的评审方法

用系统语言重写服务前的评审方法 评审先追不变量 Rust 重写服务的评审不该停在“能否编译”。先把 FFI 边界、异步取消与错误码映射写成可检查的约束:什么情况下允许、失败时由谁释放资源、调用方能依赖什么。随后沿真实调用链检查这些约束有没有被绕开。 逐项检查 …

2026/10/9 11:06:27

清理大师的完整思路:深层垃圾定位与持久优化实战

说到“清理大师”,我第一反应是前阵子帮一个朋友处理他卡到怀疑人生的旧手机。那台机子用了快三年,打开微信要转三四秒圈圈,相册滑一滑就掉帧,64G的存储常年飘红。我花了大概一个晚上,没有刷机,没有恢复出厂…

2026/10/9 11:06:27

JavaWeb期末大作业:二手闲置交易系统设计与实现全解析

简介:这是一套面向JavaWeb期末大作业与课程设计的二手闲置物品交易系统完整源码,适合高校计算机相关专业学生参考与二次开发。平台围绕闲置物品的发布、浏览、交易与个人管理等核心场景展开,代码包含用户、商品、订单、留言等模块&#xff0c…

2026/10/9 11:06:27

医疗KBQA问答系统从零搭建:21万实体关系与朴素贝叶斯的闭环实践

简介:面向希望入门知识图谱问答的开发者,整套资源从零搭建了一个医疗领域KBQA问答系统,覆盖7类实体、约3.7万实体与21万实体关系,可完整体验意图识别、实体抽取、图谱构建和答案检索等核心流程,适合作为学习或演示项目…

2026/10/9 11:01:26

求解器并发架构:进程与线程的边界与协同

很多跑算法或做工程的同学,嘴上挂着“并发”和“多线程”,一到真正碰求解器这类计算密集型任务,就翻车。要么内存爆炸,要么直接死锁卡死,要么 CPU 都跑满了但业务吞吐量上不去。这些问题的根源,往往不是数学…

2026/10/8 10:03:18

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/8 10:03:20

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/8 6:05:44

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 0:04:27

毕业论文初稿完成后首次进行AIGC疑似度自查的摸底与分流策略

毕业论文初稿完成后首次进行AIGC疑似度自查的摸底与分流策略当数万字的学位论文初稿经历开题、实验、问卷与多轮文献梳理最终成形时,绝大多数研究生都会面临一道全新的形式审查关卡:AIGC 疑似度排查。在高校毕业审核流程中,盲审前的文本检测通…

2026/10/9 0:04:27

食堂节能改造源头工厂,商用厨房设备焕新方案广受好评

商用厨房作为餐饮经营、单位供餐的核心后勤阵地,其设备配置、动线规划与运维体系直接决定后厨作业效率、运营成本与合规性。从基础的灶具、制冷存储设备,到油烟净化、水处理等配套系统,每一个环节的合理性都与食品安全、能耗管控、消防安全挂…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑