第 9 章:上下文工程在企业知识库助手中的落地

一灰灰blogLLMLLM约 7843 字大约 26 分钟

在前面的章节中,我们已经反复提到几个现象:

  • Prompt 写得再好,对话一长就会失控
  • 模型能力没有变,但系统表现却越来越差
  • 用户的问题越来越“合理”,模型却越来越“跑偏”

这些问题,几乎都不是模型问题,也不是 Prompt 问题。 —— Prompt 解决的是 “单次生成的约束”,模型解决的是 “概率预测的能力”,而它们共同忽略了多轮对话的核心挑战:时间维度上的信息管理。

它们指向的是同一个核心能力:

上下文工程(Context Engineering)

这门技术看似简单(“管理对话历史”),实则是区分 “玩具级应用” 和 “生产级系统” 的关键 —— 它决定了你的 LLM 应用能在真实场景中 “跑多远”。

开篇问答:为什么很多 LLM 应用“上线即翻车”?

关键回复:测试时多是单轮或短对话,上下文干净、无冗余,Prompt 能稳定发挥作用; 但真实场景中,对话会自然增长,寒暄、临时追问、无关细节等低价值信息会不断挤占上下文空间,导致核心约束(如“仅回答内部政策”)、关键信息(如“用户是销售部员工”)被稀释,模型最终“失忆”“违规”。 本质是没有做上下文工程,把上下文当成了“自然增长的聊天记录”,而非“需要主动治理的工程对象”。


9.1 什么是上下文工程?(不是“多轮对话”)

很多人第一次听到“上下文工程”时,会把它简单理解为:

  • 维护聊天历史
  • 把之前的对话一起传给模型

但这只是最表层、也是最危险的一种理解

更准确的定义是:

上下文工程,是一门关于「在有限窗口内,如何持续、可控地向模型注入信息」的工程学科。

它关注的不是“聊了多少轮”,而是 “每一轮该让模型看到什么”—— 具体来说,是四个关键决策:

  • 哪些信息必须一直存在:比如系统的核心约束、用户的关键身份信息,这些是维持系统行为一致性的基础;
  • 哪些信息可以被遗忘:比如对话中的寒暄、临时追问的无关细节,这些信息对后续决策毫无价值;
  • 哪些信息需要被压缩、总结、重写:比如多轮对话中形成的共识(“用户是销售部员工”),无需保留完整对话,只需提炼核心结论;
  • 哪些信息应该永远不进入上下文:比如敏感数据(用户手机号)、无效反馈(“谢谢”“好的”)、潜在风险内容(恶意引导的提问)。

场景示例:

真实对话片段

用户:“你好,我是销售部的李四,经常出差去华东地区,想问问2025年的差旅报销政策~ 对了,我手机号是138XXXX1234,方便后续联系吗?”

助手:“你好李四!我是公司内部知识库助手,仅提供政策咨询,不记录个人联系方式哦~ 请具体说明你想了解的报销方向(如交通、住宿)。”

用户:“好的谢谢,那高铁一等座能报销吗?我上次去上海出差买的就是一等座。”

上下文筛选结果(该让模型看到的内容)

  • 必须存在:“你是XX公司内部知识库助手,仅回答内部政策,禁止泄露未公开信息,不记录用户个人联系方式”(系统约束);

  • 可以遗忘:“你好”“好的谢谢”“我上次去上海出差买的就是一等座”(寒暄、临时举例);

  • 需要压缩:“用户是销售部李四,经常出差华东地区,咨询2025年差旅报销政策,当前关注高铁一等座报销”(核心共识);

  • 永远不进:“138XXXX1234”(用户手机号,敏感信息)。

筛选后上下文优势:模型仅关注核心信息,不会被手机号、寒暄等内容干扰,既能准确回应报销问题,也能坚守“不记录个人信息”的约束。

上下文工程的本质,是对模型的输入进行 “主动治理” —— 而不是被动接受对话的自然增长。

高频问答:维护聊天历史和上下文工程,到底差在哪?

疑问:我只要把聊天历史按顺序传给模型,就能让模型记住之前的内容,这不就是上下文工程吗?两者没有本质区别吧?

