欢迎光临
我们一直在努力

AI Agent上下文工程:从提示词优化到上下文压缩的全链路实践

引言:Agent真正的瓶颈,正在从“模型能力”转向“上下文能力”

过去两年,AI Agent工程实践中有一个非常明显的变化:开发者最初把主要精力放在模型选择、Prompt编写和Tool Calling上,而进入生产环境之后,真正让系统变得复杂的往往不是这些环节,而是上下文管理。

一个简单的聊天机器人,只需要把用户问题发送给大模型即可:

用户问题

Prompt

LLM

回答

但一个真正的企业级Agent通常需要同时处理:

  • 当前用户请求;
  • 多轮对话历史;
  • 用户长期偏好;
  • 当前任务状态;
  • 历史任务结果;
  • 工具调用记录;
  • 数据库查询结果;
  • RAG检索结果;
  • 外部网页或API数据;
  • 系统规则;
  • 安全策略;
  • Agent自身产生的中间状态;
  • 其他Agent返回的信息。

最终发送给模型的已经不再是一个简单Prompt,而是一套动态构建出来的Context Package(上下文包)。

可以把Agent的一次模型调用抽象为:

[ C_t = S + I_t + H_t + M_t + R_t + T_t + O_t ]

其中:

  • (S):System Instruction,系统指令;
  • (I_t):当前用户输入;
  • (H_t):短期对话历史;
  • (M_t):长期记忆;
  • (R_t):检索结果;
  • (T_t):工具及其执行状态;
  • (O_t):Agent运行过程中的其他状态。

因此,Agent的核心问题已经从:

“怎么写一个更好的Prompt?”

逐渐变成:

“在有限Token预算下,如何让模型在当前任务中获得最有价值、最可靠、最及时的上下文?”

这就是上下文工程(Context Engineering)真正解决的问题。

长上下文模型并不意味着可以无限制地把所有历史数据塞进去。研究已经发现,即使模型具备很长的上下文窗口,关键信息位于长上下文中间位置时,模型的利用能力仍可能明显下降,这就是著名的“Lost in the Middle”现象。(arXiv)

所以,上下文工程不是简单地“扩大Context Window”,而是围绕上下文生命周期进行系统设计。


一、什么是AI Agent上下文工程

1.1 Prompt Engineering与Context Engineering的区别

Prompt Engineering主要关注:

如何设计一段更好的提示词,让模型完成特定任务。

例如:

你是一名专业的软件架构师。

请分析下面的系统需求,并输出:
1. 系统架构
2. 技术选型
3. 数据库设计
4. 风险分析

这属于典型的Prompt Engineering。

而Context Engineering关注的是:

模型在某一次推理时,到底应该看到什么信息、以什么顺序看到、哪些信息应该被压缩、哪些信息应该实时检索、哪些信息应该永久保存。

例如用户连续进行了50轮对话:

System Prompt
+
用户画像
+
最近10轮对话
+
任务摘要
+
历史决策
+
当前数据库状态
+
RAG结果
+
工具调用结果
+
当前问题

这里真正困难的已经不是Prompt本身,而是:

哪些信息应该进入Context?

这也是为什么一个Agent即使使用同一个模型,不同上下文架构可能产生完全不同的效果。


二、Agent上下文的完整生命周期

一个生产级Agent可以采用下面的上下文生命周期:

┌─────────────────┐
│ User Request │
└────────┬────────┘

┌─────────────────┐
│ Context Builder │
└────────┬────────┘

┌─────────────────┼──────────────────┐
↓ ↓ ↓
Short Memory Long Memory Retrieval
↓ ↓ ↓
└─────────────────┼──────────────────┘

Context Ranking

Context Compression

Token Budget

Prompt Assembly

LLM

┌───────────┴───────────┐
↓ ↓
Tool Calling Final Answer

State Update

Memory Extraction

Context Persistence

