📘 **TELUS Agriculture & Consumer Goods** 如何通过 **Haystack Agents** 转变促销交易

教程:使用检索增强(Retrieval-Augmentation)创建您的第一个问答(QA)流水线


概述

本教程将向您展示如何使用 Haystack 的检索增强(RAG)方法创建生成式问答流水线。该过程涉及四个主要组件:SentenceTransformersTextEmbedder 用于创建用户查询的嵌入,InMemoryBM25Retriever 用于获取相关文档,PromptBuilder 用于创建模板提示,以及 OpenAIChatGenerator 用于生成响应。

在本教程中,您将使用《古代世界七大奇迹》的维基百科页面作为文档,但您可以将其替换为您想要的任何文本。

准备 Colab 环境

安装 Haystack

使用 pip 安装 Haystack 和其他必需的包

%%bash

pip install haystack-ai
pip install "datasets>=2.6.1"
pip install "sentence-transformers>=4.1.0"

获取并索引文档

您将通过下载数据并使用其嵌入将数据索引到 DocumentStore 来开始创建问答系统。

在本教程中,您将采用一种简单的方法来编写文档及其嵌入到 DocumentStore。有关包含预处理、清理和拆分的完整索引流水线,请参阅我们关于 预处理不同文件类型 的教程。

初始化 DocumentStore

初始化一个 DocumentStore 来索引您的文档。DocumentStore 存储了问答系统用于查找问题答案的文档。在本教程中,您将使用 InMemoryDocumentStore

from haystack.document_stores.in_memory import InMemoryDocumentStore

document_store = InMemoryDocumentStore()

InMemoryDocumentStore 是最容易入门的 DocumentStore。它不需要外部依赖,并且是小型项目和调试的不错选择。但它在大规模文档集合上的扩展性不太好,因此不适合生产系统。要了解 Haystack 支持的各种外部数据库,请参阅 DocumentStore 集成

DocumentStore 已准备就绪。现在是时候用一些文档填充它了。

获取数据

您将使用《古代世界七大奇迹》的维基百科页面作为文档。我们已经预处理了数据并将其上传到 Hugging Face Space:Seven Wonders。因此,您无需执行任何额外的清理或拆分。

获取数据并将其转换为 Haystack 文档

from datasets import load_dataset
from haystack import Document

dataset = load_dataset("bilgeyucel/seven-wonders", split="train")
docs = [Document(content=doc["content"], meta=doc["meta"]) for doc in dataset]

初始化文档嵌入器

要将数据及其嵌入存储在 DocumentStore 中,请使用模型名称初始化 SentenceTransformersDocumentEmbedder 并调用 warm_up() 来下载嵌入模型。

如果您愿意,可以使用不同的 Embedder 来处理您的文档。

from haystack.components.embedders import SentenceTransformersDocumentEmbedder

doc_embedder = SentenceTransformersDocumentEmbedder(model="sentence-transformers/all-MiniLM-L6-v2")
doc_embedder.warm_up()

将文档写入 DocumentStore

使用文档运行 doc_embedder。嵌入器将为每个文档创建嵌入,并将这些嵌入保存在 Document 对象的 embedding 字段中。然后,您可以使用 write_documents() 方法将文档写入 DocumentStore。

docs_with_embeddings = doc_embedder.run(docs)
document_store.write_documents(docs_with_embeddings["documents"])

构建 RAG 流水线

下一步是构建一个 Pipeline,以按照 RAG 方法为用户查询生成答案。要创建流水线,您首先需要初始化每个组件,将它们添加到流水线中,然后连接它们。

初始化文本嵌入器

初始化一个文本嵌入器,为用户查询创建嵌入。创建的嵌入稍后将由 Retriever 用于从 DocumentStore 中检索相关文档。

⚠️ 注意,您之前使用了 sentence-transformers/all-MiniLM-L6-v2 模型来为您的文档创建嵌入。这就是为什么您需要使用相同的模型来嵌入用户查询。

from haystack.components.embedders import SentenceTransformersTextEmbedder

text_embedder = SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2")

初始化检索器