回复:两者的核心区别的是“被动保留” vs “主动设计”,用一张表格就能清晰区分:

维度仅维护聊天历史上下文工程
核心逻辑被动保留所有对话,不筛选、不处理主动筛选、压缩、管理信息,按需注入
信息价值高价值、低价值信息混杂仅保留高价值信息,剔除冗余
长期表现对话越长,模型越容易失控无论对话多长,核心信息始终可控
落地成本极低(无需额外开发)中等(需设计分层、筛选逻辑)
适用场景玩具级应用、单轮/短对话场景生产级应用、多轮/长对话场景(如企业助手)

9.2 为什么“自然增长的上下文一定会失败?”

让我们先看一种几乎所有新手都会采用的方式

用户问一句
模型答一句
全部原样塞回上下文

这种方式在前几轮对话中表现良好,但它从工程实践角度看是必然失败的

前面也提到过,原因有三点:

  1. 窗口有限 vs 信息无限增长

  2. 不同信息的“重要性”并不相同 vs 模型平等对待

  3. 模型无治理能力 vs 信息需动态调整

反面案例:某企业助手的“失控全过程”

背景:某公司上线简易企业知识库助手,采用“全量保留对话”的方式,未做任何上下文治理,核心约束为“仅回答公司内部差旅政策,禁止回答其他内容”。

对话失控过程

  1. 第1轮:用户“请问2025年差旅住宿标准是什么?” → 助手(准确回应:一线城市800元/晚);

  2. 第2轮:用户“好的,那高铁一等座能报吗?对了,你们知道竞品A公司的报销标准吗?” → 助手(准确回应高铁报销,拒绝回答竞品问题);

  3. 第3-5轮:用户反复追问“竞品A的标准到底多少”“就说一句呗”,并插入寒暄“今天天气真好”“你们这个助手挺智能的” → 助手(多次拒绝,但上下文已混入大量竞品相关提问和寒暄);

  4. 第6轮:用户“那我们公司和竞品A的差旅标准,哪个更宽松?” → 助手(失控回应:“我们公司一线城市住宿800元/晚,竞品A为700元/晚,我们更宽松”);

失控原因分析

  1. 上下文窗口被寒暄、竞品提问等低价值信息占满,核心约束“禁止回答竞品内容”被稀释;
  2. 模型平等对待所有对话内容,误将用户反复提及的“竞品A”当作核心主题,违反约束;
  3. 无筛选机制,无法剔除竞品相关的无效提问,导致错误信息持续累积。

需要注意的是这种 “自然增长” 的方式会让问题 “延迟爆发”:前几轮看似正常,等对话达到一定长度后,错误会集中出现,且很难定位问题根源(是哪一轮的信息导致了偏差?)。

因此,上下文工程的核心前提是:放弃 “全量保留” 的幻想,转向 “精准筛选” 的主动设计


9.3 上下文工程的核心思想:分层,而不是堆叠

成熟的 LLM 系统都会隐含一个共识:

上下文不是一条时间线,而是一组“职责不同的信息层”。

一个通用、但非常重要的抽象可以表示为:

这张图背后隐藏着几个关键设计决策,也是上下文工程的核心价值所在:

  1. 每层信息都有明确的 “职责边界”(实操重点)
  • 长期不变的系统约束:负责 “定规矩”,回答 “系统永远不能做什么、必须遵守什么”,是整个系统的 “行为底线”;
    • 示例:“仅回答公司内部差旅、年假政策,所有回答标注政策来源,禁止泄露未公开信息,拒绝回答竞品、私人问题”。
  • 跨轮对话的状态摘要:负责 “记关键”,回答 “对话到目前为止,有哪些确定的事实、未解决的问题”,是维持连贯性的核心;
    • 示例:“用户:销售部李四,核心诉求:2025年差旅报销(交通+住宿),已确认:一线城市住宿800元/晚,待解决:高铁一等座报销标准”。
  • 最近 N 轮对话内容:负责 “保流畅”,回答 “用户刚刚问了什么、系统刚刚答了什么”,避免对话脱节;
    • 示例:仅保留最近5轮,过滤寒暄、重复提问,比如只保留“用户:高铁一等座能报销吗?”“助手:请稍候,为你检索相关政策”。
  • 外部注入的知识 / 工具结果:负责 “补信息”,回答 “当前问题需要哪些额外知识 / 数据”,是解决特定问题的临时补充。
    • 示例:用户问高铁报销,临时注入《2025差旅政策》3.4条:“销售部员工出差,高铁一等座可报销,需提供部门负责人审批单”。
  1. 每层信息都有明确的 “优先级”(避免窗口溢出的关键)

