从提示工程转向 上下文工程,6种让LLM在生产环境中稳定输出的技术

📅 发布时间:2026/7/14 10:33:07 👁️ 浏览次数:
从提示工程转向 上下文工程,6种让LLM在生产环境中稳定输出的技术
RAG系统返回了完美的文本块提示词写得很漂亮但LLM还是在产生幻觉文档加得越多回复质量反而越差。这些问题问题不出在提示词上而是出在上下文上。提示工程告诉模型怎么说话context engineering 控制模型说话时看到什么。以下是把生产系统和Demo区分开的6种上下文工程技术。什么是 Context EngineeringContext engineering 是在运行时决定AI模型看到什么信息、何时看到、以何种结构看到的工程实践。提示工程关注的是如何提问context engineering 关注的是提供什么。实际系统中大语言模型出错往往不是因为理解不了指令而是因为看到了太多不相关的信息、相互矛盾的数据或者缺失了关键事实。Context engineering 把上下文当作一条动态管道来处理而非一段静态提示词选对文档而不是全量灌入将长文档压缩为面向任务的摘要在检索之前重新表述模糊的用户查询跨会话注入记忆和用户状态用实时工具和数据锚定答案组织所有输入让模型知道什么最重要。一句话概括context engineering 是在生产环境中控制模型注意力的手段。上下文工程做得好小模型也能有不错的表现做得差最好的模型照样幻觉。选择性检索别再把什么都往里塞如果我们把50个文档全部塞进上下文指望模型自己找到需要的内容。即便上下文窗口足够大模型的注意力分布仍然不均匀它会重点关注开头和结尾的 Token中间部分被忽略。这就是所谓的lost in the middle效应。正确的做法是评分、重排、裁剪只让相关且不重复的片段进入上下文窗口。以下三步逐层过滤。相关性重排初始搜索基于向量相似度或关键词匹配返回前50个结果但相似不等于相关。交叉编码器会把查询和每个文档放在一起联合阅读重新排序。速度慢一些准确度高得多重排之后只保留前5个。冗余消除同一个概念在文档库里出现在多个地方是常态比如营销材料、技术规格、FAQ都可能提到同一功能。用 Embedding 对相似文本块做聚类余弦相似度超过0.9的基本就是重复内容删掉一个即可。模型不需要看同一个事实10遍。任务感知过滤利用元数据做筛选。每个文档都应打上标签文档类型、最后更新日期、产品版本、地区、部门。查询进来时按相关维度过滤。举个实际例子查询是总结最新的退款政策变更。过滤之前向量搜索返回50个关于退款的文本块有些来自2018年旧政策有些是其他公司的文档有些是从未面向客户的内部备忘录。LLM看到了14天和30天窗口期的矛盾说法、不同的排除条款、相互冲突的流程试图综合所有信息后幻觉出了一条根本不存在的政策。过滤之后加上regionCN和updated_at 2025-01-01两个条件立刻排除40个文本块。剩余10个用交叉编码器重排保留前5个再检查近似重复余弦相似度 0.9。最终送进上下文的只有3个高相关、无冗余的文本块。LLM现在看到的是清晰的政策声明、具体的时间线和例外清单——全部最新全部对齐。没有幻觉没有混淆。效果提示更短回答更清晰没有矛盾。实验数据显示移除噪声上下文后准确率提高15–30%Token消耗降低20–40%。但真正的收益在于可追溯性——确切知道模型看到了什么上下文才能调试失败50个文本块全灌进去只能靠运气。实现上可以从简单处着手给所有文档加last_updated时间戳按日期过滤仅凭这一步就能消除大部分噪声。接着加重排再加去重根据实际效果逐步叠加复杂度。上下文压缩让每个 Token 都有价值长篇原始文档容易撑破上下文限制同时稀释注意力。多个案例研究表明经过压缩可以在保持甚至提升准确率的同时砍掉50–75%的 Token。核心思路是在把长文档放进上下文之前将其压缩成面向当前任务的密集摘要不是通用摘要而是针对当前查询定制的摘要。三种压缩策略各有侧重。带约束的LLM摘要不要只说总结这个文档而是说总结这个文档只保留2025年1月之后关于定价变更的事实。约束条件指明了保留什么、丢弃什么。每个检索到的文档根据查询生成各自的约束。产出从3000个 Token 缩减到5–10个要点。句子级评分用较小的模型如BERT变体为每个句子计算与查询的相关性分数按分数排序后只保留前20%。这种方法叫Context-Preserving Compression速度快效果好自动留下最相关的信息。层次化摘要适合非常长的文档。先按章节分块每个章节独立生成摘要再把这些摘要归纳成一个元摘要。最终形成三级结构完整文档 → 章节摘要 → 最终摘要。根据上下文预算选用合适的层级。看一个实际例子。查询是比较API文档中Plan A与Plan B的速率限制。API文档共30页涵盖认证、速率限制、错误代码、Webhook、分页、SDK和变更日志其中只有2页涉及速率限制。检索管道取回3个相关章节共30页每章10页。LLM摘要器收到的指令是“仅提取Plan A和Plan B的速率限制和配额包括具体数字忽略认证、示例和其他功能。”第一个章节的摘要从10页压缩到100个 Token“Plan A1000次请求/小时10,000次/天。Plan B5000次请求/小时50,000次/天。两个计划均允许1分钟内20%的突发流量。”第二个章节的摘要“速率限制错误返回HTTP 429。Retry-After头部指示等待时间。速率限制在UTC午夜重置。”第三个章节的摘要“企业版计划可定制速率限制。请联系销售团队。”三份摘要合计500个 Token加上查询一起送入最终生成。模型看到的恰好是它需要的内容不必在认证流程或SDK示例里翻找。模型拿到的是聚焦后的信息而不是期望它从30页文档里正确提取相关部分。代价是多了一步延迟因为每个文档额外做一次LLM调用3个文档就是3次。但最终生成调用中节省的 Token 往往更值钱。具体值不值得要看场景文档超过2000个 Token 时压缩的收益大于开销。层次化布局结构本身就在传达重要性不要把所有内容混成一面文字墙。LLM对上下文前部和后部的注意力分配不同结构化的分区能帮助它区分指令、数据和示例。想想阅读研究论文的过程摘要是总结引言提供背景方法部分有技术细节讨论部分解读结果。这种结构让信息提取变得高效LLM从同样的结构中受益。因此需要在上下文内部设计一套固定的、分区清晰的格式。以下是一个经过验证的布局[System Rules] You are a precise financial research assistant. Answer only from provided context. If information is missing, say I dont have that information. Never make assumptions about numerical data. [Task] Goal: Answer user question using context below. Output format: Start with direct answer, then provide supporting details. [User Profile / Memory] - Risk tolerance: Low - Investment horizon: 5-10 years - Region: India - Previous sessions: Asked about HDFC Bank 3 times, showed interest in banking sector - Preferences: Conservative investments, dividend-paying stocks [Retrieved Context] DOC 1: HDFC Bank Q4 2024 earnings report - Revenue: ₹45,000 crores (up 15% YoY) - Net profit: ₹12,000 crores (up 18% YoY) - NPA ratio: 1.2% (improved from 1.5%) DOC 2: Competitor analysis Q4 2024 - ICICI Bank revenue growth: 12% YoY - SBI profit growth: 10% YoY - HDFC Bank leading in digital banking adoption [Tool Outputs] - live_price(HDFCBANK): ₹1,842.50 (updated 2 minutes ago) - news_summary(HDFCBANK): Announced dividend of ₹19 per share for FY2024. Ex-dividend date March 15, 2025. - sector_analysis(Banking): Banking sector up 8% this month due to positive earnings [Question] User: Whats the latest on HDFC Bank?系统规则排在最前面模型在任何其他内容之前先看到它们用来划定行为边界。任务说明紧随其后让模型明确目标。用户档案提供个性化信息——模型知道该用户偏好保守投资之前多次问过HDFC于是在组织答案时会相应调整侧重点。检索到的文档被标记为源材料模型将其视为引用依据。工具输出标记为实时数据意味着当前且权威不是猜测。问题放在最后模型在看到要回答什么之前已经掌握了所有上下文。分区带来的好处很直接每种信息的角色一目了然矛盾指令减少各部分可以独立替换而不破坏整体。在多智能体系统中这一点尤为关键不同智能体需要不同的上下文布局。为什么比非结构化上下文更好可以自己做个测试把5000 Token 的指令、数据、示例和问题全部混在一起扔给LLM再用同样的信息以结构化分区呈现。对比准确率结构化版本在多数领域胜出10–20%。原因在于注意力模式LLM在训练中学到了开头和结尾的文本更重要。把关键指令放在开头、问题放在结尾是在顺应模型的注意力偏好而非与之对抗。动态查询重构修复模糊问题用户提出的问题往往是模糊的缺少关键词、实体、时间范围。直接拿原始问题去检索效果不好应该先让LLM重写或扩展查询。已有研究证实在检索前生成一条优化过的搜索查询能带来可观的准确率提升。这看起来有点混乱因为多加一步似乎应该让事情变复杂但是其实逻辑很简单模糊的查询返回模糊的结果精确的查询返回精确的结果。三种可行的模式。澄清优先适用于智能体场景与其猜用户什么意思不如直接问。智能体回复要比较业绩表现需要明确几个信息——哪个时间段包含哪些竞争对手最关注哪些指标收入、利润还是市场份额用户给出具体条件后检索随之变得精确。这种策略只适用于多轮对话的智能体单次问答系统用不上。但在智能体场景下效果很好——用户并不介意回答两三个澄清问题如果换来的是更准确的答案。HyDEHypothetical Document Embeddings用户问产品最新的改进有哪些不直接用这个问题去搜索而是让LLM先生成一段假答案“最新的产品改进包括重新设计的仪表板、40%的加载速度提升、新增的协作功能和增强的移动端应用。“把这段假答案做 Embedding 后用于检索。为什么有效因为假答案的措辞和实际文档的措辞一致。文档里不会写最新的改进是什么”而会写重新设计了仪表板”“加载时间缩短了40%”。假答案的 Embedding 比原始问题的 Embedding 更贴近真实文档。多查询扩展对原始查询生成3–5个改写版本。“最新产品改进可以展开为最近的产品更新”“本季度发布的新功能”“产品增强变更日志”“2.0版本有什么新内容”。每个查询分别检索合并去重。这种方式能覆盖语义变体和不同的表述习惯。举个实际例子。用户问上季度的表现与竞争对手相比如何。这个问题里缺了太多信息哪些竞争对手哪一年的上季度衡量什么指标——收入、利润、市场份额还是用户增长LLM将其重写为比较2024年第四季度2024年10月至12月公司X与竞争对手A、B、C在内部财务报告中的收入增长和利润率。注意具体程度——精确的时间段、精确的竞争对手、精确的指标、明确的数据来源。检索时还会结合记忆中已知的竞争对手名单层次化布局的用户档案部分记录了该用户之前多次查询过竞争对手A和B。最终上下文对齐的是用户的意图而非用户键入的字面内容。LLM拿到的是精确数据不是模糊相关的内容。实现模式如下User query ↓ LLM rewriter: Expand this into a precise search query. Add time ranges, entity names, and specific metrics. ↓ Rewritten query ↓ Retrieval重写器需要能访问当前日期、用户档案和会话中的先前查询从而推断出上季度对应的具体日期以及竞争对手指的是哪几家公司。记忆与状态保留的是关系不只是事实初学者容易在这里混淆两个概念。检索回答的是当前问题记忆保留的是用户关系。检索是实时的每次查询都在全部文档中搜索相关文本块每次查询都被当作独立事件。今天问HDFC银行明天再问检索都是从零开始。记忆则不同它记住的是该用户三次问过HDFC银行偏好保守型股票住在印度投资期限5–10年。这些信息跨会话持续存在。正确的做法是给智能体配备持久化记忆而不是依赖一条不断增长的历史字符串。把摘要、偏好和关键事实存下来在每轮对话时重新注入。三种记忆类型各有分工。情景记忆即过去对话的摘要。例如上次会话讨论了为法律文档构建RAG系统用户关心的是如何处理100多页的合同最终决定采用512 Token 块配合50 Token 重叠的语义分块策略。注意这不是完整的对话记录而是一份200 Token 左右的摘要只保留了关键内容。语义记忆存储在向量数据库中的过去交互记录。例如用户3周前问过关于HDFC的类似问题当时问的是季度收益当前查询是关于股息公告两者都涉及HDFC的财务表现可以复用之前查询中关于公司基本面的上下文。语义记忆的价值在于发现模式用户依次问了HDFC的收益、竞争对手、风险因素可以判断他正在对HDFC做深度研究从而主动推送相关信息。偏好记忆很少变化的稳定事实。“用户是初学投资者”“偏好TypeScript”“风险承受能力低”“在医疗保健领域工作”“位于孟买时区”。这些事实影响每一次交互——初学者得到更简洁的解释低风险用户和高风险用户收到的建议完全不同。为什么记忆比塞入完整聊天历史更好设想一个50轮的对话轻松超过20,000个 Token。这些内容既塞不进上下文也不应该塞进去——大部分与当前问题无关。换一种做法50轮对话压缩为5个情景摘要1000 Token提取10个稳定偏好200 Token检索与当前问题最相关的3个历史情景600 Token合计1800 Token。信息量没有减少聚焦程度高出一个量级。只压缩和选取与当前轮次相关的部分就能避开上下文限制保持注意力清晰让智能体在不依赖更大模型的情况下呈现出个性化效果。落地时有两个执行点。每轮对话结束后做一次LLM摘要——“用户问了什么提供了什么用户表达了哪些偏好或需求”——将摘要与 Embedding 一起存入向量数据库。每轮对话开始前用当前查询在历史情景摘要库中做向量搜索取回最相关的3条再从另一张表加载稳定偏好这些不需要向量搜索每次都带上全部插入层次化布局的 [User Profile / Memory] 区块。用编程助手的场景来说明。某用户在构建一个React仪表板10次会话中先后问过状态管理、API集成、组件组合和测试方面的问题。存入记忆的内容如下技术栈React、TypeScript、Redux、Jest编码风格偏好函数组件使用 Hooks喜欢描述性变量名项目上下文为医疗保健数据可视化构建仪表板过去的问题Redux异步操作曾遇到困难最终用Redux Toolkit解决常见模式使用自定义 Hooks 发起API调用偏好Material-UI当用户提了新问题仪表板中如何处理实时更新智能体在检索之前已经从记忆中看到了完整背景React/TypeScript仪表板、Redux、Hooks偏好、医疗保健数据。于是可以直接给出上下文化的回答“考虑到现有的Redux架构和对Hooks的偏好建议使用Redux Toolkit的RTK Query配合WebSocket订阅与当前模式完全兼容。”对比一下没有记忆的智能体——它会先问用什么框架状态管理是什么数据类型是什么用户已经回答过这些问题10遍了。记忆消除的正是这种重复带来的挫败感。上下文保持聚焦智能体行为保持一致用户感到被理解。工具感知上下文把答案锚定在现实中通过Model Context Protocol (MCP)等协议配合函数调用可以让模型以统一格式看到来自工具、API和数据库的实时数据。不要依赖静态的文本知识。这正是 context engineering 的一部分——改变的是运行时有什么信息进入上下文、以何种形式进入。工具输出作为结构化上下文注入后幻觉率会大幅下降答案的时效性也有保障。纯LLM知识有一个根本问题它是静态的。训练数据有截止日期不知道今天的股价、当前天气、最新新闻或内部数据库的状态。工具通过运行时数据弥补了这个缺口但集成不当的工具会引入新的问题。MCP风格的工具注册。智能体没有硬编码的工具集成而是在运行时发现可用工具。智能体发出请求什么工具可以解决当前问题MCP服务器返回工具描述、输入Schema和能力清单模型据此决定调用什么。这意味着新增工具无需重新部署智能体——加到MCP服务器上即可智能体自动发现。生产系统正是靠这种机制扩展到数十乃至上百个工具。结构化的工具返回值。工具不应返回原始字符串而应返回带有明确键的JSONprice、date、source、confidence。把这些结果作为层次化布局中的独立区块插入标记为权威事实。例如工具返回{price: 1842.50, currency: INR, timestamp: 2025-02-19T14:30:00Z, source: NSE, change: 2.3%}模型看到的是结构化数据知道1842.50是价格而不是文本中随意出现的一个数字。带护栏的回答。对可靠性至关重要。在指令中写明只从 [Tool Outputs] 和 [Retrieved Context] 中回答。如果信息缺失说’当前数据源中没有该信息。绝不编造数字或事实。一旦价格工具调用失败模型会如实说明而不是自行猜测。用一个金融助手的场景贯穿整个流程。查询是HDFCBANK的最新股价和今天的新闻。智能体通过MCP发现可用工具get_live_price、get_news、get_historical_data、get_competitors、get_analyst_ratings。根据查询判断需要调用get_live_price和get_news拿到结构化响应{ get_live_price: { symbol: HDFCBANK, price: 1842.50, currency: INR, timestamp: 2025-02-19T14:30:00Z, change: 2.3%, volume: 12500000 }, get_news: { articles: [ { headline: HDFC Bank Announces ₹19 Dividend, summary: Board approves dividend of ₹19 per share for FY2024, date: 2025-02-19, source: Economic Times } ] } }这些内容插入层次化布局的[Tool Outputs]区块末尾附上用户问题。模型生成的答案是“HDFC Bank当前交易价格₹1,842.50今日上涨2.3%。该银行宣布FY2024每股派息₹19。”注意模型引用了来自工具输出的具体数字没有产生幻觉也没有把股息金额和股价搞混。这里的关键信息是提示词本身很简单真正起作用的是工程化后的运行时上下文。模型表现好是因为它看到了结构化的权威数据而不是因为有一段完美的提示词。实现路径上建议从3–5个关键工具开始确保它们稳定可靠后再扩展。不要第一天就试图接入50个工具——每个工具都需要错误处理、重试逻辑、超时管理和结果校验先把基础设施为少数工具搭建好。决策框架选择性检索适用于文档集合庞大1000个文档、检索返回结果过多20个文本块、上下文接近容量上限32K Token 附近、或需要控制成本的场景。压缩适用于文档篇幅长单个超过5000 Token、所需信息深埋在文本中、或按 Token 计费且需要成本优化的场景。如果文档本身已经很短少于1000 Token压缩带来的开销不划算。层次化布局适用于多智能体系统不同智能体需要不同的上下文结构、多种上下文来源并存文档、工具、记忆同时出现、或需要分段调试结构化分区让定位故障变得容易的场景。单轮问答且只有一个来源时布局多半是多余的。查询重构适用于用户常提出模糊问题消费类产品中的常见情况、领域有专业术语但用户不使用医疗、法律、金融领域、或查询与文档之间存在词汇鸿沟用户说退款文档写退货授权的场景。记忆适用于对话式智能体聊天产品、编程助手、用户跨会话回访有登录体系的B2B产品、需要个性化推荐、偏好起决定性作用、或对话轮数超过20轮导致历史上下文溢出的场景。工具感知上下文适用于答案依赖实时数据股价、天气、库存、构建的是智能体而非纯对话机器人智能体会采取行动聊天机器人只输出文本、准确性取决于信息时效不能凭空生成数字、或需要降低幻觉率工具提供事实依据的场景。总结每种技术都有代价。重排消耗算力压缩需要额外的LLM调用记忆需要存储空间工具需要API调用。收益是否覆盖成本需要衡量。一个更简单的管道准确率稍低一点有时候比一个复杂10倍、成本也高10倍的管道更合适。https://avoid.overfit.cn/post/7be5e3180f7641c48da7d2e73da76224by Divy Yadav