Agentic RAG = 多轮任务编排升级
文章介绍 Agentic RAG:把一次检索升级为“Plan→多轮检索→Reflect补缺→结构化推荐”,适合需求模糊的咨询型任务,并通过控制阀限制轮数与成本。
Agentic RAG 房产顾问学习笔记:GraphRAG 解决关系链,但复杂需求还需要"流程编排"
这是我学习 Agentic RAG 的完整记录。通过 3 个递进式 demo,从零跑通 Agentic RAG 的核心循环:拆问题 → 多轮检索 → 补条件 → 输出对比推荐。
前言
上一篇我学了 GraphRAG,解决了"关系链检索"的问题。但我发现还有一个更大的问题:用户的需求本身就是"多轮、多维度、需要澄清"的。
比如用户问"帮我推荐一套房子",这个问题太模糊了。传统 RAG 一次检索很难覆盖所有维度。
一句话定位:
- GraphRAG 是"检索模块升级"(把检索从"相似度"升级到"关系链")
- Agentic RAG 是"咨询流程升级"(把问答从"一次检索"升级到"多轮流程")
Agentic RAG 不是"更强的检索",而是把问答变成"可控的多轮流程",让系统像真正的买房顾问一样,能够多轮澄清、逐步推荐。
本文记录了我从零开始学习 Agentic RAG 的完整过程,包括 3 个本地 demo 和对应的讲解。
第二部分:同一个问题,GraphRAG vs Agentic RAG 怎么跑
用户问题: “我在国贸上班,预算 600万,想买三居,最好学区,安静采光好,推荐 3 套并说理由。”
用 GraphRAG 的回答方式(单次检索)
GraphRAG 会做:
Step 1: 识别实体
国贸(目的地)、600万(预算)、三居(户型)、学区、安静、采光
Step 2: 子图扩展
国贸 ← 地铁线 ← 地铁站 ← 小区(通勤链)
小区 → 学校(学区链)
小区 → POI(配套链)
Step 3: 返回候选房源
满足"通勤 40 分钟 + 学区 + 配套"的房源 Top-5
Step 4: 生成 Evidence Table
每条推荐都有证据(来自哪个数据源)
输出:
房源 1:望京新城
- 通勤:15号线到国贸 35 分钟(来自地铁时刻表)
- 学区:对应 XX小学(来自学区数据库)
- 配套:附近有医院、商场(来自 POI 数据)
GraphRAG 的局限:
❌ 不会主动追问缺失信息
用户没说"通勤时间要多少",GraphRAG 就用默认值
❌ 不会做"多轮收敛"
用户说"安静采光好",GraphRAG 无法精准理解
❌ 不会做"多维度对比"
只返回房源列表,不会生成"对比表"
结论:GraphRAG 能把"关系链检索"做对,但它不会管理"咨询流程"
用 Agentic RAG 的回答方式(多轮流程)
Agentic RAG 会做:
Step 1: Plan(拆解需求)
硬条件:预算 600万、户型三居、地区朝阳
软条件:学区、通勤 40 分钟
偏好:安静、采光好
Step 2: 多路检索(第 1 轮)
路径 1:结构化过滤 → 预算 ≤ 600万 AND 户型 = 3 居
路径 2:GraphRAG 子图 → 通勤 40 分钟以内的小区
路径 3:GraphRAG 子图 → 有学区的小区
路径 4:向量检索 → "安静采光好"的房源描述
合并结果 → 候选 Top-50
Step 3: Reflect(查缺口)
发现:某些房源的"采光信息"缺失
决定:触发补检索
Step 4: 多路检索(第 2 轮)
补检索:采光信息
合并结果 → 候选 Top-20
Step 5: Answer(结构化输出)
生成 Top3 推荐
生成对比表(预算/户型/通勤/学区/采光/噪音)
生成理由(每条推荐都有证据)
生成下一步建议
输出:
推荐 Top3:
房源 1:望京新城(学区+地铁+采光好)
房源 2:望京花园(价格便宜 20万)
房源 3:朝阳门(采光最好)
对比表:
| 维度 | 房源1 | 房源2 | 房源3 |
|------|------|------|------|
| 价格 | 600万 | 580万 | 500万 |
| 学区 | ✅ | ✅ | ✅ |
| 通勤 | 35分钟 | 38分钟 | 42分钟 |
| 采光 | 南北通透 | 南向 | 南北通透 |
理由:
房源1:完美满足所有条件
房源2:如果你更在意预算,这是最优选
房源3:如果你更在意采光,这是最优选
Agentic RAG 的优势:
✅ 主动澄清需求
系统会问"你的通勤时间要求是多少?"
✅ 多轮补齐信息
第 1 轮检索后发现缺口,自动触发第 2 轮
✅ 结构化输出
不是"房源列表",而是"对比表 + 理由"
✅ 可控流程
最多 3 轮,每轮最多 3 次检索
结论:Agentic 把"检索能力"组织成"顾问服务"
对比总结
| 维度 | GraphRAG | Agentic RAG |
|---|---|---|
| 检索能力 | 关系链检索 | 多路融合检索 |
| 流程 | 单次 | 多轮(2~3 轮) |
| 输出 | 房源列表 + 证据 | 对比表 + 理由 + 建议 |
| 用户体验 | “这些房源符合条件” | “我给你推荐 3 套,理由是…” |
| 适用场景 | 条件明确 | 条件模糊、需要澄清 |
第三部分:核心概念
Agentic RAG 的 5 个核心概念
| 概念 | 作用 | 房产例子 |
|---|---|---|
| Plan | 拆任务 | 把"帮我推荐房子"拆成"预算/户型/通勤/学区/偏好" |
| Retrieve | 找证据 | 每个槽位分别检索(预算用结构化过滤,学区用 GraphRAG) |
| Reflect | 查缺口 | 发现"通勤时间缺失",触发补检索 |
| Iterate | 继续补证据 | 最多 2~3 轮,直到信息充分 |
| Answer | 结构化输出 | Top3 推荐 + 对比表 + 引用证据 |
类比理解
传统 RAG:查字典一次
用户问:"帮我推荐房子"
系统:一次检索,返回 Top-5 房源
问题:不完整,用户还要追问
Agentic RAG:和顾问多轮沟通
用户问:"帮我推荐房子"
系统:
第 1 轮:问"你的预算是多少?"
第 2 轮:问"你要几居室?"
第 3 轮:问"你在哪里上班?"
最后:综合所有信息,推荐 Top3 + 对比表
优势:完整、可控、像真人顾问
第二部分:为什么房产咨询适合 Agentic RAG
典型用户问题
"我在国贸上班,预算 600万,想买三居,最好学区,安静采光好,推荐 3 套并说理由。"
传统 RAG 的天花板
问题 1:一次检索不可能覆盖所有维度
维度 1:预算 600万
维度 2:户型三居
维度 3:通勤国贸
维度 4:学区
维度 5:安静
维度 6:采光好
传统 RAG:一次检索,很难同时满足 6 个维度
结果:准确率 40%(因为条件太多)
问题 2:用户需求本身就是"多轮补齐"的
用户第 1 轮:"帮我推荐房子"
→ 系统:信息不足,无法推荐
用户第 2 轮:"预算 600万"
→ 系统:还需要知道户型、地区
用户第 3 轮:"三居,朝阳区"
→ 系统:还需要知道通勤目标、学区需求
用户第 4 轮:"国贸上班,要学区"
→ 系统:现在信息充分,可以推荐了
Agentic RAG 的价值
✅ 自动澄清需求
系统主动问"你的预算是多少?"
而不是等用户说
✅ 多轮补证据
第 1 轮:检索预算范围内的房源
第 2 轮:检索有学区的房源
第 3 轮:检索通勤时间合适的房源
最后:求交集
✅ 结构化输出
不是"房源列表"
而是"Top3 推荐 + 对比表 + 理由"
第三部分:3 个递进式 Demo
Demo 1:最小 Planner(槽位拆解器)
目标: 理解"Agent 怎么理解用户需求"
用户输入:
"我在国贸上班,预算 600万,想买三居,最好学区,安静采光好"
Planner 的工作:拆解成结构化的槽位
def plan_user_request(user_query):
"""
把用户问题拆解成结构化的槽位
"""
plan = {
# 硬条件(必须满足)
"hard_constraints": {
"budget": 600, # 预算 600万
"rooms": 3, # 三居
"district": "朝阳", # 朝阳区
},
# 软条件(优先满足)
"soft_constraints": {
"school": True, # 要学区
"commute_time": 40, # 通勤 40 分钟以内
},
# 偏好(参考)
"preferences": {
"quiet": True, # 安静
"sunlight": True, # 采光好
},
# 缺失的信息
"missing_info": [
"通勤目标地址",
"对装修风格的要求",
"对物业的要求"
]
}
return plan
# 使用示例
plan = plan_user_request("我在国贸上班,预算 600万,想买三居,最好学区,安静采光好")
print(f"硬条件:{plan['hard_constraints']}")
print(f"软条件:{plan['soft_constraints']}")
print(f"缺失信息:{plan['missing_info']}")
关键点:
- Plan 的输出是"结构化的槽位",不是"自由文本"
- 这样后续的检索才能"有针对性"
- 缺失的信息会触发"多轮澄清"
Demo 2:多路检索(每个槽位独立召回)
目标: 看到"多维度组合"怎么做
检索流程(用箭头链路表达):
Plan 输出:{budget: 600, rooms: 3, school: True, commute: 40}
↓
Step 1: 硬条件检索(结构化过滤)
预算 ≤ 600万 AND 户型 = 3 居
→ 候选房源 Top-100
↓
Step 2: 学区检索(GraphRAG 子图)
小区 → 学校
→ 有学区的房源 Top-50
↓
Step 3: 通勤检索(GraphRAG 子图)
小区 → 地铁站 → 国贸
→ 通勤 40 分钟以内的房源 Top-50
↓
Step 4: 偏好检索(向量检索)
"安静""采光好"
→ 符合偏好的房源 Top-50
↓
Step 5: 融合结果
合并 → 去重 → rerank
→ 最终候选 Top-20
代码实现:
def multi_path_retrieval(plan, data_sources):
"""
多路检索:每个维度独立召回
"""
results = {
"budget_results": [],
"school_results": [],
"commute_results": [],
"preference_results": []
}
# 路径 1:硬条件检索(结构化过滤)
results["budget_results"] = filter_by_constraints(
data_sources["houses"],
budget=plan["hard_constraints"]["budget"],
rooms=plan["hard_constraints"]["rooms"]
)
# 路径 2:学区检索(GraphRAG)
if plan["soft_constraints"].get("school"):
results["school_results"] = graphrag_school_search(
data_sources["graph"],
district=plan["hard_constraints"]["district"]
)
# 路径 3:通勤检索(GraphRAG)
if plan["soft_constraints"].get("commute_time"):
results["commute_results"] = graphrag_commute_search(
data_sources["graph"],
destination="国贸",
max_time=plan["soft_constraints"]["commute_time"]
)
# 路径 4:偏好检索(向量检索)
if plan["preferences"].get("quiet") or plan["preferences"].get("sunlight"):
results["preference_results"] = vector_search(
data_sources["embeddings"],
query="安静采光好"
)
# 融合结果
merged = merge_results(results)
return merged
# 使用示例
candidates = multi_path_retrieval(plan, data_sources)
print(f"最终候选房源数:{len(candidates)}")
关键点:
- 不同的维度用不同的检索方式
- 硬条件用"结构化过滤"(快、准)
- 软条件用"GraphRAG"(关系链)
- 偏好用"向量检索"(语义)
- 最后融合结果
Demo 3:Reflect + Iterate(补缺口)
目标: 理解"Agent 怎么自我纠正"
场景: 第一轮检索后,发现某些信息缺失
def reflect_and_iterate(candidates, plan, iteration=1, max_iterations=3):
"""
反思:检查是否有缺口
迭代:补充缺失的信息
"""
# Step 1: 反思(Reflect)
gaps = check_gaps(candidates, plan)
# 例如:发现"学区信息缺失"、"通勤时间不确定"
if not gaps or iteration >= max_iterations:
# 信息充分,停止迭代
return candidates
# Step 2: 迭代(Iterate)
for gap in gaps:
if gap == "school_info":
# 补检索:学区信息
school_results = graphrag_school_search(...)
candidates = merge_results(candidates, school_results)
elif gap == "commute_time":
# 补检索:通勤时间
commute_results = graphrag_commute_search(...)
candidates = merge_results(candidates, commute_results)
elif gap == "preference_match":
# 补检索:偏好匹配
pref_results = vector_search(...)
candidates = merge_results(candidates, pref_results)
# Step 3: 递归迭代
return reflect_and_iterate(
candidates,
plan,
iteration=iteration + 1,
max_iterations=max_iterations
)
# 使用示例
final_candidates = reflect_and_iterate(candidates, plan)
print(f"经过迭代后的候选房源数:{len(final_candidates)}")
关键点:
- Reflect:检查是否有缺口
- Iterate:补充缺失的信息
- 最多迭代 2~3 轮(避免无限循环)
第四部分:控制阀
为什么需要控制阀?
没有控制阀:
Agent 可能查 10 轮,成本爆炸
Agent 可能陷入"无限循环"
有控制阀:
Agent 最多查 3 轮
每轮最多 3 次检索
成本可控
三个控制阀:
def agentic_rag_with_controls(user_query, data_sources):
"""
带控制阀的 Agentic RAG
"""
# 控制阀 1:最大轮数
MAX_ROUNDS = 3
# 控制阀 2:每轮最多检索次数
MAX_RETRIEVAL_PER_ROUND = 3
# 控制阀 3:超预算降级
BUDGET_THRESHOLD = 1000 # token 数
plan = plan_user_request(user_query)
candidates = []
round_count = 0
total_cost = 0
while round_count < MAX_ROUNDS:
round_count += 1
# 检查成本
if total_cost > BUDGET_THRESHOLD:
print("成本超预算,降级到普通 RAG")
return simple_rag(user_query, data_sources)
# 多路检索(最多 3 次)
retrieval_count = 0
for path in ["budget", "school", "commute", "preference"]:
if retrieval_count >= MAX_RETRIEVAL_PER_ROUND:
break
results = retrieve_by_path(path, plan, data_sources)
candidates = merge_results(candidates, results)
retrieval_count += 1
total_cost += estimate_cost(results)
# 反思和迭代
gaps = check_gaps(candidates, plan)
if not gaps:
# 信息充分,停止
break
return candidates
# 使用示例
candidates = agentic_rag_with_controls(user_query, data_sources)
推荐配置:
max_rounds = 3
理由:房产咨询通常 3 轮就能收敛
超过 3 轮:说明需求太复杂或 Agent 在"越查越偏"
per_round_retrieve <= 3
理由:预算、学区、通勤各查一次就够
超过 3 次:说明 Agent 在"无限补条件"
总候选 <= 80
理由:80 套房源已经足够多样化
超过 80 套:成本爆炸,用户也看不完
降级策略:
- 超预算 → 走普通 RAG(一次检索)
- 证据不足 → 输出"目前能确定的部分 + 需要补充的问题"
- 高峰期 → 关闭 Agentic,用普通 RAG
第五部分:输出
固定输出模板:
推荐 Top3:
房源 1:望京新城 3 居
一句话总结:学区+地铁+采光好,完美满足你的需求
房源 2:望京花园 3 居
一句话总结:价格便宜 20万,学区+地铁,采光稍差
房源 3:朝阳门 2 居
一句话总结:最新装修,采光最好,但离地铁稍远
对比表:
| 维度 | 房源1 | 房源2 | 房源3 |
|------|------|------|------|
| 价格 | 600万 | 580万 | 500万 |
| 户型 | 3居 | 3居 | 2居 |
| 学区 | ✅ | ✅ | ✅ |
| 地铁 | 500m | 600m | 1.2km |
| 通勤 | 35分钟 | 38分钟 | 42分钟 |
| 采光 | 南北通透 | 南向 | 南北通透 |
| 噪音 | 安静 | 一般 | 安静 |
为什么推荐(Evidence Table):
房源1:
- 学区:对应 XX小学(来自学区数据库)
- 地铁:距离 15号线望京站 500m(来自 POI 数据)
- 通勤:15号线到国贸 35 分钟(来自地铁时刻表)
- 采光:南北通透(来自房源描述)
下一步建议:
- 如果你更在意学区,可以考虑房源2(便宜20万)
- 如果你更在意采光,可以考虑房源3(最新装修)
- 建议实地看房,确认采光和噪音
代码实现:
def generate_structured_output(top3_candidates, plan):
"""
生成结构化的推荐输出
"""
output = {
"recommendations": [],
"comparison_table": [],
"evidence_table": [],
"next_steps": []
}
for idx, candidate in enumerate(top3_candidates, 1):
# 一句话总结
summary = generate_summary(candidate, plan)
# 对比表数据
comparison_row = extract_comparison_data(candidate)
# 证据表
evidence = build_evidence_table(candidate)
output["recommendations"].append({
"rank": idx,
"house": candidate,
"summary": summary
})
output["comparison_table"].append(comparison_row)
output["evidence_table"].append(evidence)
# 下一步建议
output["next_steps"] = generate_next_steps(top3_candidates, plan)
return output
# 使用示例
output = generate_structured_output(top3_candidates, plan)
print(output)
第六部分:现实代价(难、贵、慢)
这一节很重要。Agentic RAG 看起来很强,但它有结构性的代价。
难:流程状态机 + 停止条件
问题: Agentic RAG 不是"一个函数",而是"一个状态机"
传统 RAG:
input → retrieve → generate → output
简单、直线
Agentic RAG:
input → plan → retrieve → reflect → iterate → answer → output
复杂、有分支、有循环
难点:
1. 状态管理:当前在哪一步?
2. 停止条件:什么时候停止迭代?
3. 错误恢复:如果某一步失败怎么办?
4. 上下文维护:多轮之间的信息怎么传递?
工程成本: 需要写"状态机"代码,不能简单地调用一个函数
贵:多轮调用的结构性成本
成本公式:
普通 RAG 成本:
= 1 次 embedding(query)
+ 1 次 retrieval
+ 1 次 LLM 调用(生成)
≈ 1x
GraphRAG 成本:
= 1 次 embedding(query)
+ 1 次复杂 retrieval(子图扩展)
+ 1 次 LLM 调用(生成)
≈ 1.2x(因为子图扩展更复杂)
Agentic RAG 成本:
= 1 次 Plan(LLM 调用)
+ 多轮 Retrieve(每轮 3 次检索)
+ 多轮 Reflect(每轮 1 次 LLM 调用)
+ 1 次 Answer(LLM 调用)
≈ (1 + 3*轮数 + 轮数 + 1) = 5 + 4*轮数
如果轮数 = 3:成本 ≈ 17x
如果轮数 = 2:成本 ≈ 13x
结论: Agentic 的成本不是"贵一点",而是"结构性更贵"
慢:每轮检索 + 反思叠加
延迟公式:
普通 RAG 延迟:
= embedding 时间(50ms)
+ retrieval 时间(100ms)
+ LLM 生成时间(500ms)
≈ 650ms
GraphRAG 延迟:
= embedding 时间(50ms)
+ 复杂 retrieval 时间(200ms)
+ LLM 生成时间(500ms)
≈ 750ms
Agentic RAG 延迟:
= Plan(LLM 调用 500ms)
+ 多轮 Retrieve(每轮 200ms * 3 = 600ms)
+ 多轮 Reflect(每轮 LLM 调用 300ms)
+ Answer(LLM 调用 500ms)
如果轮数 = 3:
= 500 + (600 + 300) * 3 + 500
= 500 + 2700 + 500
≈ 3700ms(3.7 秒)
结论: Agentic 的延迟是普通 RAG 的 5~6 倍
易翻车:跑偏、循环、证据冲突
翻车场景 1:跑偏
用户问:"帮我推荐房子"
Agent Plan 拆成:[预算][户型][地区][学区][通勤][采光][噪音][物业][升值潜力]
Agent 开始查询:[预算] → [户型] → [地区] → [学区] → [通勤] → ...
结果:查了 10 轮,还在补条件,用户已经烦了
原因:没有明确的"停止条件"
翻车场景 2:循环
Agent 第 1 轮:检索"学区房"
Agent 第 2 轮:发现"学区信息缺失",再检索
Agent 第 3 轮:发现"通勤信息缺失",再检索
Agent 第 4 轮:发现"采光信息缺失",再检索
...
结果:无限循环
原因:没有"缺口判断"的阈值
翻车场景 3:证据冲突
Agent 从 3 个数据源各找到一个"学区"信息,但互相矛盾:
数据源 1:对应 XX小学
数据源 2:对应 YY小学
数据源 3:对应 ZZ小学
结果:最后输出"混合答案",用户困惑
原因:没有"冲突检测"和"冲突解决"机制
第七部分:企业级迁移
从 demo 到生产,需要补 4 个模块:
模块 1:Slot 设计
# 硬条件 Slots(必须有)
hard_slots = {
"budget": {"type": "number", "required": True},
"rooms": {"type": "number", "required": True},
"district": {"type": "string", "required": True},
}
# 软条件 Slots(优先有)
soft_slots = {
"school": {"type": "boolean", "required": False},
"commute_time": {"type": "number", "required": False},
"subway_distance": {"type": "number", "required": False},
}
# 可选 Slots(参考)
optional_slots = {
"decoration": {"type": "string", "required": False},
"property_management": {"type": "string", "required": False},
"appreciation_potential": {"type": "string", "required": False},
}
模块 2:多源融合
def multi_source_fusion(plan):
"""
结合多个数据源
"""
results = {
"structured": [], # 结构化数据(预算、户型)
"vector": [], # 向量数据(采光、安静)
"graph": [] # 关系数据(通勤、学区)
}
# 结构化数据:预算、户型
results["structured"] = filter_by_constraints(
budget=plan["budget"],
rooms=plan["rooms"]
)
# 向量数据:采光、安静、装修风格
results["vector"] = vector_search(
query="采光好 安静 装修风格"
)
# 关系数据:通勤、学区(GraphRAG)
results["graph"] = graphrag_search(
commute_target="国贸",
school_required=True
)
# 融合
merged = merge_multi_source(results)
return merged
模块 3:冲突处理
def handle_conflicts(candidates):
"""
处理多个数据源的冲突
"""
conflicts = []
for candidate in candidates:
# 检查是否有冲突
# 例如:学区数据库说"对应 XX小学"
# 房源描述说"对应 YY小学"
if has_conflict(candidate):
conflicts.append({
"house": candidate,
"conflict_type": "school_mismatch",
"flag": "⚠️ 学区信息有争议"
})
return conflicts
# 使用示例
conflicts = handle_conflicts(candidates)
for conflict in conflicts:
print(f"{conflict['house']}: {conflict['flag']}")
模块 4:多样性约束
def ensure_diversity(top3_candidates):
"""
确保 Top3 来自不同小区
"""
communities = set()
diverse_candidates = []
for candidate in top3_candidates:
community = candidate["community"]
if community not in communities:
diverse_candidates.append(candidate)
communities.add(community)
if len(diverse_candidates) >= 3:
break
return diverse_candidates
# 使用示例
top3 = ensure_diversity(candidates)
第八部分:下一步计划
下一篇我会学习 Verification RAG,用多源验证和冲突检测,把"推荐准确性"做得更可靠。
关键点: Agentic RAG 把"流程"补齐了,但检索结果不一定准确。
比如系统推荐"望京新城对应 XX小学",但实际上对应的是 YY小学。或者说"通勤 35 分钟",但实际是 45 分钟。
这就是 Verification RAG 上场的原因——它不是"更强的流程",而是"在检索后加一层验证阀",确保推荐信息准确可信。
总结
什么时候用 Agentic RAG?
不是"所有场景都用",而是"特定场景才用":
✅ 用 Agentic RAG:
- 用户需求模糊、需要多轮澄清
- 需要"结构化输出"(对比表、理由)
- 高价值、低 QPS 场景(用户愿意等待)
- 传统 RAG 的完整性 < 70%
❌ 不用 Agentic RAG:
- 高 QPS 场景(成本爆炸)
- 用户需求明确(一次检索就够)
- 低价值场景(用户不在乎完整性)
- 没有评估闭环(无法判断是否变好)
怎么快速上手?
第 1 步:从 Demo 1 开始
理解 Planner(槽位拆解)
第 2 步:到 Demo 2
理解多路检索(多维度组合)
第 3 步:到 Demo 3
理解 Reflect + Iterate(补缺口)
第 4 步:加控制阀
理解成本、延迟、降级策略
下一步怎么优化?
1. 加 Slot 设计
区分硬条件/软条件/可选
2. 加多源融合
结构化 + 向量 + 关系(GraphRAG)
3. 加冲突处理
多个数据源不一致怎么办
4. 加多样性约束
Top3 来自不同小区
5. 加监控和评估
实时监控成本、延迟、满意度
最后一句话:
Agentic RAG 解决的是"怎么把能力组织成服务"。
它不是"更强的检索",而是"更好的流程"。
这就是我的 Agentic RAG 学习笔记。希望能帮助你快速上手!
更多推荐

所有评论(0)