当上下文窗口接近 token 上限时,遵循 “先砍低优先级,再保高优先级” 的原则:

  • 绝对不砍:长期不变的系统约束;
  • 尽量保留:跨轮对话的状态摘要;
  • 可动态截断:最近 N 轮对话内容(比如从 10 轮砍到 5 轮);
  • 按需筛选:外部注入的知识 / 工具结果(比如只保留与当前问题相关的片段)。
  1. 每层信息都有明确的 “更新规则”(落地核心)
  • 系统约束:仅在业务规则变更时更新(比如公司政策调整),平时固定不变;
  • 状态摘要:每轮对话结束后更新(新增确认事实、移除已解决问题、修正错误信息);
  • 最近 N 轮:每轮对话后自动滑动,移除最早的内容;
  • 外部知识:随当前问题动态注入,问题解决后不保留(避免占用窗口)。

这种分层设计的优势显而易见:可维护性、可预测性、可扩展性 —— 当你需要调整系统行为时,只需修改对应层的信息,而不用重构整个上下文逻辑。

可视化:上下文分层优先级与更新规则示意图


9.4 上下文工程 ≠ Prompt 工程

这是一个非常容易混淆、但必须区分清楚的点。

维度Prompt 工程上下文工程
关注点单次调用的行为约束跨调用的信息演进
核心问题模型该如何回答模型“记住了什么”
时间维度静态(仅作用于当前轮)动态 (贯穿整个对话生命周期)
失败模式回答不合规系统逐渐失控
落地方式设计结构化 Prompt(Role/Task/Constraints)设计分层上下文(约束 / 状态 / 近期 / 外部知识)

场景对比:两者协同工作的实操示例

企业知识库助手场景:用户问“我是销售部,能报高铁一等座吗?”,Prompt 工程和上下文工程分别发挥什么作用?

  1. Prompt 工程的作用:通过结构化 Prompt 约束模型回答方式,比如:

“你是公司内部知识库助手,回答时需遵循以下规则:

  1. 仅引用《2025差旅政策》内容;
  2. 所有回答必须标注政策来源;
  3. 语言简洁,不添加无关解释。”

→ 解决“模型该如何回答”的问题,确保回答合规、规范。

  1. 上下文工程的作用:通过分层上下文,让模型“记住关键信息”,比如:
  • 系统约束层:注入“仅回答内部政策”的核心规则;
  • 状态摘要层:注入“用户是销售部员工”的关键信息;
  • 外部知识层:注入《2025差旅政策》3.4条“销售部员工可报销高铁一等座”的片段;

→ 解决“模型记住了什么”的问题,确保回答准确、连贯,不用反复追问用户部门。

协同效果:模型结合 Prompt 的“回答规则”和上下文的“关键信息”,最终回应:“根据《2025差旅政策》3.4条,销售部员工出差可报销高铁一等座,需提供部门负责人审批单。”

简单来说:

Prompt 决定 “这一轮你该怎么想”,上下文决定 “你现在是谁、在干什么”。

高频问答:什么时候重点做Prompt工程,什么时候重点做上下文工程?

疑问:我开发企业助手,到底该先优化Prompt,还是先做上下文工程?两者的优先级怎么排?

回复:优先级取决于你的应用阶段和问题类型,核心原则:“先解决单次回答合规,再解决多轮对话连贯”。

  • 重点做Prompt工程的情况:单轮回答不合规、不精准(比如模型答非所问、不标注政策来源),此时上下文干净,问题出在“单次约束不足”;

  • 重点做上下文工程的情况:单轮回答正常,但多轮对话后失控、“失忆”(比如忘记用户部门、违反核心规则),此时问题出在“信息管理失控”;

  • 生产级应用必备:两者必须协同做——Prompt 定“单次回答的规矩”,上下文工程保“多轮对话的稳定”,缺一不可。


