基于 Chroma 与 Ollama 构建本地 RAG 应用
基于 Chroma 与 Ollama 构建本地 RAG 应用。通过本地部署 LLM 和 Embedding 模型,结合 LangChain 框架实现网页内容的向量化存储与检索增强生成。教程涵盖环境配置、数据分块、Prompt 优化及 Gradio 界面构建,提供完整的本地化知识库问答解决方案。重点介绍了参数调优、向量持久化及最佳实践,确保应用稳定高效运行。

基于 Chroma 与 Ollama 构建本地 RAG 应用。通过本地部署 LLM 和 Embedding 模型,结合 LangChain 框架实现网页内容的向量化存储与检索增强生成。教程涵盖环境配置、数据分块、Prompt 优化及 Gradio 界面构建,提供完整的本地化知识库问答解决方案。重点介绍了参数调优、向量持久化及最佳实践,确保应用稳定高效运行。

本文介绍如何利用 Ollama 在本地运行大语言模型(LLM),并结合 ChromaDB、LangChain 建立一个小型的基于网页内容的本地问答 RAG(Retrieval Augmented Generation)应用。
通过海量文本数据集(书籍、网站等)训练出来的具备通用语言理解和生成能力的模型。虽然它可以推理许多内容,但其知识仅限于特定时间点之前用于训练的数据。
一个用于开发由大型语言模型驱动的应用程序的框架。提供了丰富的接口、组件和能力,简化了构建 LLM 应用程序的过程。
一个免费的开源框架,可以让大模型很容易地运行在本地电脑上,支持多种模型的高效推理。
一种利用额外数据增强 LLM 知识的技术。它通过从外部数据库获取当前或相关上下文信息,并在请求 LLM 生成响应时呈现给它,从而解决了生成不正确或误导性信息的问题。
工作流程如下:

依据 Ollama 使用指南完成大模型的本地下载和运行。
# 下载 LLM 模型
ollama pull llama3
# 下载 Embedding 模型
ollama pull nomic-embed-text
安装 langchain、langchain-community、bs4 等库。
pip install langchain langchain-community bs4 gradio
from langchain_community.llms import Ollama
from langchain.callbacks.manager import CallbackManager
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
# 初始化 LLM,开启流式输出
llm = Ollama(
model="llama3",
temperature=0.1,
top_p=0.4,
callback_manager=CallbackManager([StreamingStdOutCallbackHandler()])
)
参数说明:
使用 BeautifulSoup 解析网页内容,并按标签提取所需部分。合理的分词设置会提高 RAG 的效果。
import bs4
from langchain_community.document_loaders import WebBaseLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
loader = WebBaseLoader(
web_paths=("https://vuejs.org/guide/introduction.html",),
bs_kwargs=dict(
parse_only=bs4.SoupStrainer(class_=("content",))
),
)
docs = loader.load()
# chunk_size: 分块大小
# chunk_overlap: 分块重叠部分,有助于降低将语句与其相关的重要上下文分开的可能性
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
将内容基于本地的词嵌入模型 nomic-embed-text 嵌入向量数据库中。
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import OllamaEmbeddings
vectorstore = Chroma.from_documents(
documents=splits,
embedding=OllamaEmbeddings(model="nomic-embed-text")
)
注意: 此处的嵌入模型也可以使用其他如 llama3、mistral,但在本地运行速度较慢。它们和 nomic-embed-text 一样不支持中文的词嵌入。如果想建立中文文档库,可以尝试 herald/dmeta-embedding-zh 模型。
ollama pull herald/dmeta-embedding-zh:latest
定义 Prompt 模板以规范 LLM 的输出格式,明确指示模型在不知道答案时如何回应。
from langchain_core.prompts import PromptTemplate
prompt = PromptTemplate(
input_variables=['context', 'question'],
template="""
You are an assistant for question-answering tasks.
Use the following pieces of retrieved context to answer the question.
If you don't know the answer, just say you don't know without any explanation.
Question: {question}
Context: {context}
Answer:
"""
)
基于 LangChain 实现检索问答功能。
from langchain.chains import RetrievalQA
retriever = vectorstore.as_retriever()
qa_chain = RetrievalQA.from_chain_type(
llm,
retriever=retriever,
chain_type_kwargs={"prompt": prompt}
)
# 测试问答
question = "what is vue?"
result = qa_chain.invoke({"query": question})
print(result["result"])
如果问的问题与文档无关,例如 what is react?,模型会根据 Prompt 设定回答 I don't know.。
使用 Gradio 库构建交互式机器学习界面。你只需要定义一个有输入和输出的函数,然后 Gradio 将自动为你生成一个界面。
import gradio as gr
from langchain_community.llms import Ollama
from langchain.callbacks.manager import CallbackManager
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
from langchain_community.document_loaders import WebBaseLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import OllamaEmbeddings
from langchain.chains import RetrievalQA
from langchain_core.prompts import PromptTemplate
def init_ollama_llm(model, temperature, top_p):
return Ollama(
model=model,
temperature=temperature,
top_p=top_p,
callback_manager=CallbackManager([StreamingStdOutCallbackHandler()])
)
def content_web(url):
loader = WebBaseLoader(web_paths=(url,))
docs = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
return splits
def chroma_retriever_store_content(splits):
vectorstore = Chroma.from_documents(
documents=splits,
embedding=OllamaEmbeddings(model="nomic-embed-text")
)
return vectorstore.as_retriever()
def rag_prompt():
return PromptTemplate(
input_variables=['context', 'question'],
template="""
You are an assistant for question-answering tasks.
Use the following pieces of retrieved context to answer the question.
If you don't know the answer, just say you don't know without any explanation.
Question: {question}
Context: {context}
Answer:
"""
)
def ollama_rag_chroma_web_content(web_url, question, temperature, top_p):
llm = init_ollama_llm('llama3', temperature, top_p)
splits = content_web(web_url)
retriever = chroma_retriever_store_content(splits)
qa_chain = RetrievalQA.from_chain_type(
llm,
retriever=retriever,
chain_type_kwargs={"prompt": rag_prompt()}
)
return qa_chain.invoke({"query": question})["result"]
demo = gr.Interface(
fn=ollama_rag_chroma_web_content,
inputs=[
gr.Textbox(label="web_url", value="https://vuejs.org/guide/introduction.html", info="爬取内容的网页地址"),
"text",
gr.Slider(0, 1, step=0.1, label="Temperature"),
gr.Slider(0, 1, step=0.1, label="Top P")
],
outputs="text",
title="Ollama+RAG Example",
description="输入网页的 URL,然后提问,获取答案"
)
demo.launch()
运行后会输出 Running on local URL: http://127.0.0.1:7860,打开浏览器即可查看交互效果。

chunk_size 和 chunk_overlap 对 RAG 效果影响显著。过小的分块可能导致上下文丢失,过大则可能引入噪声。建议根据文档结构(如段落、章节)动态调整,通常 500-1000 字符较为合适。
默认情况下,Chroma 存储在内存中。为了保持数据持久化,可以在初始化时指定 persist_directory。
vectorstore = Chroma.from_documents(
documents=splits,
embedding=OllamaEmbeddings(model="nomic-embed-text"),
persist_directory="./chroma_db"
)
除了纯文本检索,未来可扩展支持 PDF、Markdown 等多种文件格式加载。同时,结合关键词搜索(BM25)与向量搜索(Hybrid Search)通常能进一步提升检索准确率。
本教程演示了从零开始构建本地 RAG 应用的完整流程。通过本地部署 LLM 和 Embedding 模型,我们实现了数据的隐私保护与离线可用。结合 LangChain 的灵活编排能力和 Gradio 的快速 UI 构建,开发者可以高效验证想法并交付原型。后续可根据实际需求引入权限管理、缓存机制及更复杂的检索策略。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online