初始化一个 InMemoryEmbeddingRetriever,并使其使用您在本教程早期初始化的 InMemoryDocumentStore。此检索器将获取与查询相关的文档。

from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever

retriever = InMemoryEmbeddingRetriever(document_store)

定义模板提示

使用 RAG 方法为生成式问答任务创建一个自定义提示。提示应接受两个参数:documents(从文档存储中检索到的)和来自用户的 question。使用 Jinja2 循环语法在提示中合并检索到的文档的内容。

接下来,使用您的提示模板初始化一个 PromptBuilder 实例。PromptBuilder 在获得必要的数值后,将自动填充变量值并生成完整的提示。这种方法可以提供更定制化和有效的问答体验。

from haystack.components.builders import ChatPromptBuilder
from haystack.dataclasses import ChatMessage

template = [
    ChatMessage.from_user(
        """
Given the following information, answer the question.

Context:
{% for document in documents %}
    {{ document.content }}
{% endfor %}

Question: {{question}}
Answer:
"""
    )
]

prompt_builder = ChatPromptBuilder(template=template)

初始化聊天生成器

ChatGenerators 是与大型语言模型(LLM)交互的组件。现在,设置 OPENAI_API_KEY 环境变量,并初始化一个可以与 OpenAI GPT 模型通信的 OpenAIChatGenerator。在初始化时,提供一个模型名称。

import os
from getpass import getpass
from haystack.components.generators.chat import OpenAIChatGenerator

if "OPENAI_API_KEY" not in os.environ:
    os.environ["OPENAI_API_KEY"] = getpass("Enter OpenAI API key:")
chat_generator = OpenAIChatGenerator(model="gpt-4o-mini")

您可以在流水线中将 OpenAIChatGenerator 替换为另一个 ChatGenerator。在此 查看聊天生成器的完整列表。

构建流水线

要构建流水线,请将所有组件添加到您的流水线中并将它们连接起来。从 text_embedder 的“embedding”输出到 retriever 的“query_embedding”输入创建连接,从 retrieverprompt_builder,以及从 prompt_builderllm。显式地将 retriever 的输出与 prompt_builder 的“documents”输入连接起来,使连接更清晰,因为 prompt_builder 有两个输入(“documents”和“question”)。

有关流水线和创建连接的更多信息,请参阅 创建流水线 文档。

from haystack import Pipeline

basic_rag_pipeline = Pipeline()
# Add components to your pipeline
basic_rag_pipeline.add_component("text_embedder", text_embedder)
basic_rag_pipeline.add_component("retriever", retriever)
basic_rag_pipeline.add_component("prompt_builder", prompt_builder)
basic_rag_pipeline.add_component("llm", chat_generator)
# Now, connect the components to each other
basic_rag_pipeline.connect("text_embedder.embedding", "retriever.query_embedding")
basic_rag_pipeline.connect("retriever", "prompt_builder")
basic_rag_pipeline.connect("prompt_builder.prompt", "llm.messages")

就这样!您的 RAG 流水线已准备好生成问题的答案!

提问

提问时,请使用流水线的 run() 方法。确保将问题同时提供给 text_embedderprompt_builder。这可以确保模板提示中的 {{question}} 变量被替换为您的特定问题。

question = "What does Rhodes Statue look like?"

response = basic_rag_pipeline.run({"text_embedder": {"text": question}, "prompt_builder": {"question": question}})

print(response["llm"]["replies"][0].text)

以下是一些其他示例问题供您测试

examples = [
    "Where is Gardens of Babylon?",
    "Why did people build Great Pyramid of Giza?",
    "What does Rhodes Statue look like?",
    "Why did people visit the Temple of Artemis?",
    "What is the importance of Colossus of Rhodes?",
    "What happened to the Tomb of Mausolus?",
    "How did Colossus of Rhodes collapse?",
]

下一步

🎉 恭喜!您已经学会了如何使用 RAG 方法为您的文档创建一个生成式 QA 系统。

如果您喜欢这个教程,您可能还会喜欢

要随时了解最新的 Haystack 开发进展,您可以 订阅我们的新闻通讯加入 Haystack Discord 社区

感谢阅读!