因此可以把上下文工程拆成七个核心环节:

  • 上下文构建;
  • 上下文分层;
  • 上下文检索;
  • 上下文排序;
  • 上下文压缩;
  • 上下文装配;
  • 上下文更新。
  • 这七个环节构成Agent Context Pipeline。


    三、第一层:上下文分层设计

    最常见的错误,是把所有信息都放进一个messages数组。

    例如:

    {
    "messages": [
    {
    "role": "system",
    "content": "…"
    },
    {
    "role": "user",
    "content": "…"
    },
    {
    "role": "assistant",
    "content": "…"
    }
    ]
    }

    在Agent运行时间较短时没有问题,但随着任务复杂度增加,这种设计会逐渐失控。

    更合理的方式是把Context拆成不同层级。

    3.1 Immutable Context

    这部分内容在一个Agent生命周期内基本不变化。

    例如:

    Agent身份
    系统规则
    输出格式
    安全策略
    工具定义
    业务规则

    可以称为:

    Static Context

    这部分应该尽可能稳定。

    原因很简单:很多模型平台支持Prompt Cache。如果每次请求前面的内容发生变化,会降低缓存命中率。

    例如OpenAI API已经提供Prompt Cache相关能力,并通过prompt_cache_key等机制帮助优化相似请求的缓存命中。(OpenAI 平台)

    因此生产系统中应该尽量做到:

    稳定System Prompt

    稳定Tool Definition

    稳定业务规则

    动态Context

    用户问题

    而不是:

    用户问题
    随机信息
    Tool结果
    System Prompt
    用户画像
    历史消息

    频繁改变Prompt前缀会破坏缓存收益。


    四、第二层:短期记忆与长期记忆

    Agent记忆不能简单理解为“聊天记录”。

    更合理的方式是分成:

    Short-Term Memory
    +
    Working Memory
    +
    Long-Term Memory

    4.1 Short-Term Memory

    保存当前任务最近发生的事件。

    例如:

    用户:帮我设计一个订单系统

    Agent:需要支持哪些支付方式?

    用户:微信和支付宝

    Agent:是否需要分销?

    用户:需要三级分销

    当前任务中这些信息具有较高价值。

    因此最近若干轮应该保留。


    4.2 Working Memory

    Working Memory比聊天历史更重要。

    它不是“用户说了什么”,而是:

    Agent现在知道什么,以及任务进行到了哪一步。

    例如:

    {
    "goal": "设计订单系统",
    "payment": [
    "wechat",
    "alipay"
    ],
    "distribution": {
    "enabled": true,
    "level": 3
    },
    "database": "MySQL",
    "backend": "Go",
    "status": "architecture_design"
    }

    这类结构化状态比几十轮自然语言对话更加稳定。

    因此一个成熟Agent应该逐渐从:

    Conversation as State

    升级到:

    State + Conversation

    也就是说:

    不要让聊天记录承担数据库的职责。


    五、第三层:长期记忆不是“把所有历史保存下来”

    长期记忆最容易出现两个极端。

    第一种:

    什么都保存。

    第二种:

    什么都不保存。

    正确的方法是建立Memory Policy。

    例如:

    用户明确偏好

    长期记忆

    临时问题

    不保存

    任务结果

    根据价值决定

    重要业务决策

    长期保存

    一次性的闲聊

    丢弃

    可以定义一个Memory Score:

    [ Score = Importance \\times Recency \\times Relevance ]

    例如:

    Importance = 0.9
    Recency = 0.8
    Relevance = 0.95

    Score = 0.9 × 0.8 × 0.95
    = 0.684

    当Score低于阈值时,不需要进入模型Context。


    六、上下文检索:不是“搜索越多越好”

    RAG系统经常存在一个误区:

    找到越多文档,模型获得的信息越充分。

    实际上恰恰相反。

    如果一次检索返回:

    20个文档
    每个文档1500 Token

    那么:

    20 × 1500 = 30000 Token

    即使模型能够接受30K上下文,也不代表30K信息都应该输入。

    因为真正需要解决的问题是:

    Information Retrieval → Context Selection

    而不是:

    Information Retrieval → Context Dump


    七、Context Ranking:给上下文排序

    可以为每个候选Context计算综合评分:

    [ Score_i = \\alpha R_i + \\beta S_i + \\gamma T_i + \\delta Q_i ]

    其中:

    • (R_i):与当前Query相关性;
    • (S_i):信息可信度;
    • (T_i):时效性;
    • (Q_i):信息质量。

    例如:

    type ContextItem struct {
    ID string
    Content string
    Relevance float64
    Trust float64
    Freshness float64
    Quality float64
    TokenCount int
    }

    排序:

    func Score(c ContextItem) float64 {
    return 0.50*c.Relevance +
    0.20*c.Trust +
    0.15*c.Freshness +
    0.15*c.Quality
    }

    然后只选择Top-N。

    这一步非常重要,因为:

    Context Window应该被看作有限预算,而不是无限仓库。


    八、上下文压缩:Agent进入生产环境的关键能力

    上下文压缩通常分为四类:

    1. 截断
    2. 摘要
    3. 结构化压缩
    4. 语义压缩


    九、第一种压缩:简单截断

    最简单的策略:

    保留System Prompt
    +
    保留最近N轮
    +
    删除最早消息

    例如:

    messages = messages[20:]

    优点:

    • 简单;
    • 快;
    • 不增加额外LLM调用。

    缺点也非常明显:

    早期重要决策

    直接丢失

    例如用户在第2轮说:

    数据库必须使用PostgreSQL。

    第40轮继续讨论系统设计时,如果第2轮已经被截掉,Agent可能重新推荐MySQL。

    这就是典型的上下文丢失。


    十、第二种压缩:摘要

    更成熟的方法是Summary。

    例如原始对话:

    用户:我要开发一个电商系统。
    用户:后端使用Go。
    用户:数据库使用MySQL。
    用户:Redis用于缓存。
    用户:支付使用微信和支付宝。
    用户:需要三级分销。

    压缩为:

    【项目摘要】

    项目类型:电商系统

    技术栈:
    – Go
    – MySQL
    – Redis

    支付:
    – 微信
    – 支付宝

    业务:
    – 三级分销

    当前阶段:
    订单系统架构设计

    这样可以从几千Token压缩到几百Token。

    但摘要也存在一个严重问题:

    摘要模型可能把“看起来不重要”的信息错误删除。

    因此不能简单让模型:

    请总结以上对话。

    而应该指定Summary Schema。

    例如:

    {
    "goal": "",
    "constraints": [],
    "decisions": [],
    "open_questions": [],
    "facts": [],
    "tool_results": [],
    "next_action": ""
    }

    这种结构化摘要比自由文本摘要更适合Agent。


    十一、第三种压缩:状态化压缩

    这是企业Agent中非常值得采用的方法。

    与其:

    保留100轮对话

    不如:

    对话

    提取事实

    提取决策

    提取任务状态

    形成State

    例如:

    {
    "task": {
    "name": "订单系统",
    "status": "payment_design"
    },
    "decisions": [
    "Backend=Go",
    "Database=MySQL",
    "Cache=Redis"
    ],
    "constraints": [
    "支持微信支付",
    "支持支付宝",
    "三级分销"
    ],
    "pending": [
    "支付回调设计",
    "订单状态机设计"
    ]
    }

    这类State可以直接存储到Redis或数据库。

    最终Agent上下文只需要:

    当前State
    +
    最近对话
    +
    相关历史

    而不是整个Conversation。


    十二、第四种压缩:工具结果压缩

    Agent最容易爆Token的地方之一,其实不是用户聊天,而是Tool Calling。

    例如Agent调用数据库:

    SELECT * FROM orders;

    返回:

    10000 rows

    然后直接塞给LLM。

    这基本等于主动制造Context灾难。

    正确方式应该是:

    Tool

    Raw Result

    Result Processor

    Structured Result

    Context

    例如:

    {
    "total": 10000,
    "status_distribution": {
    "paid": 7820,
    "pending": 1210,
    "cancelled": 970
    },
    "recent_orders": [
    {
    "id": 10001,
    "amount": 299
    }
    ]
    }

    模型通常只需要知道:

    数据意味着什么。

    而不是:

    数据库返回了什么。


    十三、Tool Result应该具有Token Budget

    可以给每一个工具设置最大Context预算:

    tools:
    order_query:
    max_context_tokens: 1500

    search:
    max_context_tokens: 3000

    database:
    max_context_tokens: 2000

    web_search:
    max_context_tokens: 4000

    超过预算:

    Raw Result

    Filter

    Rank

    Summarize

    Context

    这样可以防止一个异常Tool调用直接吞掉整个Context Window。


    十四、上下文装配:Context Builder才是Agent的核心组件

    生产级Agent应该拥有一个独立的Context Builder。

    架构可以设计成:

    ┌───────────────┐
    │ User Request │
    └───────┬───────┘

    ┌─────────────────┐
    │ Context Builder │
    └────────┬────────┘

    ┌──────────────────┼─────────────────┐
    ↓ ↓ ↓
    User Memory Task State Retrieval
    ↓ ↓ ↓
    └──────────────────┼─────────────────┘

    Context Ranking

    Context Compression

    Token Budget

    Prompt Assembly

    LLM

    Go接口可以设计成:

    type ContextBuilder interface {
    Build(ctx context.Context, req BuildRequest) (*Context, error)
    }

    type BuildRequest struct {
    UserID string
    Conversation string
    Query string
    TokenBudget int
    }

    type Context struct {
    System string
    Memory []ContextItem
    History []ContextItem
    Retrieval []ContextItem
    ToolResults []ContextItem
    TaskState map[string]any
    }

    这样可以让Context成为独立基础设施,而不是散落在Agent代码中的大量字符串拼接。


    十五、Token Budget:上下文工程的核心约束

    假设模型Context Window为128K Token。

    并不意味着:

    128K全部给输入

    还需要考虑:

    System Prompt
    +
    Tools
    +
    Memory
    +
    History
    +
    Retrieval
    +
    Output
    +
    Reasoning

    因此应该提前进行预算。

    例如:

    Context Window 128K

    System 6K
    Tools 12K
    Memory 8K
    History 20K
    RAG 30K
    Output Reserve 16K
    ————————-
    Safety Margin 10K

    最终:

    实际Context Budget ≈ 26K

    这比简单依赖模型的最大上下文限制安全得多。

    OpenAI API文档也明确说明,当输入超过模型上下文限制时,可以采用截断策略;如果禁用截断,超过限制则会直接报错。(OpenAI 平台)

    因此生产系统不应该把:

    Context Limit

    当成:

    Application Budget

    两者不是一回事。


    十六、上下文压缩触发机制

    不要每一轮都压缩。

    可以采用阈值策略:

    Token Usage < 60%

    正常运行

    60% ~ 75%

    优先减少低价值Context

    75% ~ 85%

    摘要历史 + 压缩Tool Result

    > 85%

    强制Compaction

    例如:

    func NeedCompaction(used, limit int) bool {
    return float64(used)/float64(limit) >= 0.80
    }

    更好的策略不是“达到100%再压缩”,而是提前留出安全区。


    十七、Compaction:从截断升级为上下文重构

    Compaction可以理解为:

    把大量历史状态重新编码成更小、更高价值的上下文。

    例如:

    100轮Conversation

    事实提取

    任务状态

    关键决策

    未完成事项

    工具结果摘要

    20轮高价值Context

    这比单纯删除旧消息可靠得多。

    现代Agent平台也已经开始提供显式的Compaction能力。例如OpenAI Responses API中已经出现compaction相关对象,用于表示由上下文压缩产生的压缩项。(OpenAI 平台)

    这意味着上下文压缩正在从“开发者自行拼Prompt的小技巧”,逐渐变成Agent Runtime的一等能力。


    十八、Compaction必须保护关键事实

    压缩过程中最重要的问题不是:

    能压缩多少?

    而是:

    哪些信息绝对不能丢?

    建议建立四级信息分类:

    P0:不可丢失
    P1:重要
    P2:可压缩
    P3:可删除

    例如:

    类型等级策略
    用户明确业务约束 P0 永久保存
    已确认技术选型 P0 结构化保存
    当前任务状态 P0 实时更新
    重要工具结果 P1 摘要
    普通历史对话 P2 压缩
    寒暄 P3 删除
    重复信息 P3 去重

    这样Context Compaction就不再是“让模型总结”,而是一个有明确策略的状态转换过程。


    十九、Context Update:上下文必须持续更新

    很多Agent系统只关注:

    Context → LLM

    却忽略:

    LLM → Context

    实际上Agent每次运行之后都应该更新状态。

    完整流程:

    Request

    Build Context

    LLM

    Tool Calls

    Result

    State Update

    Memory Extraction

    Context Store

    例如Agent完成一次任务:

    {
    "event": "payment_design_completed",
    "decision": {
    "provider": "wechat",
    "callback": "async",
    "idempotency": true
    }
    }

    这个事件应该进入Task State。

    而不是仅仅留在聊天记录里。


    二十、Event Sourcing思路可以用于Agent状态管理

    对于复杂Agent,可以把每一次重要变化记录为Event:

    {
    "event_id": "evt_10001",
    "type": "decision_made",
    "timestamp": "2026-08-13T09:20:00Z",
    "payload": {
    "database": "mysql"
    }
    }

    连续事件:

    TaskCreated

    DatabaseSelected

    PaymentSelected

    ArchitectureCompleted

    CodeGenerated

    TestCompleted

    然后可以从Event重建Agent State。

    这对于:

    • 长任务;
    • 多Agent协作;
    • Agent恢复;
    • 故障重试;
    • 审计;
    • Debug;

    都非常有价值。


    二十一、多Agent系统中的上下文工程

    多Agent架构还有一个特殊问题:

    Agent之间应该共享多少上下文?

    最危险的设计是:

    Agent A全部Context

    Agent B全部Context

    Agent C全部Context

    这样不仅Token成本高,而且会产生严重的信息污染。

    更好的方式是:

    Agent A

    Task Result

    Structured Handoff

    Agent B

    例如:

    {
    "task": "architecture_analysis",
    "result": {
    "backend": "Go",
    "database": "MySQL",
    "cache": "Redis"
    },
    "confidence": 0.92,
    "open_questions": [
    "是否需要消息队列"
    ]
    }

    Agent B不需要知道Agent A的全部思考过程,只需要获得:

    结论
    依据
    约束
    未解决问题

    这就是Context Isolation。


    二十二、不要把Chain-of-Thought当成Context数据库

    一个非常重要的工程原则是:

    模型推理过程和业务状态不是一回事。

    Agent真正需要长期保存的应该是:

    事实
    决策
    约束
    任务状态
    工具结果
    最终结论

    而不是:

    模型所有中间推理文本

    这样可以显著降低Context体积,同时提高状态稳定性。

    对于复杂任务,更推荐保存:

    {
    "decision": "使用Redis作为缓存",
    "reason": "降低高频读取数据库压力",
    "source": "architecture_analysis",
    "confidence": 0.91
    }

    而不是保存大量自然语言推理过程。


    二十三、Prompt Cache与Context Engineering

    上下文工程还有一个经常被忽略的经济因素:

    相同Context是否可以被缓存?

    如果一个Agent每次请求都发送:

    10K System Prompt
    +
    20K Tools
    +
    30K Business Knowledge
    +
    2K User Query

    其中前60K几乎完全不变,那么最合理的设计是让稳定前缀保持稳定。

    可以组织为:

    [Stable Prefix]
    System
    Tools
    Business Rules
    Static Knowledge

    [Dynamic Context]
    Memory
    Task State
    RAG
    Tool Results

    [User Query]

    这样可以同时获得:

    • 更好的Prompt Cache命中;
    • 更低输入Token成本;
    • 更低延迟;
    • 更稳定的上下文结构。

    OpenAI文档明确提供了缓存Token使用量等指标,API响应中可以看到cached_tokens等Usage信息,因此生产系统可以直接监控缓存命中效果。(OpenAI 平台)


    二十四、上下文成本模型

    可以把一次Agent调用成本抽象为:

    [ Cost = C_{input} + C_{cached} + C_{output} + C_{tool} + C_{retrieval} ]

    如果每次请求都把100K历史上下文重新发送,那么即使模型性能没有问题,成本也可能迅速增长。

    更值得关注的是:

    [ TotalCost = \\sum_{t=1}^{N} ContextTokens_t \\times Price ]

    所以优化Agent成本最直接的方法之一,不是简单更换便宜模型,而是:

    减少无效Context Token。


    二十五、上下文工程的缓存架构

    推荐设计三级缓存:

    ┌──────────────┐
    │ L1 Memory │
    │ Local/Process│
    └──────┬───────┘

    ┌──────────────┐
    │ L2 Redis │
    │ Hot Context │
    └──────┬───────┘

    ┌──────────────┐
    │ L3 Database │
    │ Long Memory │
    └──────────────┘

    例如:

    L1:
    当前请求Context

    L2:
    最近任务State、短期Memory

    L3:
    用户长期记忆、历史任务、知识数据

    检索顺序:

    L1 → L2 → L3 → Vector Search

    这样能够减少大量无意义查询。


    二十六、Context Store数据库设计

    可以建立:

    CREATE TABLE agent_context (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    session_id VARCHAR(64) NOT NULL,
    context_type VARCHAR(32) NOT NULL,
    content TEXT NOT NULL,
    importance FLOAT DEFAULT 0,
    relevance FLOAT DEFAULT 0,
    token_count INT DEFAULT 0,
    created_at DATETIME NOT NULL,
    updated_at DATETIME NOT NULL
    );

    其中:

    context_type

    可以是:

    system
    memory
    fact
    decision
    task_state
    tool_result
    summary
    retrieval

    这样后续可以针对不同类型采用不同策略。


    二十七、推荐的Agent Context架构

    综合前面的设计,一个比较完整的企业级架构可以是:

    ┌─────────────────────┐
    │ User Input │
    └──────────┬──────────┘

    ┌─────────────────────┐
    │ Query Understanding │
    └──────────┬──────────┘

    ┌─────────────────────┐
    │ Context Builder │
    └──────────┬──────────┘

    ┌───────────────────────┼───────────────────────┐
    ↓ ↓ ↓
    ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
    │ Short Memory │ │ Long Memory │ │ Retrieval │
    └──────┬───────┘ └──────┬───────┘ └──────┬───────┘
    │ │ │
    └───────────────────────┼───────────────────────┘

    ┌─────────────────────┐
    │ Context Ranking │
    └──────────┬──────────┘

    ┌─────────────────────┐
    │ Token Budget Manager│
    └──────────┬──────────┘

    ┌─────────────────────┐
    │ Context Compaction │
    └──────────┬──────────┘

    ┌─────────────────────┐
    │ Prompt Assembly │
    └──────────┬──────────┘

    ┌─────────────────────┐
    │ LLM │
    └──────────┬──────────┘

    ┌─────────────┴─────────────┐
    ↓ ↓
    Tool Calling Final Answer

    Result Processing

    State Update

    Memory Extraction

    Context Store


    二十八、一个可落地的Context Builder实现

    下面给出一个简化的Go实现:

    type ContextManager struct {
    MemoryStore MemoryStore
    Retrieval Retriever
    Compressor Compressor
    Tokenizer Tokenizer
    }

    func (m *ContextManager) Build(
    ctx context.Context,
    req BuildRequest,
    ) (*Context, error) {

    memory, err := m.MemoryStore.Search(
    ctx,
    req.UserID,
    req.Query,
    )
    if err != nil {
    return nil, err
    }

    docs, err := m.Retrieval.Search(
    ctx,
    req.Query,
    10,
    )
    if err != nil {
    return nil, err
    }

    context := &Context{
    Memory: memory,
    Retrieval: docs,
    History: req.History,
    TaskState: req.TaskState,
    }

    tokens := m.Tokenizer.Count(context)

    if tokens > req.TokenBudget {
    context, err = m.Compressor.Compress(
    ctx,
    context,
    req.TokenBudget,
    )
    if err != nil {
    return nil, err
    }
    }

    return context, nil
    }

    关键点不是代码本身,而是:

    Build

    Count

    Budget

    Compress

    Context Manager应该拥有明确的Token预算控制能力。


    二十九、Context Compression不要只看Token压缩率

    一个压缩器如果:

    原始:10000 Token
    压缩:1000 Token

    看起来非常优秀。

    但如果压缩后丢失:

    数据库选型
    支付方式
    关键业务约束

    那么这个压缩器实际上是失败的。

    因此应该定义:

    [ Compression\\ Efficiency = \\frac{Useful\\ Information\\ Retained} {Context\\ Tokens} ]

    而不是:

    [ Compression\\ Ratio = \\frac{CompressedTokens} {OriginalTokens} ]

    真正优秀的Context压缩应该做到:

    Token ↓
    信息密度 ↑
    任务成功率不下降


    三十、建立Context Evaluation体系

    生产环境中不能只测试:

    回答是否正确?

    还应该测试:

    1. Context Recall

    关键事实是否被保留?

    2. Context Precision

    加入的上下文是否真正有用?

    3. Context Utilization

    模型是否正确使用上下文?

    4. Compression Loss

    压缩前后任务成功率下降多少?

    5. Token Efficiency

    完成相同任务需要多少Token?

    6. Cache Hit Rate

    稳定Context的缓存命中率是多少?


    三十一、Lost in the Middle应该成为测试项

    长Context测试不能只把正确答案放在:

    开头

    或者:

    结尾

    而应该测试:

    10%
    30%
    50%
    70%
    90%

    不同位置。

    因为研究显示,长上下文模型在关键证据位于中间位置时可能出现明显性能下降。(arXiv)

    因此Agent评测数据集应该专门设计:

    Long Context
    +
    Distractors
    +
    Position Shift
    +
    Multiple Relevant Facts

    测试模型是否真的使用了Context,而不是只依赖最近几条消息。


    三十二、一个生产级Context策略

    对于绝大多数企业Agent,可以从下面这套策略开始:

    System Prompt

    稳定不变

    Tool Definition

    稳定不变

    User Profile

    只保留长期有效信息

    Task State

    结构化存储

    Recent History

    保留最近5~20轮

    Long History

    Summary

    RAG

    Top-K + Rerank

    Tool Result

    结构化 + 摘要

    Context

    Token Budget

    超过阈值

    Compaction

    这比单纯使用:

    messages = 全部历史消息

    可靠得多。


    三十三、常见错误与反模式

    33.1 把所有聊天记录全部发送

    这是最常见的问题。

    结果:

    Token成本 ↑
    延迟 ↑
    噪声 ↑
    相关性 ↓
    模型注意力分散


    33.2 把RAG结果全部塞给模型

    RAG应该解决:

    不知道

    而不是:

    什么都给模型

    检索系统必须承担过滤责任。


    33.3 只使用Summary,不保存原始事实

    Summary有损压缩。

    因此重要事实应该独立保存:

    Fact Store
    +
    Summary

    而不是:

    只有Summary


    33.4 让Tool直接返回巨大文本

    应该:

    Tool

    Result Processor

    Structured Data

    LLM


    33.5 Context没有Token Budget

    如果Context没有Budget,它迟早会失控。

    所有生产Agent都应该能够回答:

    当前Context多少Token?

    各模块占多少?

    哪部分最占Token?

    哪些Context被压缩?

    哪些Context被丢弃?


    三十四、Context Observability:必须知道模型到底看到了什么

    Agent日志不能只记录:

    request
    response

    至少应该记录:

    {
    "session_id": "sess_001",
    "model": "xxx",
    "input_tokens": 18240,
    "cached_tokens": 12100,
    "output_tokens": 1300,
    "context": {
    "system": 3200,
    "memory": 900,
    "history": 4200,
    "retrieval": 6800,
    "tools": 2400,
    "task_state": 740
    },
    "compaction": {
    "triggered": true,
    "before": 31000,
    "after": 14200
    }
    }

    这样出现:

    “Agent为什么忘记用户刚才说的话?”

    时,工程师才能真正定位:

    是没有检索?
    还是排序错误?
    还是Context被压缩?
    还是Token Budget不足?
    还是Tool结果覆盖?
    还是模型没有正确利用Context?


    三十五、推荐的Context工程目录结构

    对于Go Agent项目,可以采用:

    agent/
    ├── context/
    │ ├── builder.go
    │ ├── budget.go
    │ ├── ranking.go
    │ ├── compression.go
    │ ├── summarizer.go
    │ └── policy.go

    ├── memory/
    │ ├── short_term.go
    │ ├── long_term.go
    │ ├── vector.go
    │ └── store.go

    ├── retrieval/
    │ ├── search.go
    │ ├── reranker.go
    │ └── filter.go

    ├── state/
    │ ├── state.go
    │ ├── event.go
    │ └── reducer.go

    ├── tools/
    │ ├── registry.go
    │ ├── executor.go
    │ └── result_processor.go

    ├── agent/
    │ ├── runner.go
    │ └── planner.go

    └── observability/
    ├── tracing.go
    ├── metrics.go
    └── context_log.go

    这样的架构可以把Context从Agent业务逻辑中解耦出来。


    三十六、从Prompt Engineering走向Context Engineering

    Prompt Engineering解决的是:

    怎么告诉模型做什么

    Context Engineering解决的是:

    模型现在应该知道什么

    两者并不是替代关系,而是上下游关系:

    Prompt Engineering

    Instruction

    Context Engineering

    Information

    Agent Runtime

    Execution

    LLM

    Decision

    未来Agent系统的竞争力,很大程度上不再取决于谁写了一段更漂亮的System Prompt,而取决于谁能构建更加可靠的Context Runtime。


    三十七、企业级落地路线

    如果从零开始建设Context Engineering体系,不建议一开始就做得非常复杂。

    可以分四个阶段。

    第一阶段:基础Context

    实现:

    System Prompt
    +
    Recent History
    +
    Token Counting

    目标:

    防止Context无限增长。


    第二阶段:Memory + State

    加入:

    Short Memory
    Long Memory
    Task State

    目标:

    不再依赖完整聊天记录保存任务状态。


    第三阶段:Retrieval + Compression

    加入:

    RAG
    Rerank
    Summary
    Compaction
    Tool Result Compression

    目标:

    在有限Token下提升信息密度。


    第四阶段:Context Runtime

    最终建设:

    Context Builder
    Context Policy
    Context Budget
    Context Ranking
    Context Compression
    Context Cache
    Context Observability
    Context Evaluation

    这时候Context已经不再是Agent代码中的一个变量,而成为独立基础设施。


    三十八、结语:Agent的核心不是记住一切,而是知道此刻需要什么

    长上下文解决的是:

    模型能够容纳多少信息。

    上下文工程解决的是:

    模型应该看到哪些信息。

    这是两个完全不同的问题。

    一个128K甚至更大的Context Window,并不能自动解决长对话中的“遗忘”、RAG噪声、Tool结果膨胀和Token成本问题。已有研究表明,长上下文模型依然可能受到信息位置和上下文长度的影响。(arXiv)

    因此,一个真正成熟的Agent应该遵循这样的上下文原则:

    不是保存所有信息

    而是保存重要信息

    不是检索所有文档

    而是检索相关信息

    不是发送所有工具结果

    而是发送有效结果

    不是无限扩大Context

    而是管理Context Budget

    不是简单删除历史

    而是进行结构化Compaction

    不是让Conversation承担全部状态

    而是Conversation + State + Memory

    不是只看模型输出

    而是观察整个Context Pipeline

    最终可以把Agent上下文工程浓缩成一个公式:

    [ Agent\\ Intelligence \\approx Model\\ Capability \\times Context\\ Quality \\times State\\ Consistency ]

    模型决定Agent的上限,而上下文决定模型在具体任务中能够发挥多少能力。

    对于生产环境而言,真正值得投入的不是把Prompt再写长一点,而是建立一套完整的Context Runtime:能够检索、筛选、排序、压缩、缓存、更新和观测上下文,并且始终围绕当前任务的Token预算做信息取舍。

    当Agent从“聊天机器人”升级到能够连续运行数小时、数天甚至数周的业务系统之后,上下文工程就不再是优化项,而会成为Agent架构中与模型、工具、记忆和工作流同等重要的基础设施。

    参考资料

  • Nelson F. Liu, Kevin Lin, John Hewitt, Ashwin Paranjape, Michele Bevilacqua, Fabio Petroni, Percy Liang. Lost in the Middle: How Language Models Use Long Contexts. arXiv:2307.03172, 2023. (arXiv)
  • OpenAI API Documentation. Responses API / Streaming Events / Context Truncation / Compaction / Prompt Caching. OpenAI API官方文档
  • OpenAI. Data controls in the OpenAI platform. OpenAI Platform Documentation. OpenAI Platform官方文档
  • WangduTech Official Documentation https://www.wangdu.net.cn/announcements/59
  • 赞(0)
    未经允许不得转载:171主机测评 » AI Agent上下文工程:从提示词优化到上下文压缩的全链路实践
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址