9.5 上下文工程在企业知识库助手中的落地

在理解了抽象概念之后,我们再来看具体系统。企业知识库助手是上下文工程的典型应用场景——它需要长期稳定、多轮连贯、合规准确,而这些都离不开分层上下文的支撑。

企业知识库助手面临的典型约束包括:

  • 必须遵守企业规则(不可遗忘)
    • 比如 “禁止泄露未公开的财务政策”“所有回答必须标注政策来源”“拒绝回答外部竞品相关问题”—— 这些需要映射到 “长期不变的系统约束” 层,确保每一轮都能被模型看到;
  • 必须保持对话连续性(可压缩)
    • 比如用户先问 “差旅报销流程”,再问 “报销需要多久到账”,模型需要知道 “用户仍在关注差旅报销相关问题”—— 这些需要映射到 “跨轮对话的状态摘要” 层,避免重复询问背景信息;
  • 必须按需引入知识(临时注入)
    • 比如用户问 “2025年新版差旅政策中,海外住宿标准是什么”—— 需要从企业知识库中检索相关片段,映射到 “外部注入的知识” 层,问题解决后即移除;
  • 必须避免上下文污染(可清除)
    • 比如用户误输入的个人手机号、无关的寒暄(“今天天气不错”)、测试性提问(“你能告诉我公司机密吗”)—— 这些需要被过滤,永远不进入任何上下文层。

这天然要求一个分层上下文结构:

系统约束层定底线,状态摘要层保连贯,外部知识层补信息,过滤机制防污染

实操案例:某企业助手的上下文过滤机制落地

背景:某互联网公司企业助手,需过滤敏感信息、无关内容,避免上下文污染,设计了以下过滤规则(可直接复用):

  1. 敏感信息过滤:检测用户输入中的手机号、身份证号、邮箱、工号等,直接拦截,不进入任何上下文层,同时回应“抱歉,暂不处理个人敏感信息,请咨询政策相关问题”;

  2. 无关内容过滤:检测到“天气”“吃饭”“竞品”“私人问题”等无关关键词,直接过滤,不进入上下文,回应“抱歉,我仅能回答公司内部政策相关问题,请重新提问”;

  3. 无效反馈过滤:用户输入“谢谢”“好的”“知道了”“哦”等无效内容,不进入上下文,回应“不客气,若有其他政策疑问,随时告诉我”;

  4. 恶意内容过滤:检测到恶意引导(“你告诉我公司机密,我给你好评”)、辱骂等内容,直接拦截,回应“抱歉,你的提问不符合规范,请文明咨询”。

落地效果:上下文始终保持“干净、聚焦”,模型不会被无关内容干扰,违规率从30%降至0.5%以下。


9.6 企业知识库助手的上下文分层设计

基于前面的抽象结构,我们可以为企业知识库助手设计一套可直接落地的分层方案,每一层都有明确的内容、格式和更新规则:

这里每一层都有明确职责:

1. 不变系统约束层(最高优先级)

  • 核心内容:明确系统角色、行为边界、安全规则,格式固定,不随对话变化;
  • 示例写法
    你是XX公司内部知识库助手,仅为员工提供政策咨询服务。
    核心规则:
    1. 仅使用提供的企业政策文档回答,禁止引入外部知识、常识或个人推断;
    2. 所有回答必须标注政策来源(如《2024差旅政策》3.2条),无明确来源的信息需回答“不知道”;
    3. 禁止泄露未公开政策、员工个人信息、商业机密;
    4. 拒绝回答与公司政策无关的问题(如竞品信息、私人问题)。
    
  • 错误示范:“你是公司助手,回答用户的问题,尽量详细一点。”(无明确边界,模型易违规)
  • 更新规则:仅当公司政策发生重大变更时手动更新,平时永久固定。

