BrainBank
AI 课堂/AI 评测DeepLearningAI

M4 智能体式人工智能 - 为研究工作流添加组件级评估

2026/8/5 17:04:19

#evaluation#ai-evaluation#lab#research

动手实验:将一个使用工具的智能体中的研究步骤单独隔离出来,构建一个客观的、针对单个样例的组件级评估,依据一份优选域名列表为检索到的 URL 打分。

M4 智能体式人工智能 - 为研究工作流添加组件级评估

1. 简介

在上一个评分实验(M3)中,你构建了一个使用工具的研究智能体,它执行了一个包含三个步骤的工作流:

  1. 在网络上搜索信息。
  2. 对其输出进行反思。
  3. 发布一份清晰的 HTML 报告。

现在,在这个非评分实验中,你将专注于评估该工作流中的一个组件研究步骤

在这里,你不会像之前那样生成文章并加以改进,而是要设计一个组件级评估,用来检查研究步骤所返回来源的质量。

该评估会把智能体检索到的 URL,与一份预定义的优选域名列表(例如 arxiv.orgnature.comnasa.gov)进行比对。

这让你能够使用一种客观的、针对每个样例都有明确标准答案的评估方式,来量化系统是否在从可信来源获取信息。

1.1. 实验概览

在视频中,Andrew 展示了一个网络搜索结果质量不佳的案例,使得所检索到的信息难以令人信任。 在此基础上,在这个实验中,你将通过把来源与一份预定义的优选域名列表进行比对,来评估这些来源的可靠性。

在这次评估中,我们将聚焦于*“黑洞科学的最新进展”*这个主题——这是本课程中重点介绍的案例之一。 核心思路是验证网络搜索工具返回的来源是否属于优选域名,并量化优选结果占总结果的比例。

这个评估将被实现为一个执行客观的、针对单个样例的检查的函数。它将会:

  • 解析 Tavily 的输出(我们的网络搜索工具)。
  • 识别哪些 URL 属于优选域名列表。
  • 计算优选来源与全部检索来源的比例。
  • 返回一个布尔标志(PASS/FAIL)以及一份可以直接嵌入报告的 Markdown 格式摘要。
<img src="M4-UGL-1.png" width="70%">

1.2. 🎯 学习目标

你将学会如何:

  • 编写一个函数,检查网络搜索 API 的结果中是否包含优选来源
  • 创建一个评估,验证你的来源是否来自你的优选域名
  • 为网络搜索函数添加一个组件级评估

2. 环境搭建:导入库并加载环境

与之前的实验一样,你将从导入所需的库并初始化环境开始。

# =========================
# Imports
# =========================

# --- Standard library 
from datetime import datetime
import json
import re

# --- Third-party ---
from aisuite import Client

# --- Local / project ---
import research_tools
import utils

client = Client()

3. 研究步骤 – find_references

在评分实验中,你实现的那个函数既要搜索网络,又要撰写草稿报告,全部在一个步骤中完成。

在这里,我们把网络搜索功能拆分成了一个单独的函数,叫做 find_references。这让你可以独立于撰写和反思步骤,单独评估搜索结果——由于本实验只专注于网络搜索这一步的输出,我们会把撰写和反思步骤排除在外。

请注意与评分实验实现方式的两个关键区别:

  • 这个新函数使用了 AISuite,它会自动为你管理工具调用(而不必像使用 OpenAI SDK 那样手写工具调用代码)。
  • 该函数还会告知大模型当前日期,这有助于提升对时效性较强的查询的相关性。

find_references 的作用是从诸如 ArxivTavilyWikipedia 等工具中收集外部信息。 由于这些结果的质量会直接影响评分实验中的输出,因此这正是你可以应用评估方法的阶段——例如,检查返回的 URL 是否来自你的优选域名列表。

def find_references(task: str, model: str = "openai:gpt-4o", return_messages: bool = False):
    """Perform a research task using external tools (arxiv, tavily, wikipedia)."""

    prompt = f"""
    You are a research function with access to:
    - arxiv_tool: academic papers
    - tavily_tool: general web search (return JSON when asked)
    - wikipedia_tool: encyclopedic summaries

    Task:
    {task}

    Today is {datetime.now().strftime('%Y-%m-%d')}.
    """.strip()

    messages = [{"role": "user", "content": prompt}]
    tools = [
        research_tools.arxiv_search_tool,
        research_tools.tavily_search_tool,
        research_tools.wikipedia_search_tool,
    ]

    try:
        response = client.chat.completions.create(
            model=model,
            messages=messages,
            tools=tools,
            tool_choice="auto",
            max_turns=5,
        )
        content = response.choices[0].message.content
        return (content, messages) if return_messages else content
    except Exception as e:
        return f"[Model Error: {e}]"

运行下方单元格来测试这个研究函数。 这个任务将检索两篇关于黑洞科学最新进展的近期论文,并展示结果。

research_task = "Find 2 recent papers about recent developments in black hole science"
research_result = find_references(research_task)

utils.print_html(
    research_result,
    title="Research Function Output"
)

4. 评估步骤 – 优选域名

