DSPy与Agentic RAG:让AI系统自我进化
·
第一部分:DSPy自动优化
1.1 DSPy的核心创新
传统方式的问题:
Prompt = 字符串
优化 = 手动改字符串
评估 = 靠感觉
DSPy的突破:
Prompt = 可优化的参数
优化 = 搜索算法
评估 = 量化函数
类比深度学习:
- 神经网络权重 ≈ DSPy的Prompt
- 梯度下降 ≈ DSPy的优化器
- 损失函数 ≈ DSPy的评估函数
1.2 三步实现DSPy优化
Step 1:定义Program
import dspy
class GenerationAgent(dspy.Module):
def __init__(self):
super().__init__()
# 定义输入→输出
self.generate = dspy.ChainOfThought(
"query, context -> recommendation"
)
def forward(self, query, context):
result = self.generate(query=query, context=context)
return result.recommendation
Step 2:定义评估函数
def metric(example, pred, trace=None):
# 相关性
relevance = calculate_relevance(example.query, pred.recommendation)
# 忠实度
faithfulness = calculate_faithfulness(pred.recommendation, example.context)
return relevance * 0.5 + faithfulness * 0.5
Step 3:自动优化
from dspy.teleprompt import BootstrapFewShot
optimizer = BootstrapFewShot(metric=metric, max_bootstrapped_demos=4)
optimized_agent = optimizer.compile(student=GenerationAgent(), trainset=trainset)
1.3 效果对比
| 指标 | 手动Prompt | DSPy优化 | 提升 |
|---|---|---|---|
| 准确率 | 72% | 83% | +15% |
| 调优时间 | 2小时 | 5分钟 | -96% |
注意:不是所有场景都能提升这么多,取决于:
- 训练数据质量(我用了200条)
- 评估函数设计
- 任务复杂度
1.4 我踩过的坑
坑1:训练数据太少
# 50条训练数据:准确率68%(比手动还差)
# 100条训练数据:准确率75%
# 200条训练数据:准确率83% ✓
教训:至少需要100-200条训练数据。
坑2:Few-shot示例过多
# 测试不同数量的示例
4个示例:准确率83% ← 最佳
8个示例:准确率81%
16个示例:准确率76%(过拟合)
教训:4-8个示例最佳。
坑3:评估函数设计不当
# 错误:只看准确率
def bad_metric(example, pred):
return int(pred.recommendation == example.answer)
# 正确:多维度评估
def good_metric(example, pred):
relevance = calculate_relevance(example.query, pred.recommendation)
faithfulness = calculate_faithfulness(pred.recommendation, example.context)
completeness = calculate_completeness(pred.recommendation, example.required_fields)
return relevance * 0.4 + faithfulness * 0.4 + completeness * 0.2
教训:评估函数要全面,否则优化方向会偏。
1.5 完整实现示例
import dspy
from typing import List, Dict
class HouseRecommendationAgent(dspy.Module):
def __init__(self):
super().__init__()
self.generate = dspy.ChainOfThought(
"query, context, memory -> recommendation, reasoning"
)
def forward(self, query: str, context: List[Dict], memory: str):
# 格式化上下文
context_str = "\n".join([
f"房源{i+1}: {doc['title']}, {doc['price']}, {doc['location']}"
for i, doc in enumerate(context)
])
# 生成推荐
result = self.generate(
query=query,
context=context_str,
memory=memory
)
return {
"recommendation": result.recommendation,
"reasoning": result.reasoning
}
# 训练数据准备
trainset = [
dspy.Example(
query="3室2厅,预算500万,靠近地铁",
context=[...], # 检索到的房源
memory="用户偏好:现代风格,重视交通",
answer="推荐房源A,理由:..."
).with_inputs("query", "context", "memory"),
# ... 更多示例
]
# 优化
optimizer = dspy.teleprompt.BootstrapFewShot(
metric=good_metric,
max_bootstrapped_demos=4,
max_labeled_demos=4
)
optimized_agent = optimizer.compile(
student=HouseRecommendationAgent(),
trainset=trainset
)
# 保存模型
optimized_agent.save("models/optimized_agent.json")
1.6 关键洞察
💡 洞察1:Prompt是可优化的参数,不是固定字符串
💡 洞察2:Few-shot示例的选择比数量更重要(4个精选 > 16个随机)
💡 洞察3:评估函数决定优化方向(多指标平衡很重要)
💡 洞察4:训练数据质量最重要(至少100-200条)
💡 洞察5:不是所有场景都适合DSPy(简单任务手动Prompt就够了)
第二部分:Agentic RAG智能检索
2.1 三大核心技术
技术1:Self-RAG(检索后反思)
核心思想:检索后评估质量,过滤无关文档
class SelfRAG:
def retrieve_and_reflect(self, query):
# 1. 检索
documents = self.retriever.retrieve(query)
# 2. 反思:评估相关性
relevance_scores = self._score_relevance(query, documents)
# 3. 过滤
relevant_docs = [doc for doc, score in zip(documents, relevance_scores)
if score > 0.7]
return relevant_docs
效果:
- 检索相关性:0.72 → 0.85(+18%)
- 过滤掉约60%的无关文档
技术2:Corrective RAG(查询改写)
核心思想:检索质量低时,改写查询重试
class CorrectiveRAG:
def retrieve_with_correction(self, query, max_attempts=2):
for attempt in range(max_attempts):
documents = self.retriever.retrieve(query)
quality = self._evaluate_quality(query, documents)
if quality > 0.75:
return documents
# 改写查询
query = self._rewrite_query(query)
return documents
效果:
- 检索成功率:75% → 87%(+16%)
- 平均重试1.2次
技术3:Adaptive Routing(自适应策略)
核心思想:根据查询复杂度选择策略
class AdaptiveRetriever:
def retrieve(self, query):
complexity = self._analyze_complexity(query)
if complexity == "简单":
return self._fast_retrieve(query, top_k=5)
else:
return self._deep_retrieve(query, top_k=20)
效果:
- 简单查询:响应时间-40%
- 复杂查询:准确率+25%
2.2 整体效果
| 方法 | 准确率 | 响应时间 |
|---|---|---|
| 传统RAG | 72% | 650ms |
| + Self-RAG | 78% | 700ms |
| + Corrective RAG | 81% | 600ms |
| + Adaptive Routing | 83% | 480ms |
关键发现:
- Self-RAG贡献最大(+6%)
- Corrective RAG提升稳定性(+3%)
- Adaptive Routing优化性能(+2%,-120ms)
2.3 我踩过的坑
坑4:重试次数过多
# 1次重试:成功率+12%,响应时间+50ms
# 2次重试:成功率+16%,响应时间+100ms ✓
# 3次重试:成功率+16%,响应时间+200ms(边际收益为0)
教训:最多重试2次。
坑5:Self-RAG阈值太高
# 阈值0.9:过滤90%文档,只剩1个 ✗
# 阈值0.7:过滤60%文档,剩5-8个 ✓
# 阈值0.5:过滤30%文档,效果不明显
教训:阈值0.7左右最佳。
坑6:查询改写过度
# 原始查询:"3室2厅,靠近地铁"
# 改写1次:"三居室两厅,地铁沿线" ✓
# 改写2次:"多卧室住宅,公共交通便利" ✗(语义漂移)
教训:改写要保持原意,不能过度泛化。
2.4 完整实现示例
class AgenticRAGPipeline:
def __init__(self, retriever, rewriter, verifier):
self.retriever = retriever
self.rewriter = rewriter
self.verifier = verifier
def retrieve(self, query: str, max_attempts: int = 2):
"""完整的Agentic RAG流程"""
# 1. 分析查询复杂度
complexity = self._analyze_complexity(query)
top_k = 20 if complexity == "复杂" else 5
# 2. 检索 + 重试
for attempt in range(max_attempts):
documents = self.retriever.retrieve(query, top_k=top_k)
# 3. Self-RAG:评估相关性
scored_docs = []
for doc in documents:
score = self.verifier.score_relevance(query, doc)
if score > 0.7:
scored_docs.append((doc, score))
# 4. 检查质量
if len(scored_docs) >= 3:
# 按分数排序
scored_docs.sort(key=lambda x: x[1], reverse=True)
return [doc for doc, _ in scored_docs[:5]]
# 5. Corrective RAG:改写查询
if attempt < max_attempts - 1:
query = self.rewriter.rewrite(query, documents)
print(f"改写查询: {query}")
# 6. 兜底:返回最佳结果
return [doc for doc, _ in scored_docs[:3]] if scored_docs else documents[:3]
def _analyze_complexity(self, query: str) -> str:
"""分析查询复杂度"""
# 多条件 = 复杂
conditions = len([w for w in ["预算", "位置", "面积", "户型", "楼层"] if w in query])
return "复杂" if conditions >= 3 else "简单"
# 使用示例
pipeline = AgenticRAGPipeline(retriever, rewriter, verifier)
results = pipeline.retrieve("3室2厅,预算500万,靠近地铁,楼层不要太高")
2.5 关键洞察
💡 洞察1:检索不是一次性的,需要反思和调整
💡 洞察2:检索质量比数量更重要(5个高质量 > 20个低质量)
💡 洞察3:不同查询需要不同策略(简单查询快速检索,复杂查询深度检索)
💡 洞察4:重试次数要控制(1-2次最佳)
💡 洞察5:性能和准确率要平衡(不能为了准确率牺牲太多性能)
第三部分:记忆系统集成
3.1 集成要点
记忆系统与DSPy集成:
# 记忆上下文作为DSPy的输入
memory_context = build_memory_context(memory_manager, entity_memory, bias_manager)
result = optimized_agent(
query=query,
context=context,
memory=memory_context # 包含用户偏好、历史对话
)
记忆系统与Agentic RAG集成:
- 检索记忆:缓存结果,避免重复检索
- 偏置记忆:个性化检索策略
- 实体记忆:指代消解
3.2 效果
| 指标 | 无记忆 | 有记忆 | 提升 |
|---|---|---|---|
| 多轮对话准确率 | 68% | 81% | +19% |
| 重复推荐率 | 38% | 0% | -100% |
| 响应时间 | 650ms | 480ms | -26% |
第四部分:实验结果
4.1 整体效果
| 指标 | 基线 | 优化后 | 提升 |
|---|---|---|---|
| 整体准确率 | 72% | 83% | +15% |
| 复杂查询准确率 | 65% | 81% | +25% |
| 检索相关性 | 0.72 | 0.85 | +18% |
| 响应时间 | 650ms | 480ms | -26% |
| 重复推荐率 | 38% | 0% | -100% |
说明:
- 数据基于200条训练集、50条测试集
- 运行环境:本地CPU(16GB内存)
- API成本:约$3(使用GPT-3.5)
4.2 消融实验
| 配置 | 准确率 | 提升 |
|---|---|---|
| 基线 | 72% | - |
| + DSPy | 77% | +5% |
| + Self-RAG | 80% | +3% |
| + Corrective RAG | 82% | +2% |
| + 记忆系统 | 83% | +1% |
结论:
- DSPy贡献最大(+5%)
- Self-RAG是核心(+3%)
- 其他技术锦上添花(+3%)
4.3 实战经验
经验1:优化器选择
- 简单任务用BootstrapFewShot(快10倍)
- 复杂任务用MIPROv2(准5%)
经验2:缓存策略
- 必须缓存优化结果
- 否则每次都重新优化(耗时5分钟)
- 方案:保存为JSON文件,TTL=7天
经验3:记忆容量控制
- 短期记忆:5轮
- 实体记忆:最近5个
- 总Token:<2000
总结
从手动调优到自动优化,从被动检索到主动思考,我们的系统经历了质的飞跃。
核心收获:
- DSPy:Prompt调优时间-96%,准确率+15%
- Agentic RAG:检索相关性+18%,复杂查询准确率+25%
- 记忆系统:多轮对话准确率+19%,重复推荐率-100%
但也要注意:
- 不是所有场景都能达到这个效果
- 数据质量很重要(垃圾进,垃圾出)
- 要根据实际情况调整参数
最重要的是:系统现在能自我优化了!
更多推荐



所有评论(0)