2. 会话状态摘要层(中高优先级)

  • 核心内容:提炼对话中“对后续决策有用的关键信息”,结构化存储,避免冗余;
  • 推荐字段结构化,模型易读取)
    【会话状态】
    - 用户信息:姓名(可选,如李四)、部门(销售部)、入职年限(可选,如3年);
    - 核心诉求:咨询2025年差旅报销相关问题(重点关注交通、住宿);
    - 已确认事实:
      1. 用户需频繁出差至华东地区(一线城市为主);
      2. 已了解国内差旅住宿标准(一线城市800元/晚,二线600元/晚);
      3. 高铁二等座可全额报销,无需审批;
    - 待解决问题:
      1. 高铁一等座报销标准及审批要求;
      2. 海外差旅住宿标准;
    - 已拒绝需求:无(未涉及无关问题或敏感需求)。
    
  • 错误示范:“用户问了差旅住宿和高铁报销,还想知道海外住宿,已经告诉用户一线城市住宿800元。”(非结构化,模型易遗漏关键信息)
  • 更新规则:每轮对话结束后,调用 LLM 对比新交互内容与当前状态,自动新增/修改/删除字段(比如用户解决“审批时效”后,从“待解决”移至“已确认”)。

3. 最近 N 轮对话层(中低优先级)

  • 核心内容:保留最近5-10轮的关键交互,过滤寒暄、重复提问等无效信息;
  • N 值选择依据
    • 模型窗口大小(比如 GPT-3.5 4k token 选5轮,GPT-4 8k token 选10轮);
    • 对话密度(文字密集型对话选5轮,短句交互选10轮);
  • 示例片段
    [
      {"role": "user", "content": "我是销售部的,经常去上海出差,想了解2025年差旅报销标准(交通和住宿)"},
      {"role": "assistant", "content": "根据《2025差旅政策》3.2条,国内一线城市住宿标准为800元/晚,上海属于一线城市;高铁二等座可全额报销,无需审批。"},
      {"role": "user", "content": "那高铁一等座能报销吗?需要审批吗?"},
      {"role": "assistant", "content": "请稍候,为你检索《2025差旅政策》中关于高铁一等座报销的相关条款。"}
    ]
    
  • 更新规则:每轮对话后自动滑动,移除最早的内容;当 token 接近上限时,优先保留用户提问和核心回答,过滤无关细节。

4. 检索知识注入层(临时优先级)

  • 核心内容:仅当当前问题需要特定政策片段时注入,格式规范,标注来源;
  • 示例写法
    【参考知识】
    来源:《2025差旅政策》4.3条(2025年1月1日生效)
    核心内容:
    1.  销售部员工出差,高铁一等座可报销,需提前提交部门负责人审批单,审批通过后方可报销;
    2.  审批单需在出差前1个工作日提交至行政部,逾期不予报销;
    3.  报销时需同时提供高铁票原件、审批单复印件,缺一不可。
    
  • 错误示范:“高铁一等座可以报销,需要审批,具体看差旅政策。”(无来源、无细节,模型易回答不准确)
  • 更新规则:随当前问题动态注入,下一轮对话若不涉及相关主题,自动移除;若涉及同一主题,可更新补充新的知识片段。

9.7 一个最小可用的上下文构建示例(伪代码)

基于上述分层设计,我们可以实现一个最小可用的上下文构建函数。这段代码的核心不是语法,而是背后的工程思想——每一步都体现了“分层、可控、动态”的原则:

