多模态AI模型落地时,最容易翻车的地方往往不在模型本身,而在上下文窗口里塞了什么、怎么塞的。我做过不少多模态项目,从早期的简单图文问答到后来的长视频分析,踩过最痛的一个坑,就是没有上下文预算意识:给模型喂了一张4K原图,光一张图就烧掉上万Token,回答依然答非所问。今天这篇内容,从提示工程架构师的视角,把上下文工程优化的完整方法论拆开来讲,包括预算公式、分级策略、排序重构、文本化补偿、效果评估和问题排查,适合正在做多模态应用、智能客服、知识库问答的工程师参考。
1. 从提示工程到上下文工程:多模态场景下的思路升级
1.1 提示工程与上下文工程到底差在哪
传统提示工程解决的是“怎么说清楚”的问题:角色怎么设定、指令怎么措辞、输出格式怎么约束。这套方法在纯文本时代非常有效,因为文本输入的成本是可以预期并且相对可控的。可一旦进入多模态,情况完全变了。一张截图、一段视频、一段音频,体积和Token消耗都远超出文本,且波动巨大。你即使把指令写得再漂亮,模型还没来得及看你的指令,上下文窗口就被一张高清原图塞满了。
上下文工程关注的不是“措辞”,而是整条上下文的资源配置:什么东西该进上下文、以什么形态进、占多少预算、放在哪个位置、和谁相邻。打个比方,提示工程像是写一份精致的菜单,上下文工程则是规划整个后厨的备餐与上菜顺序。菜单写得再好,后厨备菜乱了,菜一股脑全倒进锅里,端出来照样没法吃。
两类工作的差异可以简化成一张对照表:
| 优化维度 | 传统提示工程 | 上下文工程 |
|---|---|---|
| 核心对象 | 指令措辞、角色定义 | 上下文窗口内的资源分配 |
| 主要约束 | 表达清晰、意图明确 | Token预算、信息密度、依赖顺序 |
| 输入形态 | 纯文本 | 文本、图像、音频、结构化数据混合 |
| 评估重点 | 输出是否符合指令 | 输出质量、单次成本、无效信息占比 |
我自己的体会是,要把上下文工程单独拎出来做,是因为它和提示工程的优化方向经常冲突。比如为了让模型理解得更细,我们习惯在提示词里加很多限定和例子;但在多模态场景下,这些额外的文本和示例会挤占图片和视频的空间。这时候必须做取舍,而取舍的依据,恰恰是上下文工程这套预算与优先级逻辑。
1.2 多模态场景的三个致命痛点
第一个痛点是Token估算不可控。文本大致可以按字数估,一张图片到底消耗多少Token,不同模型、不同分辨率、不同编码方式之间的差异非常大。我在项目中见过同一张图在两种模型下Token消耗相差三倍的情况。视频更夸张,按帧算,一秒钟视频按两帧采样就是两张图,按30秒算就是几十张图的量级。
第二个痛点是信息密度分布严重不均。一张纯白背景的截图和一张复杂的数据图表,Token消耗可能差不多,但信息量差了几个数量级。于是常见的情况是:上下文被大量低信息量内容占满,真正关键的视觉细节反而被压缩或挤出。
第三个痛点是上下文失忆会提前到来。文本时代,几十轮对话也未必能把窗口填满;多模态时代,几段视频、十几张截图就能把窗口撑爆,模型直接“忘了”最开始给它的参考图。不是模型能力不行,而是它根本没空间记住。
这三点叠加下来,多模态应用的优化节奏就变成了:想提升质量,得先控制上下文体积;想控制体积,又怕丢掉关键信息。绕开这个矛盾的办法,就是建立一套显式的上下文工程流程。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 上下文窗口的容量规划与预算分配策略
2.1 预算公式与Token基准测算方法
上下文窗口不是无限内存,任何一段输入都有代价。我习惯把预算拆成下面这个公式:
code复制总上下文预算 = 系统提示词 + 多模态输入 + 历史摘要 + 当前查询指令
在此基础上还要扣两块硬开销:一块是模型生成回复时占用的输出Token,另一块是防止意外溢出的预留缓冲,一般取总额的10%到20%。
举个例子,假设模型上下文是32K,单次最大输出4K,系统提示词经过精简后实测1.2K,预留取10%即3.2K。那么固定开销是:
code复制固定开销 = 1.2K(系统提示词) + 4K(输出上限) + 3.2K(预留) = 8.4K
可用输入预算 = 32K - 8.4K = 23.6K
这23.6K再按任务类型分配给多模态输入、历史会话和当前查询。我见过很多人把上下文加到128K就放松了预算管理,结果成本直线上升,效果却没变好。实际上大部分任务根本用不到那么大的窗口,选一个刚好够用的模型,成本低、延迟小、更可控。
关于各形态输入的Token粗估,我一般参考这个量级:
| 输入类型 | 估算基准 | 备注 |
|---|---|---|
| 纯文本 | 1个汉字约1到2 Token | 按实际分词结果为准 |
| 图片 | 512×512约1000到1500 Token | 分辨率越大,Token按面积比例上升 |
| 视频 | 采样帧数 × 单帧Token | 常按每秒1到2帧抽样 |
| 音频 | 每秒约60到100 Token | 不同模型差异较大 |
这里要特别提醒一句:不同模型对图片的Token化逻辑差别很大,上面只是通用量级,上线前务必拿真实输入在当前模型上实测一轮,否则预算表全是纸上谈兵。
2.2 按信息密度分级:L1/L2/L3三类输入策略
把预算算清楚之后,下一步就是决定每种输入用什么形态进入上下文。我习惯把输入分成三个级别。
L1是文本化替代。也就是用OCR文字、一句话描述、结构化元数据来替代原图。适合那些“只要知道图里写了什么、大概是什么场景”就能回答的任务。L2是中度视觉。把图片压缩到512到768的分辨率,或者把复杂图表转成Markdown表格。适合需要看布局、看颜色、看比例关系的任务。L3是高保真视觉。保留原图分辨率,或者使用视频关键帧序列,适合需要做精细对比、微小瑕疵检测、图像取证这类任务。
决策时先问一个问题:模型必须看到像素本身才能判断,还是通过文字描述就够了?能靠文字就走L1,需要看轮廓和粗粒度结构走L2,必须看到纹理和细节差异才走L3。
很多团队一上来就把所有图片按L3处理,理由是“怕丢信息”。但无脑高保真的代价是上下文被迅速塞满,真正的高价值图片反而没有空间。一个更好的做法是“能裁剪就裁剪”,只把感兴趣区域裁出来送进去,等于把高分辨率图片的Token花在刀刃上。比如做截屏分析,只需要裁出报错弹窗那一块,其余桌面背景全是噪声。
2.3 一个可抄作业的上下文预算表
拿我做过的智能工单质检系统举例,原始输入包括用户截图、文字描述、历史会话和检索出来的知识库条目。优化后的上下文预算表长这样:
| 内容块 | 原始形态 | 处理后形态 | 预估Token | 优先级 |
|---|---|---|---|---|
| 系统提示词 | 固定QA规则 | 精简为要点,保留JSON输出结构 | 1200 | 固定 |
| 当前查询 | 用户自然语言 | 清洗、补齐必要信息 | 300 | 高 |
| 用户截图 | 1920×1080高清截屏 | 压缩至512宽 + OCR文本 + 一句话描述 | 1200 | 中 |
| 历史会话 | 10轮聊天原文 | 滚动摘要,保留最近2轮原文 | 1200 | 低 |
| 知识库补充 | 检索出的3条FAQ | 每条压缩到200字以内 | 600 | 中 |
合计约4500 Token。如果选用一个14K上下文的模型,还能剩9000多Token余量,留给突发情况非常从容。这里有个设计原则:优先级低的内容在预算紧张时最先被丢弃或进一步压缩。比如历史摘要可以从800字压到300字,检索补充可以从3条砍到2条。
这张表看着简单,背后的关键是把“处理前”和“处理后”分列,把Token和优先级显式写出来。只要团队里每个人都按这张表执行,上下文就不会莫名其妙被塞爆。
3. 多模态上下文的组织重构与文本化补偿
3.1 三类排序策略与混合方案
预算确定了内容,排序决定模型先看到什么、后看到什么。顺序对多模态模型的影响比纯文本更大,因为上下文一旦被视觉内容占满,后面的指令很容易被淹没。
第一类是时间倒序,最新信息放在最前面。适合客服、持续会话类任务,模型更容易回应最新的会话状态。风险是早期的全局信息会被挤出窗口。第二类是信息密度优先,把结论、风险点、关键证据放最前,支撑材料放在后面。适合分析、审核类任务。风险是时间线会被打乱,模型可能误解事件的先后关系。第三类是主题分组,把所有与某个对象相关的图像和文本放在一组,再放另一组。比如把“用户A的截图”和“用户A的历史反馈”放在相邻位置,模型交叉引用时不容易串。
三种策略各有适用场景,我实际项目中常用的是混合方案:大结构按信息密度排序,小结构按主题分组,组内再按时间排列,同时给每个块打上时间戳标注。这样模型既有全局的轻重缓急,又能看出时间线的先后。
排序策略的对比如下:
| 策略 | 优势 | 风险 | 适用场景 |
|---|---|---|---|
| 时间倒序 | 状态对齐好 | 早期关键信息易丢 | 客服、持续会话 |
| 信息密度优先 | 结论输出稳定 | 时间线索混乱 | 审核、数据分析 |
| 主题分组 | 跨模态关联强 | 排序计算成本更高 | 多对象对比、跨模态检索 |
3.2 视觉信息的文本化补偿机制
多模态模型的视觉理解能力很强,但不代表所有视觉信息都必须原样塞进上下文。文本化补偿的核心思路是:用OCR、图像描述、结构化元数据,把图里的信息转成文本,再用大约几十分之一的Token达到同等甚至更好的效果。
举一个报错截图处理的例子。原始输入是一张高清截屏,约需要2000到3000 Token。处理管线是这样跑的:第一步OCR提取关键文本,得到“0x80070005 Access Denied”;第二步用一句话描述整张图,“用户在文件管理器中删除目录时弹出权限错误截图”;第三步补充元数据,包括截图时间和来源系统。最终注入上下文的是一个约120 Token的文本块,模型回答准确率没有下降,成本却降了一个数量级。
但文本化补偿不是万能的。当任务需要模型自己决定“看哪里”,比如复杂界面可用性分析、画风判断、细微瑕疵检测,这时候必须保留视觉输入。我的经验是两条腿走路:先用文本和向量检索定位最相关的图,再把关键图以合适分辨率放入上下文。这相当于先靠文本缩小范围,再靠视觉做精细判断。
还有一个细节容易被忽略:文本化之后要给模型一个信任锚点。比如在描述后标注“以下OCR文本可能存在误差”,模型就不会因为某个字符识别错误而过度自信。
3.3 指令与示例的比例控制
多模态场景下,Few-shot示例非常昂贵。一个“图片加文本”的示例动辄上千Token,加上反例,几十个示例就能把整个上下文吃光。所以我建议把规则放在前面,示例放在最后兜底。
先用清晰规则加输出模板约束模型,只有当模型实在把握不住“什么样的输出才算合格”时,才加示例。示例数量控制在两个以内:一个正例,一个反例,很多时候一个正例也够了。正反例之间必须体现真正的差异,别放两个结构雷同的示例,有一大半内容是重复信息,纯属浪费预算。
举个例子,判断工单是否需要升级,与其给模型十个历史工单做参考,不如给两条决策规则加两个示例:一个升级、一个不升级。同样的任务,上下文体积减少70%,准确率基本持平。这个结果我在多个任务里反复验证过。
4. 完整落地流程与效果验证
4.1 六步搭建上下文工程链路
第一步,采集与盘点。把所有真实输入记录下来,统计文本、图片、视频、音频各占多少比例。这一步不需要复杂工具,一个日志脚本就行,每行输出请求ID、内容类型、Token估算值。
第二步,制定预算。按前面说的公式给每个任务类型设定单次上下文的预算上限。我的经验是先按比较紧的预算跑,不够再加,而不是反过来。
第三步,设计处理管线。把L1、L2、L3的判定规则固化成代码模块,包括OCR、图像压缩、裁剪、视频抽帧、描述生成。这步可以写成一个简单的预算分配器:
python复制# 上下文预算分配示例
def allocate_context_budget(total, max_output, system_tokens, reserve_ratio=0.1):
reserve = int(total * reserve_ratio)
fixed = max_output + system_tokens + reserve
usable = total - fixed
return usable, reserve
# 图片Token粗估:按面积比例
def estimate_image_tokens(width, height, base_size=512, base_tokens=1200):
ratio = (width * height) / (base_size * base_size)
return int(base_tokens * ratio)
usable, reserve = allocate_context_budget(total=32000, max_output=4000, system_tokens=1200)
print(usable, reserve) # 22680, 3200
第四步,组织排序。实现文本化补偿和混合排序逻辑,把处理后的内容块按优先级和时间戳组合成最终上下文。第五步,注入验证。在一个固定测试集上跑优化前后的对比,别一边改一边看效果,那样永远是糊涂账。第六步,上线监控。把单次成本、首轮正确率、上下文平均Token记下来,设置告警阈值,异常时能追溯。
这六步里最容易翻车的是第五步。很多人跳过验证直接上线,结果出问题也不知道是排序问题还是压缩问题。我的建议是先用人工抽看50条处理后的上下文,确认关键信息没丢,再跑自动化评估。
4.2 效果评估指标与消融检查
上下文工程的评估指标和普通提示工程不太一样。除了回答正确率,还要看上下文本身的健康度。
有效Token率是最核心的指标,计算方式是对最终输出有贡献的Token数除以总输入Token数。这个值很难精确计算,但可以做粗略估算。做法是消融检查:把某一段输入临时注释掉,再跑同一个问题,如果答案不变,说明这段输入对本次任务没有贡献,可以考虑移除或压缩。
上下文利用率也要看,实际使用Token除以预算额度。太高说明随时可能溢出,太低说明预算给得过于宽松,可能需要换一个更小的模型来省钱。
平均单次成本是上线后最需要盯的指标。它综合反映上下文体积和模型单价,优化上下文工程最直接的效果就体现在这里。
信息保留率通常靠人工抽检。每一类任务抽20条,人工标注原始输入里的关键要素是否出现在处理后的上下文中。这个指标在优化初期比准确率更重要,因为信息丢了,后面模型再怎么聪明也补不回来。
4.3 优化前后实测对比
我在内部验证集上跑过一个工单质检场景的对比,优化前是“高清原图直塞加长提示词”,优化后是完整上下文工程流程:OCR加摘要、图片压缩、历史滚动摘要、信息密度优先排序。结果如下:
| 指标 | 优化前 | 优化后 |
|---|---|---|
| 首轮准确率 | 68% | 83% |
| 单次平均输入Token | 12000 | 4200 |
| 平均响应延迟 | 5.1秒 | 2.2秒 |
| 单次上下文处理耗时 | 0 | 0.4秒 |
| 月度成本系数 | 1.0 | 约0.35 |
这个对比最让我意外的不是Token从12000降到4200,而是准确率同时提升了15个百分点。原因是优化前的上下文被大量无关像素和重复信息占满,模型的注意力被稀释了;优化后送到模型面前的都是高信息密度内容,回答自然更稳。
当然,不同任务、不同模型的绝对数值差异很大,但方向是一致的:凡是能把无效信息挡在上下文之外的方案,几乎总是质量与成本双赢。
5. 常见问题与排查技巧实录
5.1 典型问题速查表
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 模型忘了早期上下文 | 多模态内容把窗口挤满 | 检查Token分布,开启滚动摘要 |
| 图片相关回答质量差 | 降采样过度或描述缺失 | 验证处理后文本是否包含关键指标 |
| 单次成本暴增 | 图片视频无脑直塞 | 启用L1/L2策略,加OCR补偿 |
| 回答前后矛盾 | 上下文排序混乱 | 检查主题分组,补时间戳标注 |
| 指令失效、输出格式乱 | 指令被视觉内容淹没 | 把当前指令移到上下文末尾 |
| 处理管线本身太慢 | OCR加描述串行执行 | 改为并行处理,或只对关键区域跑OCR |
这些问题是项目初期最容易遇到的,大部分不是模型能力问题,而是上下文组织问题。把预算表和排序规则建立起来之后,多数现象会自然消失。
5.2 我在排查中常用的小技巧
第一个技巧是给每次请求写Token日志。记录输入形态、各段Token、成本和输出结果,一旦出问题,拿日志对照比对着模型空想要快得多。这个日志最好带上原始输入和处理后上下文的快照,否则没法回溯到底哪一步丢了关键信息。
第二个技巧是消融脚本自动化。手动一段段删输入太慢,可以写一个循环,把上下文中的每个块逐个移除,各跑一遍测试集。输出变化最大的块,就是最关键的块。
第三个技巧是双通道对照验证。对同一个任务跑纯文本版本和“多模态原图”版本各一次,如果纯文本版本的输出更好,说明视觉细节没有被充分利用,问题出在图片处理和描述环节;反过来,如果原图版本更好,说明文本化补偿做得过度,应该提高视觉保真度。
第四个技巧是坚持单一变量原则。每次只改一个参数,要么改压缩策略,要么改排序规则,不要同时动两处。我踩过太多次“一次改三处,出问题不知道赖谁”的坑。
第五个技巧是建立无效内容黑名单。常见页面签名、页脚、广告位、固定导航栏,这些内容在截屏分析里几乎永远不贡献信息,直接裁剪或过滤掉。把噪声挡在管线入口,比让模型在上下文中自己筛选要省钱得多。
我自己做下来最深的体会是,上下文工程不是一个一次性的设计工作,而是一个持续度量、持续消减的过程。每次模型版本升级、每次任务复杂度变化,这张预算表都要重新过一遍。最后再分享一个小技巧:把每次处理前的原始输入和处理后的上下文都存一份日志,出问题的时候随手就能对照,这比什么排查工具都管用。
