这道题其实问的是,在大模型应用里,我们怎么把输入这件事拆成两个不同层面来优化。一个是怎么问,也就是提示工程;另一个是给什么,也就是上下文工程。两者目标不同,但在真实落地时,往往是混合着用的。
先明确一下边界。Prompt Engineering 解决的是表达问题,比如指令怎么写、示例怎么放、格式怎么约束,核心是让模型理解我们想要什么。而 Context Engineering 解决的是信息质量问题,尤其是当模型需要依赖外部知识时,比如客服场景下的退款政策、库存数据,怎么从一堆文档里选出最相关的片段,并且组织好,再喂给模型。说白了,Prompt Engineering 是说话的艺术,Context Engineering 是选材的艺术。
具体到上下文工程,我一般把它拆成三层。第一层是检索,这里不能只用一种方法,我会把 向量检索 和 [[BM25]] 这种关键词检索结合起来做,也就是 [[Hybrid Search]],能覆盖语义相似和精确匹配两种需求。第二层是[[重排序]],因为初步召回的结果往往有噪音,我会用 [[Cross-Encoder]] 做一次精排,把真正相关的文档提到前面,同时用 MMR 算法控制多样性,避免一堆相似内容挤占上下文窗口。第三层是压缩,因为大模型上下文窗口有限,不能把所有文档都塞进去,我会用 LLMLingua 或选择性上下文,把冗余信息去掉,只保留最核心的句子。
这里有个坑:很多人以为只要检索够好就行,但实际落地时,重排序和压缩往往才是决定最终效果的关键。如果不做重排,模型可能被不相关的噪音误导;如果不做压缩,窗口一满,模型会丢失关键信息。
举个例子,电商客服的退款场景。用户问“我买的手机降价了,能退差价吗?”这时候,Prompt Engineering 负责把问题转成标准指令,比如“请根据以下政策判断是否支持价保”。但真正能回答问题的,是上下文工程从知识库中检索到的价保政策文档。如果只靠关键词“降价”去搜,可能搜到一堆促销文章,但找不到具体的“7天价保”条款。所以我会先用混合检索召回,再用重排序把“7天价保”相关片段排到前面,最后压缩成一段话,加上提示词里的指令,模型才能给出准确答复。
再一个,落地时有个前提:上下文工程的效果,高度依赖知识库的质量和切分方式。文档如果没经过清洗,或者切分粒度过粗过细,检索召回率都会崩。常见失败场景是,文档里政策条款和客服话术混在一起,模型可能把话术当成政策。所以上线前我会特别关注文档的预处理,把结构化字段(比如政策ID、生效日期)单独提取出来,方便精确匹配。
说到这,其实还有一个有意思的延伸:当上下文工程做得足够好时,我们甚至可以用 [[Zero-shot]] 提示代替 [[Few-shot]] 示例,因为模型从上下文中已经学到了足够多的模式。但这会引发一个权衡,上下文质量是否真的能替代示例的引导作用?
所以整体来看,我更倾向于把 Prompt Engineering 看成是“最后一道工序”,而 Context Engineering 是“前面的供应链”。如果供应链不行,再好的工序也出不了好产品。反过来,如果供应链很强,提示词可以做得非常简洁。在工程化时,我会优先把精力花在上下文工程上,因为它的优化空间更大,收益也更稳定。