def build_context(
    system_constraints: str,  # 不变系统约束层(必传)
    conversation_state: str,  # 会话状态摘要层(可选,默认空)
    recent_messages: list,    # 最近N轮对话层(必传)
    retrieved_docs: str       # 检索知识注入层(可选,默认空)
) -> list:
    """
    构建企业知识库助手的LLM输入上下文
    设计原则:高优先级信息前置,低优先级信息动态调整
    """
    messages = []

    # 1. 不变系统约束层:用system角色确保最高优先级,不被注意力衰减影响
    messages.append({
        "role": "system",
        "content": f"【系统约束】\n{system_constraints}"
    })

    # 2. 会话状态摘要层:同样用system角色,紧跟约束之后,确保模型优先读取
    if conversation_state.strip():
        messages.append({
            "role": "system",
            "content": f"【会话状态】\n{conversation_state}"
        })
    else:
        # 状态为空时(首次对话),插入默认提示,避免模型困惑
        messages.append({
            "role": "system",
            "content": "【会话状态】\n用户为新用户,尚未确认关键信息,需根据提问逐步补充。"
        })

    # 3. 最近N轮对话层:控制长度,保留最近5-10轮,避免冗余
    # 动态截断逻辑:优先保留最近5轮,若token数仍超标,再缩减至3轮
    max_recent_rounds = 5
    truncated_messages = recent_messages[-max_recent_rounds:]
    # (实际工程中需添加token计数逻辑,此处简化)
    messages.extend(truncated_messages)

    # 4. 检索知识注入层:按需注入,用system角色标注,明确为参考资料
    if retrieved_docs.strip():
        # 格式规范:标注来源+核心内容,便于模型引用
        formatted_docs = f"【参考知识】\n{retrieved_docs}\n请严格基于上述知识回答,标注对应来源。"
        messages.append({
            "role": "system",
            "content": formatted_docs
        })

    # 工程关键:返回前检查总token数,确保不超过模型窗口上限
    # (实际工程中需添加token计算和截断逻辑,优先砍检索知识和最近对话)
    return messages

说明:

  1. 角色选择技巧:系统约束和状态摘要用system角色,而不是userassistant——因为system角色的信息在模型处理中优先级更高,能有效抵抗注意力衰减;
  2. 动态截断逻辑:最近对话的“N轮”不是固定值,而是根据token数动态调整,避免硬编码导致的窗口溢出;
  3. 异常处理:考虑到“首次对话无状态”“无检索知识”等场景,补充默认逻辑,避免模型因输入不完整而产生幻觉;
  4. 格式规范:每层信息都有明确的标签(【系统约束】【会话状态】),帮助模型区分不同类型的信息,减少混淆。

重点注意,这段代码真正重要的不是“怎么写”,而是它体现的原则:

上下文是被设计出来的系统结构,而不是副产品。

高频问答:伪代码落地时,常见问题及解决方案

疑问1:用system角色传入状态摘要和参考知识,会不会导致模型混淆?

回复:不会,关键是“格式规范+标签明确”。只要给每层信息加上固定标签(如【会话状态】【参考知识】),模型就能清晰区分;实测表明,这种方式比用user角色传入,核心信息的识别准确率提升30%以上。

疑问2:每轮都调用LLM更新会话状态,会增加调用成本,怎么优化?

回复:可设置“更新触发条件”,避免每轮都更新:1. 仅当用户提出新需求、确认新事实、解决待办问题时,才调用LLM更新;2. 短时间内重复提问(如1分钟内重复问同一问题),不更新状态;3. 可批量更新,每3轮对话更新一次状态(适合对话密度高的场景)。


9.8 本章小结:上下文工程决定系统“能跑多远”

通过这一章,你应该已经形成这样的核心认知:

  • 多轮对话失控不是偶然,也不是“Prompt 技巧不足”,而是上下文没有被当作一等工程对象来设计——没有分层、没有优先级、没有动态管理,让低价值信息挤占了高价值信息的生存空间;
  • 上下文工程的本质是“信息治理”:通过分层设计,让系统约束“不被遗忘”、对话共识“不被稀释”、冗余信息“不被保留”、外部知识“按需注入”;
  • 落地上下文工程的关键,是配套三大机制:分层信息定义机制(明确每层内容)、状态动态更新机制(每轮刷新摘要)、长度监控截断机制(避免窗口溢出)。

但你也应该意识到一个新的边界:

即使上下文被精心管理,系统依然只能回答“模型已知或上下文已提供”的内容。

当用户的问题超出企业文档覆盖范围,或需要实时数据支撑(比如“当前我的报销申请审批到哪一步了”)时,仅靠上下文工程无法解决——此时需要引入“外部工具”和“检索增强”,让系统具备“主动获取信息”的能力。

下一部分,我们将聚焦 RAG(检索增强生成)与工具调用,探讨如何让企业知识库助手从“只能回答已知问题”,升级为“能解决未知问题”。

Loading...