网络搜索检索到的来源并非同等可靠。 在这个实验中,我们只聚焦于上一个评分实验中的一个步骤——即 find_references 研究步骤——展示如何设计一个组件级评估,检查返回的域名是否属于一份预先定义的优选域名列表。

这是一个具有明确的、针对单个样例的标准答案的客观评估的例子。 回想一下讲座中提到的评估的两个坐标轴:在这两个坐标轴上,我们所处的位置是左上象限——即对每个样例都有明确定义标准答案的客观评估。

<img src='M4-UGL-1-Evaluations.png' width='80%'>

为什么要做组件级评估?

正如 Andrew 在讲座中提到的:

  • 如果问题出在网络搜索环节(这通常是评分实验工作流中的第一步),每次都重新运行整个流水线(搜索 → 起草 → 反思)可能既昂贵又充满噪音。
  • 网络搜索质量上的微小改进,可能会被后续组件引入的随机性所掩盖。
  • 通过单独评估网络搜索环节,你能获得关于该组件是否在改进的更清晰的信号

当多个团队在同一个系统的不同部分上协作时,组件级评估同样很高效:每个团队都可以用一个清晰的指标来优化自己负责的组件,而无需运行或等待完整的端到端测试。

我们该如何评估?

这里的评估是客观的,因此可以通过代码来完成。它具有针对具体样例的标准答案——即这个黑洞主题查询所对应的优选来源列表。要构建这个评估,你将:

  1. 提取 Tavily 返回的 URL。
  2. 将它们与一份预定义的优选域名列表(例如 arxiv.orgnature.comnasa.gov)进行比对。
  3. 计算优选结果与全部结果的比例
  4. 返回一个 PASS/FAIL 标志,以及一份 Markdown 格式的摘要。

这提供了一个可复现、低成本的指标,能告诉我们——研究组件(也仅仅是评分实验中的这一个步骤)——是否正在从可信来源获取信息。

# list of preferred domains for Tavily results
TOP_DOMAINS = {
    # General reference / institutions / publishers
    "wikipedia.org", "nature.com", "science.org", "sciencemag.org", "cell.com",
    "mit.edu", "stanford.edu", "harvard.edu", "nasa.gov", "noaa.gov", "europa.eu",

    # CS/AI venues & indexes
    "arxiv.org", "acm.org", "ieee.org", "neurips.cc", "icml.cc", "openreview.net",

    # Other reputable outlets
    "elifesciences.org", "pnas.org", "jmlr.org", "springer.com", "sciencedirect.com",

    # Extra domains (case-specific additions)
    "pbs.org", "nova.edu", "nvcc.edu", "cccco.edu",

    # Well known programming sites
    "codecademy.com", "datacamp.com"
}

def evaluate_tavily_results(TOP_DOMAINS, raw: str, min_ratio=0.4):
    """
    Evaluate whether plain-text research results mostly come from preferred domains.

    Args:
        TOP_DOMAINS (set[str]): Set of preferred domains (e.g., 'arxiv.org', 'nature.com').
        raw (str): Plain text or Markdown containing URLs.
        min_ratio (float): Minimum preferred ratio required to pass (e.g., 0.4 = 40%).

    Returns:
        tuple[bool, str]: (flag, markdown_report)
            flag -> True if PASS, False if FAIL
            markdown_report -> Markdown-formatted summary of the evaluation
    """

    # Extract URLs from the text
    url_pattern = re.compile(r'https?://[^\s\]\)>\}]+', flags=re.IGNORECASE)
    urls = url_pattern.findall(raw)

    if not urls:
        return False, """### Evaluation — Tavily Preferred Domains
No URLs detected in the provided text. 
Please include links in your research results.
"""

    # Count preferred vs total
    total = len(urls)
    preferred_count = 0
    details = []

    for url in urls:
        domain = url.split("/")[2]
        preferred = any(td in domain for td in TOP_DOMAINS)
        if preferred:
            preferred_count += 1
        details.append(f"- {url}{'✅ PREFERRED' if preferred else '❌ NOT PREFERRED'}")

    ratio = preferred_count / total if total > 0 else 0.0
    flag = ratio >= min_ratio

    # Markdown report
    report = f"""
### Evaluation — Tavily Preferred Domains
- Total results: {total}
- Preferred results: {preferred_count}
- Ratio: {ratio:.2%}
- Threshold: {min_ratio:.0%}
- Status: {"✅ PASS" if flag else "❌ FAIL"}

**Details:**
{chr(10).join(details)}
"""
    return flag, report
<div style="border:1px solid #93c5fd; border-left:6px solid #3b82f6; background:#dbeafe; border-radius:6px; padding:12px 14px; color:#1e3a8a; font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif;"> <strong>🔎 为什么这是一个客观评估:</strong><br><br> 从 Tavily 检索到的每一个 URL,都会与一份预先定义的<em>优选域名</em>列表(<code>TOP_DOMAINS</code>)进行比对:<br> • 如果域名匹配 → ✅ PREFERRED(优选)<br> • 否则 → ❌ NOT PREFERRED(非优选)<br><br> 这样就能根据优选来源的比例是否超过给定阈值,得出一个清晰的 PASS/FAIL 信号。 由于标准答案(优选与否)对每个样例都是明确定义的,这个评估既**客观**又**可复现**。 </div>

