共计 2977 个字符,预计需要花费 8 分钟才能阅读完成。
AI Agent 上下文工程实战:从提示词优化到记忆管理的最佳实践
背景痛点
在构建 AI Agent 时,尤其是需要处理长对话或多轮交互的场景,开发者经常会遇到以下几个问题:

- 上下文丢失:当对话轮次增多时,LLM(大语言模型)可能会忘记之前的对话内容,导致回答不一致或偏离主题。
- 记忆混乱:不同对话之间的信息可能会互相干扰,尤其是在多用户或多任务场景下。
- 提示词效率低下:简单的提示词设计可能无法有效引导 LLM 生成符合预期的输出,尤其是在复杂任务中。
这些问题不仅影响用户体验,还可能增加开发成本(例如重复调用 API 导致的 token 消耗)。
技术对比
以下是几种常见的上下文管理方案的对比:
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Prompt Chaining | 实现简单,适合短期任务 | 上下文窗口有限,长对话性能下降 | 简单任务或短期对话 |
| Vector DB 记忆存储 | 支持长期记忆,检索效率高 | 实现复杂,需额外存储和计算资源 | 需要长期记忆的复杂任务 |
| LLM 自带会话记忆 | 无需额外开发,适合简单场景 | 记忆容量有限,无法跨会话持久化 | 小规模或临时对话 |
从延迟、成本和复杂度来看:
- Prompt Chaining:延迟低(仅依赖 LLM 的上下文窗口),成本适中(受 token 限制),复杂度低。
- Vector DB 记忆存储:延迟较高(需检索和嵌入计算),成本较高(存储和计算开销),复杂度高。
- LLM 自带会话记忆:延迟最低,成本最低,复杂度最低,但功能有限。
核心实现
分层记忆管理系统
以下是一个基于 Python 的分层记忆管理系统示例,包含短期工作记忆和长期知识记忆:
from typing import List, Dict
import numpy as np
import faiss
class MemoryManager:
def __init__(self, embedding_dim: int = 768):
# 短期工作记忆(保留最近几条对话)self.short_term_memory: List[Dict] = []
# 长期知识记忆(向量化存储)self.long_term_memory = faiss.IndexFlatL2(embedding_dim)
self.memory_data: List[Dict] = []
def add_to_short_term(self, message: Dict):
"""添加消息到短期记忆"""
self.short_term_memory.append(message)
if len(self.short_term_memory) > 5: # 限制短期记忆长度
self.short_term_memory.pop(0)
def add_to_long_term(self, embedding: np.ndarray, metadata: Dict):
"""添加嵌入向量到长期记忆"""
self.long_term_memory.add(embedding)
self.memory_data.append(metadata)
def retrieve_from_long_term(self, query_embedding: np.ndarray, k: int = 3):
"""从长期记忆检索最相关的 k 条记录"""
_, indices = self.long_term_memory.search(query_embedding, k)
return [self.memory_data[i] for i in indices[0]]
提示词模板优化
以下是一个带注释的提示词模板优化示例:
def build_prompt_template(user_input: str, short_term: List[Dict], long_term: List[Dict]) -> str:
""" 构建优化的提示词模板
Args:
user_input: 用户输入
short_term: 短期记忆中的对话历史
long_term: 从长期记忆中检索到的相关内容
"""
# 拼接短期记忆
short_term_context = "\n".join([f"{msg['role']}: {msg['content']}" for msg in short_term])
# 拼接长期记忆
long_term_context = "\n".join([f"相关知识: {item['content']}" for item in long_term])
# 构建完整提示词
prompt = f"""
你是一个专业的助手,请根据以下上下文回答用户问题。近期对话历史:
{short_term_context}
相关背景知识:
{long_term_context}
当前用户输入: {user_input}
"""
return prompt
记忆向量化检索
以下是使用 FAISS 实现记忆向量化检索的示例:
import numpy as np
import faiss
# 假设我们有一些预先生成的嵌入向量
embeddings = np.random.rand(100, 768).astype('float32') # 100 条记忆,维度 768
# 构建 FAISS 索引
index = faiss.IndexFlatL2(768)
index.add(embeddings)
# 检索示例
query_embedding = np.random.rand(1, 768).astype('float32') # 模拟查询嵌入
k = 3 # 返回最相关的 3 条记忆
D, I = index.search(query_embedding, k) # D 是距离,I 是索引
print(f"最相关的 {k} 条记忆索引: {I}")
print(f"与查询的距离: {D}")
生产考量
记忆碎片化处理策略
- 分块存储:将大段记忆拆分为有意义的块(如按主题、实体或时间)。
- 元数据标记:为每个记忆块添加时间戳、来源、重要性等元数据。
- 定期整理:设置定时任务合并或清理冗余记忆。
对话上下文压缩算法
- 关键信息提取:使用 LLM 提取对话中的关键实体和事实。
- 摘要生成:对长对话生成简洁摘要作为新上下文。
- 重要性评分:基于频率、最近使用等指标保留重要内容。
敏感信息过滤机制
def filter_sensitive_content(text: str) -> str:
"""简单的敏感信息过滤"""
sensitive_keywords = ["密码", "信用卡", "身份证号"]
for keyword in sensitive_keywords:
if keyword in text:
text = text.replace(keyword, "[已过滤]")
return text
避坑指南
避免记忆污染的设计模式
- 隔离用户数据:不同用户的记忆存储在不同的命名空间。
- 版本控制:对记忆的修改保留历史版本。
- 读写权限:关键记忆设置为只读。
处理 LLM 上下文窗口限制的技巧
- 分层加载:优先加载最近和最相关的记忆。
- 动态截断:根据 token 计数动态移除旧内容。
- 外部缓存:将部分上下文存储在外部缓存中按需加载。
记忆检索的冷启动优化
- 默认记忆:为常见问题预设回答模板。
- 渐进式学习:随着交互增加逐步丰富记忆库。
- 混合检索:冷启动时结合关键词和语义检索。
思考题
- 如何设计实验评估记忆检索的召回率和准确率?
- 在多用户场景下,如何平衡记忆的个性化和通用性?
- 当记忆库规模很大时,有哪些优化检索效率的策略?
希望这篇实战指南能帮助你更好地构建具有长期记忆能力的 AI Agent 系统。如果有任何问题或建议,欢迎交流讨论!
正文完
