世界上有一种技术叫Context Engineering,它就像AI的图书馆管理员。每次Agent要找资料,它都会递给你那本最对味的书。
而这,就是优化Agent性能的核心秘密。
📚 什么是Context Engineering?
🎯 核心定义
Context Engineering 是一门关于如何高效管理AI Agent上下文(Context)的技术。它包括:
- 上下文选择:决定哪些信息应该放入Context
- 上下文压缩:在有限Token内最大化信息密度
- 上下文更新:动态调整Context内容
- 上下文检索:快速找到相关历史信息
Context Quality = Relevance × Density ÷ Token_Cost
为什么Context Engineering重要?
在OpenClaw Agent中:
- ✅ 好的Context → Agent准确理解任务 → 高质量输出
- ❌ 差的Context → Agent困惑 → 垃圾输出
- ⚠️ 过多的Context → Token成本飙升 → 浪费钱
- ⚠️ 过少的Context → 信息不足 → Agent瞎猜
🔧 实战技巧1:上下文压缩
问题:Token不够用
假设你要让Agent分析一篇长文章(5000字),但GPT-4的Context Window只有8192个Token(约6000字)。
解决方案:分层压缩
# 方法1:提取关键信息
def compress_article(text):
"""压缩长文章"""
# 步骤1:提取段落大意
paragraphs = text.split('\n\n')
summaries = []
for para in paragraphs:
summary = summarize(para) # 使用summarization模型
summaries.append(summary)
# 步骤2:合并相关段落
merged = merge_related(summaries)
# 步骤3:生成最终摘要
final = ' '.join(merged)
return final
# 方法2:使用向量检索(RAG)
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
def build_context(query, documents, max_tokens=4000):
"""构建相关上下文"""
# 编码查询和文档
query_embedding = model.encode(query)
doc_embeddings = model.encode(documents)
# 计算相似度
similarities = cosine_similarity([query_embedding], doc_embeddings)[0]
# 选择最相关的文档
relevant_docs = []
total_tokens = 0
for idx in similarities.argsort()[::-1]:
doc = documents[idx]
doc_tokens = len(doc.split()) * 1.3 # 粗略估算
if total_tokens + doc_tokens > max_tokens:
break
relevant_docs.append(doc)
total_tokens += doc_tokens
return '\n\n'.join(relevant_docs)
💡 周星驰式吐槽: 就像你妈让你穿秋裤,但你只穿一条。不是不穿,是要穿得刚刚好!
🔧 实战技巧2:动态上下文更新
场景:多轮对话
在OpenClaw中,Agent需要记住之前的对话内容。但随着对话变长,Context会爆炸。
解决方案:滑动窗口 + 摘要
class DynamicContextManager:
def __init__(self, max_tokens=4000):
self.max_tokens = max_tokens
self.conversation = []
self.summary = ""
def add_message(self, role, content):
"""添加新消息"""
self.conversation.append({"role": role, "content": content})
self._optimize_context()
def _optimize_context(self):
"""优化上下文"""
# 计算当前Token数
total_tokens = sum(len(m["content"].split()) * 1.3 for m in self.conversation)
# 如果超限,进行压缩
if total_tokens > self.max_tokens:
# 保留最近5条消息
recent = self.conversation[-5:]
# 对前面的消息生成摘要
older = self.conversation[:-5]
self.summary = self._summarize(older)
# 更新conversation
self.conversation = [
{"role": "system", "content": f"之前的对话摘要:{self.summary}"}
] + recent
def _summarize(self, messages):
"""生成对话摘要"""
text = "\n".join([f"{m['role']}: {m['content']}" for m in messages])
# 调用摘要模型(省略实现)
return summarize_text(text)
def get_context(self):
"""获取优化后的上下文"""
return self.conversation
# 使用示例
context_mgr = DynamicContextManager()
context_mgr.add_message("user", "帮我写一个Python函数计算斐波那契数列")
context_mgr.add_message("assistant", "好的,这是代码...")
context_mgr.add_message("user", "能不能优化一下性能?")
# ... 更多对话 ...
# 获取优化后的上下文
context = context_mgr.get_context()
🔧 实战技巧3:上下文检索(RAG)
场景:知识库问答
假设你的Agent需要回答关于OpenClaw的问题,但OpenClaw文档有几百页。
解决方案:向量数据库 + 语义检索
import chromadb
from sentence_transformers import SentenceTransformer
class RAGContextProvider:
def __init__(self, docs_dir):
self.model = SentenceTransformer('all-MiniLM-L6-v2')
self.client = chromadb.Client()
self.collection = self.client.create_collection("openclaw-docs")
# 加载文档
self._load_documents(docs_dir)
def _load_documents(self, docs_dir):
"""加载并索引文档"""
docs = []
for file in os.listdir(docs_dir):
with open(os.path.join(docs_dir, file), 'r') as f:
text = f.read()
# 分块
chunks = self._chunk_text(text, chunk_size=500)
docs.extend(chunks)
# 生成嵌入并存储
embeddings = self.model.encode(docs)
self.collection.add(
embeddings=embeddings.tolist(),
documents=docs,
ids=[f"doc_{i}" for i in range(len(docs))]
)
def _chunk_text(self, text, chunk_size=500):
"""将文本分块"""
words = text.split()
chunks = []
for i in range(0, len(words), chunk_size):
chunk = ' '.join(words[i:i+chunk_size])
chunks.append(chunk)
return chunks
def get_relevant_context(self, query, n_results=3):
"""获取相关上下文"""
query_embedding = self.model.encode(query).tolist()
results = self.collection.query(
query_embeddings=[query_embedding],
n_results=n_results
)
return results['documents'][0]
# 使用示例
rag = RAGContextProvider("/path/to/openclaw/docs")
# Agent处理问题时
query = "如何在OpenClaw中安装Skill?"
context = rag.get_relevant_context(query)
# context包含最相关的文档片段
# 将context放入Agent的prompt
prompt = f"""
根据以下上下文回答问题:
{context}
问题:{query}
"""
# 调用LLM...
📝 实际效果对比
没有RAG:
Q: "如何在OpenClaw中安装Skill?"
A: "抱歉,我不知道。" (因为不在Context中)
有RAG:
Q: "如何在OpenClaw中安装Skill?"
A: "根据文档,你可以通过以下方式安装Skill:
1. 使用CLI: openclaw skill install <skill-name>
2. 从ClawHub网站下载后安装..." (因为检索到了相关文档)
📊 性能优化最佳实践
1. 根据任务类型调整Context
| 任务类型 | 推荐Context策略 |
|---|---|
| 代码生成 | 提供完整的需求描述 + 相关代码示例 |
| 文档问答 | 使用RAG检索最相关的文档片段 |
| 数据分析 | 提供数据样本 + 分析目标 + 类似案例 |
| 创意写作 | 提供风格示例 + 主题要求 + 限制条件 |
2. 监控Token使用
# OpenClaw中监控Token使用
import tiktoken
def count_tokens(text, model="gpt-4"):
"""计算Token数"""
enc = tiktoken.encoding_for_model(model)
return len(enc.encode(text))
# 在Agent执行前后统计
class TokenMonitor:
def __init__(self):
self.start_tokens = 0
self.end_tokens = 0
def start(self, context):
self.start_tokens = count_tokens(str(context))
def end(self, output):
self.end_tokens = count_tokens(str(output))
def report(self):
print(f"Context Token数: {self.start_tokens}")
print(f"Output Token数: {self.end_tokens}")
print(f"Total Token数: {self.start_tokens + self.end_tokens}")
print(f"预估成本: ${ (self.start_tokens + self.end_tokens) * 0.00003:.4f}")
# 使用
monitor = TokenMonitor()
monitor.start(agent.context)
output = agent.run()
monitor.end(output)
monitor.report()