运行下方单元格,展示优选域名示例、研究结果,以及评估摘要(PASS/FAIL 及详情)。

utils.print_html(json.dumps(list(TOP_DOMAINS)[:4], indent=2), title="Sample Trusted Domains")

utils.print_html("<h3>Research Results</h3>" + research_result, title="Research Results")

flag, report = evaluate_tavily_results(TOP_DOMAINS, research_result)
utils.print_html("<pre>" + report + "</pre>", title="<h3>Evaluation Summary</h3>")

亲自试一试!

现在轮到你了。 在这一部分,你可以直接对研究步骤及其评估进行实验:

  • 主题:选择一个不同的研究主题。
  • 优选域名:编辑或扩充 TOP_DOMAINS 列表。
  • 评估比例:调整 min_ratio(例如 0.4 表示至少 40% 的来源为优选来源)。

在修改之后重新运行下方单元格,看看评估结果会如何变化。

# === 5.1. Try it yourself: topic, ratio & preferred domains ===
# Edit these parameters before running the cell

topic = "recent developments in black hole science"   # <- Change the topic here
min_ratio = 0.4                                       # <- Change threshold (0.0–1.0)
run_reflection = True                                 # <- Set False to skip Step 4

# Short list of preferred domains (edit or expand as needed)
TOP_DOMAINS = {
    "wikipedia.org", "nature.com", "science.org", "arxiv.org",
    "nasa.gov", "mit.edu", "stanford.edu", "harvard.edu"
}

# Show a sample of preferred domains
import json
utils.print_html(
    json.dumps(sorted(list(TOP_DOMAINS)), indent=2),
    title="<h3>Sample Preferred Domains</h3>"
)

# 1) Research
research_task = f"Find 2–3 key papers and reliable overviews about {topic}."
research_output = find_references(research_task)
utils.print_html(research_output, title=f"<h3>Research Results on {topic}</h3>")

# 2) Evaluate sources (preferred domains ratio)
flag, eval_md = evaluate_tavily_results(TOP_DOMAINS, research_output, min_ratio=min_ratio)
utils.print_html("<pre>" + eval_md + "</pre>", title="<h3>Evaluation Summary</h3>")

5. 总结要点

  • 你刚刚看到了如何评估单个组件——find_references 研究步骤——的表现。
  • 你的组件级评估检查了检索到的 URL 是否属于一份预先定义的优选域名列表。
  • 这是一个客观评估的例子,具有清晰的针对单个样例的标准答案
  • 要构建一份评估集,你可以设计约 10 条覆盖不同主题(天文学、机器人学、金融等)的提示词,并为每个主题定义优选域名。
  • 检索到的来源中符合优选域名列表的比例,提供了一个有用的指标,用来指导改进方向,例如调整提示词或工具参数。
  • 与评估带有反思和重写过程的完整文章相比,这种方法更简单、成本更低,因为你只需专注于网络搜索这一个组件。
<div style="border:1px solid #22c55e; border-left:6px solid #16a34a; background:#dcfce7; border-radius:6px; padding:14px 16px; color:#064e3b; font-family:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif;">

🎉 恭喜!

你设计了一个组件级评估,让你的研究智能体变得更加可靠。 通过直接检查来源的质量,你引入了一道客观、可复现、且性价比高的安全防线。

这与 Andrew 讲座中强调的理念一致:组件级评估能让你在无需评估整个流水线的开销下,测试一个 AI 系统的单个部分。

</div>

学习地图

本页是「DeepLearningAI > Agentic AI Lab」的第 5 / 7 页——这是一份真实的 DeepLearning.AI 笔记本(代码 + 讲解文字),而非「Agentic AI」板块中那种模板化内容。顺序上接在「M3 智能体式人工智能 - 邮件助手工作流」之后。完成后可继续阅读「M5 智能体式人工智能 - 客服智能体」。代码单元格完全保留了源笔记本中的原样——请在你自己的 Python 环境中按顺序运行它们(它们依赖 utils.py 等本地辅助模块,这里并未包含)。

动手实践——分步指南

搭建好这份笔记本所需的本地依赖(代码单元格中导入的辅助模块,例如 utils.py、display_functions.py,以及文中引用的各个工具模块),然后按照「M4 智能体式人工智能 - 为研究工作流添加组件级评估」自身的分步讲解,从上到下依次运行每个代码单元格。在进入下一个实验之前,先尝试文中建议的实验(更换模型、修改提示词、提出你自己的请求)。

三大推荐资源

  1. 1
    Anthropic Engineering Blog

    Practical write-ups on building, evaluating, and operating agentic systems.

    https://www.anthropic.com/engineering

  2. 2
    DeepLearning.AI Course Catalog

    The DeepLearning.AI catalog these lab notebooks are drawn from.

    https://www.deeplearning.ai/courses/

链接由 AI 推荐——使用前建议快速核实。