#
创建宾客信息检索生成（RAG）工具

您信赖的智能体 Alfred 正在筹备本世纪最盛大的晚会。为确保活动顺利进行，Alfred 需要快速获取最新宾客信息。让我们通过定制化的检索增强生成（RAG）工具（基于专属数据集）为 Alfred 赋能。

##
为何选择 RAG 技术？

试想 Alfred 在宾客间穿梭时需即时调取详细信息，传统大语言模型（LLM）可能面临以下挑战：

1. 宾客名单属于特定活动数据，不在模型训练范围内
2. 宾客信息可能频繁变更或更新
3. 需精确检索电子邮件地址等细节信息

这正是检索增强生成（RAG）技术的优势所在！通过结合检索系统与 LLM，Alfred 可按需获取准确、实时的宾客信息。

> 您可以选择课程涵盖的任何框架实现本用例，请通过代码标签页选择偏好方案。

##
应用搭建

我们将以 Hugging Face Space 为开发环境，采用结构化 Python 项目构建智能体。这种架构通过功能模块化实现代码整洁，更贴近实际部署场景。

###
项目结构

- `tools.py` – 为智能体提供辅助工具
- `retriever.py` – 实现支持知识访问的检索功能
- `app.py` – 整合所有组件形成完整功能智能体（将在本单元最后完成）

实操参考：Hugging Face Space 示例，该空间已部署本单元开发的智能体增强 RAG 系统，欢迎克隆体验！

可直接测试下方智能体：

##
数据集概览

数据集 `agents-course/unit3-invitees` 包含以下字段：

- Name: 宾客全名
- Relation: 与主办方关系
- Description: 简要传记或趣闻
- Email Address: 邀请函发送及跟进联系方式

数据集预览：

> 实际场景可扩展数据集字段，包含饮食偏好、礼品兴趣、禁忌话题等对主持人有用的详细信息。

##
构建宾客信息工具

我们将创建 Alfred 在晚会期间快速检索宾客信息的定制工具，分三步实现：

1. 加载并预处理数据集
2. 创建检索工具
3. 工具与 Alfred 集成

###
步骤一：加载并预处理数据集

首先将原始宾客数据转换为适合检索的格式：

smolagents
llama-index
langgraph

    import datasets
    from langchain_core.documents import Document

    # 加载数据集
    guest_dataset = datasets.load_dataset("agents-course/unit3-invitees", split="train")

    # 转换为 Document 对象
    docs = [
        Document(
            page_content="\n".join([
                f"Name: {guest['name']}",
                f"Relation: {guest['relation']}",
                f"Description: {guest['description']}",
                f"Email: {guest['email']}"
            ]),
            metadata={"name": guest["name"]}
        )
        for guest in guest_dataset
    ]

在上面的代码中，我们：

- 加载数据集
- 将每条房客记录转换为包含格式化内容的 “Document” 对象
- 将 “Document” 对象存储在列表中

这意味着我们已经准备好所有数据，可以开始配置检索功能了。

###
步骤 2：创建检索工具

现在，让我们创建一个自定义工具，Alfred 可以使用它来搜索房客信息。

smolagents
llama-index
langgraph

我们将使用“langchain_community.retrievers”模块中的“BM25Retriever”来创建一个检索工具。

> `BM25Retriever` 是检索的一个很好的起点，但对于更高级的语义搜索，您可以考虑使用基于嵌入的检索器，例如来自 sentence-transformers 的检索器。

    from smolagents import Tool
    from langchain_community.retrievers import BM25Retriever

    class GuestInfoRetrieverTool(Tool):
        name = "guest_info_retriever"
        description = "Retrieves detailed information about gala guests based on their name or relation."
        inputs = {
            "query": {
                "type": "string",
                "description": "The name or relation of the guest you want information about."
            }
        }
        output_type = "string"

        def __init__(self, docs):
            self.is_initialized = False
            self.retriever = BM25Retriever.from_documents(docs)

        def forward(self, query: str):
            results = self.retriever.get_relevant_documents(query)
            if results:
                return "\n\n".join([doc.page_content for doc in results[:3]])
            else:
                return "No matching guest information found."

    # 初始化工具
    guest_info_tool = GuestInfoRetrieverTool(docs)

让我们逐步了解这个工具：

- `name` 和 `description` 帮助智能体了解何时以及如何使用此工具
- `inputs` 定义工具所需的参数（在本例中为搜索查询）
- 我们使用 `BM25Retriever`，这是一种强大的文本检索算法，不需要嵌入
- `forward` 方法处理查询并返回最相关的客人信息

###
步骤 3：将工具与 Alfred 集成

最后，让我们创建智能体并为其配备自定义工具，将所有内容整合在一起：

smolagents
llama-index
langgraph

    from smolagents import CodeAgent, InferenceClientModel

    # 初始化 Hugging Face 模型
    model = InferenceClientModel()

    # 使用宾客信息工具创建我们的晚会智能体 Alfred
    alfred = CodeAgent(tools=[guest_info_tool], model=model)

    # Example query Alfred might receive during the gala
    response = alfred.run("Tell me about our guest named 'Lady Ada Lovelace'.")

    print("🎩 Alfred's Response:")
    print(response)

预期输出：

    🎩 Alfred's Response:
    根据我检索到的信息，艾达·洛夫莱斯夫人是一位受人尊敬的数学家和朋友。她因其在数学和计算机领域的开创性工作而闻名，并因其在查尔斯·巴贝奇的分析机方面的贡献而被誉为第一位计算机程序员。她的电子邮件地址是 ada.lovelace@example.com。

这最后一步具体做了什么：

- 我们使用 `InferenceClientModel` 类初始化 Hugging Face 模型
- 我们将智能体 (Alfred) 创建为 `CodeAgent`，它可以执行 Python 代码来解决问题
- 我们让 Alfred 检索一位名叫“Lady Ada Lovelace”的客人的信息

##
互动示例

在晚会上，对话可能像这样进行：

你：“Alfred，那位正在和大使说话的先生是谁？”

Alfred 快速搜索嘉宾数据库 “先生，那是尼古拉·特斯拉博士。他是你大学时代的老朋友。他最近申请了一种新的无线能量传输系统的专利，很乐意和你讨论一下。不过别忘了，他对鸽子很感兴趣，所以这或许会成为一次很好的闲聊。”

    {
        "name": "Dr. Nikola Tesla",
        "relation": "old friend from university days",
        "description": "Dr. Nikola Tesla is an old friend from your university days. He's recently patented a new wireless energy transmission system and would be delighted to discuss it with you. Just remember he's passionate about pigeons, so that might make for good small talk.",
        "email": "nikola.tesla@gmail.com"
    }

##
更进一步

既然 Alfred 可以检索宾客信息，不妨考虑如何增强这个系统：

1. 改进检索器，使用更复杂的算法，例如 sentence-transformers
2. 实现对话记忆，让 Alfred 记住之前的互动
3. 结合网页搜索，获取陌生宾客的最新信息
4. 整合多个索引，从经过验证的来源获取更完整的信息

现在，Alfred 已经完全有能力轻松处理宾客的咨询，确保您的晚会成为本世纪最精致、最令人愉悦的盛事！

<提示> 尝试扩展检索工具，使其能够根据每位宾客的兴趣或背景返回对话开场白。您将如何修改该工具来实现这一点？

完成后，在 `retriever.py` 文件中实现您的宾客检索工具。 </提示>

Update on GitHub