AI Agent 的上下文工程:Prompt设计与优化策略
AI Agent 的上下文工程:Prompt设计与优化策略
摘要:上下文(Context)是 LLM 推理的"燃料",而 Prompt 是注入燃料的"管道"。本文系统探讨 AI Agent 场景下的上下文管理策略,从 System Prompt 设计、少样本提示到动态上下文压缩,给出可直接落地的代码实现与优化方案。
---
一、上下文管理:Agent 的"工作记忆"
与人类认知类似,LLM 的每次推理都依赖于输入的上下文。在 AI Agent 架构中,上下文不仅包含用户的当前指令,还涵盖了: - 系统角色定义:Agent 的身份、能力边界与行为约束 - 历史对话记录:多轮交互的累积信息 - 工具调用结果:外部 API、数据库查询的返回数据 - 环境状态:文件系统、内存变量、会话缓存 上下文管理的质量直接决定 Agent 的任务完成率。一个典型的 Agent 上下文窗口通常被多层信息填充:
[系统提示] ──→ 角色定义 + 工具描述 + 安全约束
↓
[少样本示例] ──→ 输入/输出模式示范
↓
[历史对话] ──→ 用户与 Agent 的 N 轮交互
↓
[当前输入] ──→ 用户最新指令
↓
[工具结果] ──→ 外部工具返回的实时数据
然而,所有主流模型都存在上下文长度限制(如 GPT-4o 的 128K tokens、Claude 3.5 Sonnet 的 200K tokens)。当上下文超载时,模型性能会出现"中间迷失"(Lost in the Middle)现象——对长文本中间部分的信息提取能力显著下降。因此,上下文工程(Context Engineering)成为 Agent 开发的必修课。 ---
二、System Prompt 设计:定义 Agent 的"人格"与"能力"
System Prompt 是 LLM 推理的"底层操作系统",它在每次请求中隐式存在,影响模型的全局行为模式。
2.1 最佳实践结构
一个高质量的 System Prompt 应包含以下模块:
SYSTEM_PROMPT = """你是一个专业的数据分析助手 Agent。请严格遵守以下规则:
1. 角色定义
- 身份:资深数据分析师,擅长 Python 数据处理和可视化 - 语言:用户输入为中文时,用中文回复;否则用英文回复 - 态度:专业、简洁、乐于解释
2. 能力边界
- 你可以:分析数据、生成图表、编写 Python 代码、解释统计概念 - 你不可以:访问互联网获取实时数据、执行本地文件写操作(除非用户明确授权)
3. 工具调用规范
当任务需要计算时,你必须调用 python_executor 工具执行代码,而非在文本中直接输出计算结果。 工具调用格式: {"name": "python_executor", "arguments": {"code": "print(1+1)"}}
4. 安全约束
- 拒绝生成恶意代码、破解工具或侵犯隐私的内容 - 遇到敏感数据时,提醒用户注意数据脱敏
5. 输出格式
- 分析结果先给出结论,再展示详细过程 - 代码块使用 python 标记 """
2.2 关键设计原则
| 原则 | 说明 | 反例 | |------|------|------| | 明确边界 | 清晰声明能做什么和不能做什么 | "你是一个有用的助手"(过于模糊) | | 结构化 | 使用标题、列表、编号组织信息 | 大段连续文本,模型难以提取关键约束 | | 示例驱动 | 用示例说明期望的输出格式 | 仅用抽象描述,模型理解偏差大 | | 优先级排序 | 将最重要的约束放在前面 | 安全约束 buried 在文本末尾 | | 语言对齐 | 系统提示与目标对话语言一致 | 英文系统提示 + 中文用户输入,易产生混杂输出 | ---
三、少样本提示与上下文压缩
3.1 Few-shot 提示:用示例引导模式
Few-shot Prompting 通过在上下文中嵌入输入-输出示例,让模型"学习"期望的行为模式,比零样本(Zero-shot)的准确率平均提升 20%-40%。 python FEW_SHOT_PROMPT = """请将用户的问题分类到以下类别之一:技术咨询、账单问题、功能反馈、其他。 示例: 输入:"我的服务器连接超时了,错误码是 502" 输出:{"category": "技术咨询", "confidence": 0.95} 输入:"这个月账单怎么多了 50 块钱?" 输出:{"category": "账单问题", "confidence": 0.98} 输入:"希望能支持导出 Excel 格式的报表" 输出:{"category": "功能反馈", "confidence": 0.92} 输入:"{user_question}" 输出:"""
关键技巧:
- 示例应覆盖边界情况(如模糊查询、多意图混合)
- 示例数量控制在 3-5 个,过多会挤占有效上下文
- 示例中的输出格式必须与生产环境完全一致
3.2 上下文压缩:在有限窗口中保留最大信息量
当历史对话或工具结果过长时,需要进行智能压缩。以下是几种常用策略: python from typing import List, Dict import tiktoken class ContextCompressor: """上下文压缩器:在 token 限制内保留关键信息""" def __init__(self, model: str = "gpt-4o", max_tokens: int = 8000): self.encoder = tiktoken.encoding_for_model(model) self.max_tokens = max_tokens def count_tokens(self, text: str) -> int: return len(self.encoder.encode(text)) def summarize_messages(self, messages: List[Dict], keep_recent: int = 4) -> List[Dict]: """ 压缩策略:保留最近 N 轮完整对话, 更早的对话仅保留摘要 """ if len(messages) <= keep_recent: return messages # 保留最近的对话 recent = messages[-keep_recent:] # 对早期对话进行摘要 early = messages[:-keep_recent] early_text = "\n".join([ f"{m['role']}: {m['content'][:200]}" for m in early ]) summary = { "role": "system", "content": f"[历史对话摘要] 以下是之前 {len(early)} 轮对话的要点:\n{early_text[:1000]}..." } return [summary] + recent def truncate_by_tokens(self, text: str, max_tokens: int = None) -> str: """按 token 数截断文本""" max_t = max_tokens or self.max_tokens tokens = self.encoder.encode(text) if len(tokens) <= max_t: return text return self.encoder.decode(tokens[:max_t]) def semantic_pruning(self, messages: List[Dict], query: str) -> List[Dict]: """ 基于与当前查询的相关性进行剪枝 (简化实现:使用关键词匹配,生产环境可替换为向量相似度) """ query_keywords = set(query.lower().split()) scored = [] for msg in messages: content = msg.get("content", "").lower() score = len(query_keywords & set(content.split())) scored.append((score, msg)) # 按相关性降序,保留 top-k scored.sort(reverse=True) return [msg for _, msg in scored[:10]]
使用示例
compressor = ContextCompressor(max_tokens=6000) long_h
更多推荐


所有评论(0)