检索增强生成 (RAG)

RAG 使您的应用程序能够引用和回忆来自先前交互或外部文档的信息。

Llama Stack 将实现 RAG 的 API 分为三个层次

  1. 最底层的 API 处理原始存储和检索。这些包括 Vector IO、KeyValue IO(即将推出)和 Relational IO(也即将推出)。

  2. 接下来是“Rag Tool”,它是 Tools API 的一个一等工具,允许您以各种分块策略摄取文档(来自 URL、文件等)并智能地查询它们。

  3. 最后,这一切都通过顶层的 “Agents” API 汇集在一起,该 API 允许您创建能够使用这些工具回答问题、执行任务等。

RAG System

RAG 系统使用较低层存储不同类型的数据

  • Vector IO: 用于语义搜索和检索

  • Key-Value and Relational IO: 用于结构化数据存储

未来我们可能会添加更多存储类型,例如 Graph IO。

设置向量数据库

本指南将使用 Ollama 作为推理提供者。Ollama 是一个 LLM 运行时,允许您在本地运行 Llama 模型。

以下是如何设置向量数据库以用于 RAG

# Create http client
import os
from llama_stack_client import LlamaStackClient

client = LlamaStackClient(base_url=f"http://localhost:{os.environ['LLAMA_STACK_PORT']}")


# Register a vector db
vector_db_id = "my_documents"
response = client.vector_dbs.register(
    vector_db_id=vector_db_id,
    embedding_model="all-MiniLM-L6-v2",
    embedding_dimension=384,
    provider_id="faiss",
)

文档摄取

您可以通过两种方法将文档摄取到向量数据库中:直接插入预分块文档或使用 RAG 工具。

# You can insert a pre-chunked document directly into the vector db
chunks = [
    {
        "content": "Your document text here",
        "mime_type": "text/plain",
        "metadata": {
            "document_id": "doc1",
            "author": "Jane Doe",
        },
    },
]
client.vector_io.insert(vector_db_id=vector_db_id, chunks=chunks)

检索

您可以查询向量数据库以根据其嵌入向量检索文档。

# You can then query for these chunks
chunks_response = client.vector_io.query(
    vector_db_id=vector_db_id, query="What do you know about..."
)

使用 RAG 工具

摄取文档的更好方法是使用 RAG 工具。该工具允许您摄取来自 URL、文件等的文档,并自动将其分块。有关如何格式化 RAGDocument 的更多示例可在附录中找到。

from llama_stack_client import RAGDocument

urls = ["memory_optimizations.rst", "chat.rst", "llama3.rst"]
documents = [
    RAGDocument(
        document_id=f"num-{i}",
        content=f"https://raw.githubusercontent.com/pytorch/torchtune/main/docs/source/tutorials/{url}",
        mime_type="text/plain",
        metadata={},
    )
    for i, url in enumerate(urls)
]

client.tool_runtime.rag_tool.insert(
    documents=documents,
    vector_db_id=vector_db_id,
    chunk_size_in_tokens=512,
)

# Query documents
results = client.tool_runtime.rag_tool.query(
    vector_db_ids=[vector_db_id],
    content="What do you know about...",
)

如果您认为对您的应用程序有用,可以配置 RAG 工具如何将元数据添加到上下文中。只需添加

# Query documents
results = client.tool_runtime.rag_tool.query(
    vector_db_ids=[vector_db_id],
    content="What do you know about...",
    query_config={
        "chunk_template": "Result {index}\nContent: {chunk.content}\nMetadata: {metadata}\n",
    },
)

构建 RAG 增强型代理

最强大的模式之一是将代理与 RAG 能力结合起来。这是一个完整的示例

from llama_stack_client import Agent

# Create agent with memory
agent = Agent(
    client,
    model="meta-llama/Llama-3.3-70B-Instruct",
    instructions="You are a helpful assistant",
    tools=[
        {
            "name": "builtin::rag/knowledge_search",
            "args": {
                "vector_db_ids": [vector_db_id],
                # Defaults
                "query_config": {
                    "chunk_size_in_tokens": 512,
                    "chunk_overlap_in_tokens": 0,
                    "chunk_template": "Result {index}\nContent: {chunk.content}\nMetadata: {metadata}\n",
                },
            },
        }
    ],
)
session_id = agent.create_session("rag_session")


# Ask questions about documents in the vector db, and the agent will query the db to answer the question.
response = agent.create_turn(
    messages=[{"role": "user", "content": "How to optimize memory in PyTorch?"}],
    session_id=session_id,
)

注意:AgentConfig 中的 instructions 字段可用于指导代理的行为。尝试使用不同的指令来找出最适合您的用例的方法非常重要。

您也可以在用户消息中附带文档,并询问有关这些文档的问题。

# Initial document ingestion
response = agent.create_turn(
    messages=[
        {"role": "user", "content": "I am providing some documents for reference."}
    ],
    documents=[
        {
            "content": "https://raw.githubusercontent.com/pytorch/torchtune/main/docs/source/tutorials/memory_optimizations.rst",
            "mime_type": "text/plain",
        }
    ],
    session_id=session_id,
)

# Query with RAG
response = agent.create_turn(
    messages=[{"role": "user", "content": "What are the key topics in the documents?"}],
    session_id=session_id,
)

您可以使用以下方法打印响应。

from llama_stack_client import AgentEventLogger

for log in AgentEventLogger().log(response):
    log.print()

取消注册向量数据库

如果您需要清理并取消注册向量数据库,可以按如下方式进行操作

# Unregister a specified vector database
vector_db_id = "my_vector_db_id"
print(f"Unregistering vector database: {vector_db_id}")
client.vector_dbs.unregister(vector_db_id=vector_db_id)


# Unregister all vector databases
for vector_db_id in client.vector_dbs.list():
    print(f"Unregistering vector database: {vector_db_id.identifier}")
    client.vector_dbs.unregister(vector_db_id=vector_db_id.identifier)

附录

更多 RAGDocument 示例

from llama_stack_client import RAGDocument
import base64

RAGDocument(document_id="num-0", content={"uri": "file://path/to/file"})
RAGDocument(document_id="num-1", content="plain text")
RAGDocument(
    document_id="num-2",
    content={
        "type": "text",
        "text": "plain text input",
    },  # for inputs that should be treated as text explicitly
)
RAGDocument(
    document_id="num-3",
    content={
        "type": "image",
        "image": {"url": {"uri": "https://mywebsite.com/image.jpg"}},
    },
)
B64_ENCODED_IMAGE = base64.b64encode(
    requests.get(
        "https://raw.githubusercontent.com/meta-llama/llama-stack/refs/heads/main/docs/_static/llama-stack.png"
    ).content
)
RAGDocuemnt(
    document_id="num-4",
    content={"type": "image", "image": {"data": B64_ENCODED_IMAGE}},
)

如需更强的类型交互,请使用 此处 的类型化字典。