AgentDepthAgent 工程学习指南
输入概念或问题,检索正文和待编写目录。
第一次学习?从 L0 总览开始 →

Agentic RAG 与动态检索

我的学习 →

正在读取学习记录…

普通检索常把问题一次送入检索器,再用返回的资料回答。Agentic RAG 会检查已有资料还缺什么,选择下一次检索,获得新证据后再判断是否可以回答。Agentic表示由Agent的决策流程控制检索。

客户问“生鲜签收第10天还能退吗”,需要期限和商品例外两个事实。先找到期限时,下一步可以专门查商品例外。像查办一件售后申请:手边已有订单信息,就去补缺少的规则,不必每次从头翻全部资料。

将“还缺什么”写成可检查的状态

程序把作答需要的事实列成 deadline 与 exception,分别表示期限和例外。已得到的事实放在字典里;每轮从尚未得到的字段中选择下一项。固定资料库先提供7天期限,再提供生鲜例外。

停止条件有三个:两项齐全就回答;检索次数达到上限就说明仍缺哪项;某项没有资料就停止并报告缺口。最后一次允许的检索补齐资料时,也应正常回答。

每轮只补当前缺口:需要:期限 + 商品例外,已有事实:空;第1次查期限 → 得到7天,缺口缩为商品例外;第2次查例外 → 得到生鲜,两项齐全 → 回答并停止;次数用尽 / 无资料,列出缺口 → 暂不能判断
图1:每轮只补当前缺口。

跟着固定样本运行

先在 PowerShell 创建并进入学习目录:

Bash
mkdir "F:\学习\l5-agentic-rag" -Force
cd "F:\学习\l5-agentic-rag"

保存下面的文件后,在这个终端运行 dir 核对文件名,再执行本节给出的运行命令。

新建 F:\学习\l5-agentic-rag,将下面完整代码保存为 agentic_rag_demo.py。

先在 PowerShell 创建并进入学习目录:

Bash
mkdir "F:\学习\l5-agentic-rag" -Force
cd "F:\学习\l5-agentic-rag"

保存下面的文件后,在这个终端运行 dir 核对文件名,再执行本节给出的运行命令。

Python
"""按证据缺口选择检索,并在明确条件下停止。"""
REQUIRED = ("deadline", "exception")
CORPUS = {"deadline": 7, "exception": "生鲜"}


def run(corpus, max_searches=2):
    if max_searches < 0:
        raise ValueError("检索上限必须非负")
    facts, trace = {}, []
    for _ in range(max_searches):
        missing = [key for key in REQUIRED if key not in facts]
        if not missing:
            break
        target = missing[0]
        trace.append("检索:" + target)
        # 检索指定事实;查不到就停止,避免重复同一空请求。
        if target not in corpus:
            return "资料缺失:" + target, facts, trace
        facts[target] = corpus[target]
    # 先检查事实齐全,再检查预算,允许最后一次检索成功。
    missing = [key for key in REQUIRED if key not in facts]
    if missing:
        return "次数用尽,仍缺:" + "、".join(missing), facts, trace
    return "证据齐全", facts, trace


def answer(facts, day=10, product="生鲜"):
    if any(key not in facts for key in REQUIRED):
        return "需要补充规则,暂不能判断。"
    if product == facts["exception"]:
        return "生鲜属于例外,不能按无理由退货规则申请。"
    return "期限内可申请。" if day <= facts["deadline"] else "超过退货期限。"


if __name__ == "__main__":
    for label, corpus, budget in (
        ("正常", CORPUS, 2),
        ("上限1次", CORPUS, 1),
        ("缺少例外资料", {"deadline": 7}, 2),
    ):
        status, facts, trace = run(corpus, budget)
        print(f"{label}:" + " → ".join(trace) + ";" + status)
        print("答复:" + answer(facts))

在 PowerShell 中进入保存目录并运行:

Bash
cd "F:\学习\l5-agentic-rag"
ls
python -X utf8 agentic_rag_demo.py

输出为:

TXT
正常:检索:deadline → 检索:exception;证据齐全
答复:生鲜属于例外,不能按无理由退货规则申请。
上限1次:检索:deadline;次数用尽,仍缺:exception
答复:需要补充规则,暂不能判断。
缺少例外资料:检索:deadline → 检索:exception;资料缺失:exception
答复:需要补充规则,暂不能判断。

正常场景用两次检索补齐期限和例外,随后给出答复。上限1次时已有期限、缺少例外,程序没有把“7天”当成完整答案。第三组有两次额度,但资料库没有例外条目,所以以资料缺失停止。

trace 是检索过程记录,显示选择了哪些目标;facts 是已经得到的证据。两者分开,才能同时回答“过程做了什么”和“最终知道什么”。

决策依赖证据,停止依赖条件

示例使用固定规则选择第一个缺口。实际Agent可以让模型提议下一条查询、改写关键词、选择不同检索器;程序仍需要验证查询范围、次数和资料权限。动态是查询随已得信息变化,增加轮数只是为补充证据提供机会。

真实检索返回长文本,需要将原文、来源和提取字段一起保存。字段提取错误会让缺口检查误以为信息齐全。条款矛盾时也不能只按字段是否存在判断:应该比较版本、有效期和适用对象,再决定是否继续查证。

查不到时还能换一种查法吗

当前程序遇到缺失条目立即停止。真实资料库可以安排一次查询改写,例如将“生鲜退货”换为“无理由退货商品例外”。改写也消耗检索次数;重复查询、连续无新证据与总时间都可以成为额外停止条件。

增加检索轮数可能带来更完整证据,也可能带来重复片段、费用和延迟。评估时同时看最终答对率、调用次数及每轮新增有效事实,判断多出的步骤是否值得。

用固定改法观察停止

把正常场景的额度2改成5,再运行,正常行依然只有两次检索。程序在证据齐全后停止。改成1时,它会走已有的次数用尽路径;恢复2后再次得到完整答复。

现象检查位置
总在重复查同一内容缺口是否随新证据更新
最后一轮拿齐资料却返回失败成功检查与预算检查的先后
拿到两段文字仍无法回答所需事实是否真的被覆盖
资料互相矛盾来源版本、适用对象与有效期

检查实现中的六种情况

在同一目录将下面测试保存为 test_agentic_rag_demo.py。测试覆盖正文中的正常路径与边界条件。

测试代码:test_agentic_rag_demo.py
Python
"""检查动态检索的证据、预算与停止顺序。"""
import unittest
from agentic_rag_demo import CORPUS, run, answer


class AgenticRagTests(unittest.TestCase):
    def test_final_allowed_search_succeeds(self):
        status, facts, trace = run(CORPUS, 2)
        self.assertEqual(status, "证据齐全")
        self.assertEqual(len(trace), 2)
        self.assertIn("属于例外", answer(facts))

    def test_budget_exhausted(self):
        status, facts, trace = run(CORPUS, 1)
        self.assertIn("仍缺:exception", status)
        self.assertEqual(facts, {"deadline": 7})

    def test_missing_document_stops(self):
        status, facts, trace = run({"deadline": 7}, 5)
        self.assertEqual(status, "资料缺失:exception")
        self.assertEqual(len(trace), 2)

    def test_extra_budget_does_not_add_searches(self):
        self.assertEqual(len(run(CORPUS, 10)[2]), 2)

    def test_zero_budget(self):
        self.assertEqual(run(CORPUS, 0)[1], {})

    def test_negative_budget(self):
        with self.assertRaises(ValueError):
            run(CORPUS, -1)


if __name__ == "__main__":
    unittest.main()
Bash
cd "F:\学习\l5-agentic-rag"
python -X utf8 -m unittest -v test_agentic_rag_demo

应显示6项通过。将主程序恢复到上面的固定输入后,可以再次对照完整输出。

课后练习展开习题收起习题

4 道练习 · 客观题规则评分 · 其余题目待批改

正在读取本地记录…

不调用模型,不执行代码。简答、代码和场景题仅保存答案并展示自查标准,不生成评分、徽章或认证。输入内容不会自动保存,请点击提交;不要填写个人信息或密钥。

练习 1 / 4 · v1.0.1

选择题 · 先判断边界

关于“Agentic RAG 与动态检索”,哪种做法更稳妥?

对应知识点:L5-agentic-rag

选择一个答案
练习 2 / 4 · v1.0.0

简答题 · 解释失败

写出一个失败输入并说明记录字段。

对应知识点:L5-agentic-rag

练习 3 / 4 · v1.0.0

代码题 · 边界测试

补充正常、边界、失败三组输入和预期结果。

对应知识点:L5-agentic-rag

练习 4 / 4 · v1.0.0

场景题 · 结果未知

证据不足时如何设计状态和人工接管?

对应知识点:L5-agentic-rag

图片查看器
100%

文章配图 · 按 Esc 关闭