Skip to content

入门教程(使用本地大语言模型)#

本教程将展示如何开始使用LlamaIndex构建智能代理。我们将从一个基础示例开始,然后演示如何添加RAG(检索增强生成)功能。

我们将使用BAAI/bge-base-en-v1.5作为嵌入模型,以及通过Ollama运行的llama3.1 8B模型。

Tip

请确保您已先完成安装步骤

环境设置#

Ollama是一个帮助您快速在本地搭建大语言模型的工具。

按照README说明学习如何安装。

下载Llama3模型只需执行ollama pull llama3.1

注意:您需要一台至少拥有约32GB内存的机器。

如我们的安装指南所述,llama-index实际上是一个软件包集合。要运行Ollama和Huggingface,我们需要安装这些集成组件:

pip install llama-index-llms-ollama llama-index-embeddings-huggingface

这些包名直接对应导入语句,非常便于记忆如何导入或安装它们!

from llama_index.llms.ollama import Ollama
from llama_index.embeddings.huggingface import HuggingFaceEmbedding

更多集成组件都列在https://llamahub.ai上。

基础代理示例#

让我们从一个简单示例开始,创建一个能通过调用工具进行基本乘法运算的代理。创建一个名为starter.py的文件:

import asyncio
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.llms.ollama import Ollama


# 定义一个简单的计算器工具
def multiply(a: float, b: float) -> float:
    """用于两个数字相乘"""
    return a * b


# 使用我们的计算器工具创建代理工作流
agent = FunctionAgent(
    tools=[multiply],
    llm=Ollama(
        model="llama3.1",
        request_timeout=360.0,
        # 手动设置上下文窗口以限制内存使用
        context_window=8000,
    ),
    system_prompt="你是一个能进行数字相乘的助手",
)


async def main():
    # 运行代理
    response = await agent.run("1234乘以4567等于多少?")
    print(str(response))


# 运行代理
if __name__ == "__main__":
    asyncio.run(main())

这将输出类似结果:1234乘以4567的结果是:5,618,916

整个过程是:

  • 代理收到问题:1234乘以4567等于多少?
  • 底层机制会将此问题及工具模式(名称、文档字符串和参数)传递给大语言模型
  • 代理选择了multiply工具并写入工具参数
  • 代理从工具接收结果并将其插入最终响应中

Tip

如您所见,我们使用了async异步函数。许多大语言模型和工具支持异步调用,使用异步代码能提升应用性能。要了解更多关于异步编程的知识,我们推荐阅读异步Python简明指南

添加聊天历史#

AgentWorkflow还能记住之前的对话记录,这些信息保存在AgentWorkflowContext中。

如果传入Context,代理将使用它来继续对话。

from llama_index.core.workflow import Context

# 创建上下文
ctx = Context(agent)

# 带上下文运行代理
response = await agent.run("我叫Logan", ctx=ctx)
response = await agent.run("我的名字是什么?", ctx=ctx)

添加RAG功能#

现在让我们增强代理能力,使其能够搜索文档。首先通过终端获取一些示例数据:

mkdir data
wget https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt -O data/paul_graham_essay.txt

现在您的目录结构应该如下:

├── starter.py
└── data
    └── paul_graham_essay.txt

现在我们可以使用LlamaIndex创建一个文档搜索工具。默认情况下,我们的VectorStoreIndex会使用OpenAI的text-embedding-ada-002模型来嵌入和检索文本。

修改后的starter.py应如下:

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llama_index.core.agent.workflow import AgentWorkflow
from llama_index.llms.ollama import Ollama
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
import asyncio
import os

# 设置控制全局默认值
Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-base-en-v1.5")
Settings.llm = Ollama(
    model="llama3.1",
    request_timeout=360.0,
    # 手动设置上下文窗口以限制内存使用
    context_window=8000,
)

# 使用LlamaIndex创建RAG工具
documents = SimpleDirectoryReader("data").load_data()
index = VectorStoreIndex.from_documents(
    documents,
    # 这里可以覆盖embed_model
    # embed_model=Settings.embed_model,
)
query_engine = index.as_query_engine(
    # 这里可以覆盖llm
    # llm=Settings.llm,
)


def multiply(a: float, b: float) -> float:
    """用于两个数字相乘"""
    return a * b


async def search_documents(query: str) -> str:
    """用于回答关于Paul Graham个人文章的自然语言问题"""
    response = await query_engine.aquery(query)
    return str(response)


# 创建包含两个工具的增强工作流
agent = AgentWorkflow.from_tools_or_functions(
    [multiply, search_documents],
    llm=Settings.llm,
    system_prompt="""你是一个能进行数学计算
    和搜索文档回答问题的助手""",
)


# 现在我们可以询问文档内容或进行计算
async def main():
    response = await agent.run(
        "作者在大学做了什么?另外,7乘以8等于多少?"
    )
    print(response)


# 运行代理
if __name__ == "__main__":
    asyncio.run(main())

现在代理可以无缝切换使用计算器和搜索文档来回答问题。

存储RAG索引#

为避免每次重新处理文档,您可以将索引持久化到磁盘:

# 保存索引
index.storage_context.persist("storage")

# 之后加载索引
from llama_index.core import StorageContext, load_index_from_storage

storage_context = StorageContext.from_defaults(persist_dir="storage")
index = load_index_from_storage(
    storage_context,
    # 这里可以覆盖embed_model
    # 必须使用与构建索引时相同的embed_model
    # embed_model=Settings.embed_model,
)
query_engine = index.as_query_engine(
    # 这里可以覆盖llm
    # llm=Settings.llm,
)

Tip

如果您使用了向量存储集成而非默认选项,通常可以直接从向量存储重新加载:

index = VectorStoreIndex.from_vector_store(
    vector_store,
    # 必须使用与构建索引时相同的embed_model
    # embed_model=Settings.embed_model,
)

下一步?#

这只是使用LlamaIndex代理的开始!您还可以:

  • 为代理添加更多工具
  • 使用不同的大语言模型
  • 通过系统提示自定义代理行为
  • 添加流式处理能力
  • 实现人机协作工作流
  • 使用多个代理协同完成任务

一些有用的后续链接: