
大模型算法应用与 Prompt Engineering上下文与工具如何分工1. 20万 Token 窗口塞满后模型开始张冠李戴把 20 万 Token 的文档全塞给大模型看起来省事线上表现却惨不忍睹。前段时间线上系统抛出警报用户查询准确率从 92% 跌到了 61%。排查日志发现模型不仅把 50 页以前定义的否定条件漏得一干二净甚至把不同产品的规格参数张冠李戴。更糟的是每次调用的 Token 开销飙升了 14 倍平均响应延迟直接拉到 8.5 秒。这类问题通常是上下文注意力稀释。大语言模型处理超长上下文时注意力分布并不均匀。开头的指令和末尾的提示词激活度高中间的大段背景数据容易被丢弃。把大模型当数据库用把所有数据硬挤进 Prompt 里既浪费算力又拉低准确率。在生产环境中应划分两者的边界上下文负责提供短期推理背景、人设约束与决策意图精确数据检索、数值计算与状态变更应交给外挂工具。----------------------------------------------------------------------------------- [示例1] | LLM 决策层 | | - 意图识别 (Intent Recognition) | | - 上下文裁切 (Context Pruning) | | - 工具调度决策 (Tool Calling Decision) | ----------------------------------------------------------------------------------- [示例1] | ------------------------------------ | | v v ------------------------------- ----------------------------------------------- | Context Window (短期) | | Tool Calling (确定性) | | - 当前会话状态 (State) | | - 向量数据库检索 (Vector DB) | | - 历史交互摘要 (Summary) | | - 精确数值计算 (Calculator) | | - 边界条件与负向提示 (System) | | - 业务系统 API (CRM/ERP Transaction) | ------------------------------- -----------------------------------------------2. 区分工作内存与手脚确定性计算坚决剔出上下文很多人在设计 Agent 架构时容易踩入一个误区试图通过优化 Prompt 强化模型的数学计算与精准匹配能力。比如要求模型计算(3485.4 * 0.85) 120.5的含税价格或者查询某一天的库房确切库存。即使在 Prompt 里写了“请一步步思考并精确计算”模型依旧可能在小数点后产生摄动抖动。语言模型本质是概率采样底层架构决定了它不擅长做离散逻辑运算。正确做法是让上下文保存用户的核心意图。如果用户提出“计算这笔订单打折后的价格”上下文只需要保留商品的原始属性和用户的优惠身份。模型识别出需要计算立刻触发calculate_discounted_price工具。由 Python 或底层微服务完成浮点数计算把确定性结果返回给模型。上下文是模型的工作内存工具是模型的手脚与计算器。把内存用来存死数据手脚就会无所适从。flowchart TD A[用户请求输入] -- B{Context 预算检查} B -- 超出预算 -- C[执行滑动窗口摘要裁切] B -- 未超预算 -- D[意图与参数解析] C -- D D -- E{需要确定性计算或查询?} E -- 是 -- F[生成结构化 Tool Call 参数] E -- 否 -- G[直接基于上下文生成回答] F -- H[Schema 参数校验门禁] H -- 校验通过 -- I[调用本地或微服务 Tool] H -- 校验失败 -- J[捕获异常并注入 Prompt 重试] I -- K[Tool 返回确定性数据] K -- L[拼接结果渲染给用户] J -- D3. 分工控制面设计滑动窗口摘要与 Pydantic 闸门实现明确分工必须在 LLM 上游搭建一层确定性的 Gateway。上下文控制层不能任由历史对话无限制叠加。需要维护一个动态滑动窗口设定系统 Prompt 预算上限比如 2040 Token。一旦历史上下文接近阈值自动触发异步 Thread 提炼 Key-Value 形式的会话摘要将原始 Token 压缩掉 7无 以上。工具拦截层同样关键。模型返回 Tool Call 指令时不应直接用eval()或无保护调用。必须用 Pydantic 对参数做类型校验与边界检查。一旦模型生成的 Tool 参数缺少必填项或类型溢出门禁层必须拦截这次错误调用并捕获 Traceback构造一条标准的 Error Message 返回给模型提示模型补全参数重试。这样能防止非确定性的 LLM 输出脏数据破坏下游数据库。4. 面向生产环境的调度器实现参数校验与确定性工具门禁以下代码演示了一个面向生产环境的 Context 与 Tool 调度器。包含了上下文 Token 截断、Pydantic 参数校验门禁以及确定性工具调用的降级机制。import json import logging from typing import Dict, Any, Callable, List, Optional from pydantic import BaseModel, Field, ValidationError # 示例1 logging.basicConfig(levellogging.INFO) # 示例1 logger logging.getLogger(agent_gateway) class DiscountCalculatorInput(BaseModel): original_price: float Field(..., gt0, description商品原价必须大于0) discount_rate: float Field(..., gt0, le1.0, description折扣率介于 0 到 1 之间) shipping_fee: float Field(default0.0, ge0, description运费非负数) def calculate_discounted_price(original_price: float, discount_rate: float, shipping_fee: float) - Dict[str, Any]: 确定性工具精确计算折后价格 final_price round((original_price * discount_rate) shipping_fee, 2) return {final_price: final_price, currency: CNY, status: success} class ContextAndToolScheduler: def __init__(self, max_context_tokens: int 4000): self.max_context_tokens max_context_tokens self.tool_registry: Dict[str, Callable] {} self.schema_registry: Dict[str, BaseModel] {} # 注册工具与对应的 Schema self.register_tool(calculate_discounted_price, calculate_discounted_price, DiscountCalculatorInput) def register_tool(self, name: str, func: Callable, schema: BaseModel): self.tool_registry[name] func self.schema_registry[name] schema def truncate_context(self, history: List[Dict[str, str]]) - List[Dict[str, str]]: 基于字符长度估算执行滑动窗口截断保留 System 提示词 system_prompts [msg for msg in history if msg.get(role) system] user_msgs [msg for msg in history if msg.get(role) ! system] total_len sum(len(m.get(content, )) for m in system_prompts) retained_user_msgs [] for msg in reversed(user_msgs): msg_len len(msg.get(content, )) if total_len msg_len self.max_context_tokens * 4: # 粗略按 1 token ~ 4 char 计算 logger.warning(fContext 超出上限已截断历史消息: {msg.get(role)}) break retained_user_msgs.insert(0, msg) total_len msg_len return system_prompts retained_user_msgs def execute_tool_call(self, tool_name: str, raw_args_json: str) - Dict[str, Any]: 确定性工具执行门禁防范非确定性参数注入 if tool_name not in self.tool_registry: return {error: fTool {tool_name} 未注册, code: 404} try: parsed_args json.loads(raw_args_json) except json.JSONDecodeError as e: return {error: fTool 参数 JSON 格式非法: {str(e)}, code: 400} schema_cls self.schema_registry[tool_name] try: # 使用 Pydantic 校验类型与数值范围 validated_args schema_cls(**parsed_args) except ValidationError as val_err: logger.error(fTool Calling Schema 校验未通过: {val_err.json()}) return {error: f参数不符合契约校验: {val_err.errors()}, code: 422} # 执行确定性 Python 函数 try: result self.tool_registry[tool_name](**validated_args.dict()) return {status: success, data: result} except Exception as ex: logger.error(fTool 执行异常: {str(ex)}) return {error: f工具运行时崩溃: {str(ex)}, code: 500} if __name__ __main__: scheduler ContextAndToolScheduler(max_context_tokens1000) # 模拟 LLM 生成的参数 mock_llm_tool_call { name: calculate_discounted_price, arguments: {original_price: 299.0, discount_rate: 0.8, shipping_fee: 10.0} } res scheduler.execute_tool_call(mock_llm_tool_call[name], mock_llm_tool_call[arguments]) print(正常调用输出:, res) # 模拟非法的 LLM 输出折扣率 1.5超出 le1.0 约束 invalid_llm_tool_call { name: calculate_discounted_price, arguments: {original_price: 299.0, discount_rate: 1.5} } res_err scheduler.execute_tool_call(invalid_llm_tool_call[name], invalid_llm_tool_call[arguments]) print(非法参数拦截输出:, res_err)5. 压测边界下游 Tool 响应突破 800ms 时的熔断策略线上很多故障并非源于模型算错而是工具拖垮了整个应用。压测到 200 并发时外挂工具调用了下游微服务 API。由于微服务数据库连接池满载Tool 响应耗时从 40ms 暴涨到 1200ms。LLM 的 HTTP 连接句柄随之挂起导致网关内存迅速吃紧引发雪崩。防范 Tool Calling 拖垮系统必须建立三道防线。第一为所有外挂 Tool 设置 Timeout 超时闸门建议设为 800ms。超时立刻触发熔断返回预设的降级文案避免下游死锁阻塞模型线程。第二做好 Tool 参数的幂等 Key 缓存。对于无状态查询类 Tool以ToolName Hash(ValidatedArgs)为 Key 写入 Redis 缓存。相同参数调用直接走 Cache 返回减少二次请求。第三严格恪守上下文与工具的界限。上下文做导航工具做执行。守住这条线大模型应用才能在流量冲击下稳住阵脚。