Ollama 本地知识库:用 ChromaDB 实现文档向量化与语义检索Ollama

1. 准备环境:安装 Ollama 与 ChromaDB

本地知识库的核心是 向量数据库 ,用于存储文档的语义向量。ChromaDB 轻量、易用,适合个人开发者。首先确保已安装 Ollama,并拉取一个嵌入模型(如 nomic-embed-text),该模型将文档转为向量。

复制代码
# 安装 ChromaDB
pip install chromadb

# 拉取嵌入模型
ollama pull nomic-embed-text

原因:嵌入模型负责将文本转化为数值向量,向量数据库根据向量相似度检索文档。没有向量化,语义搜索就无从谈起。

2. 加载文档并生成向量

假设你有一个 Markdown 文件 knowledge.md,内容为技术问答。首先读取文件,分割为段落(chunks),并利用 Ollama 生成每个段落的向量。

复制代码
import chromadb
from chromadb.utils import embedding_functions

# 初始化 ChromaDB 客户端
client = chromadb.PersistentClient(path='./kb_chroma')

# 使用 Ollama 嵌入函数
ollama_ef = embedding_functions.OllamaEmbeddingFunction(
    model_name="nomic-embed-text",
    url="http://localhost:11434/api/embeddings"
)

# 创建或获取集合
collection = client.get_or_create_collection(
    name="my_kb",
    embedding_function=ollama_ef
)

# 加载文档并添加
with open('knowledge.md', 'r') as f:
    text = f.read()

# 简单分段(每段200字符)
chunks = [text[i:i+200] for i in range(0, len(text), 200)]
ids = [f"chunk_{i}" for i in range(len(chunks))]

collection.add(
    documents=chunks,
    ids=ids
)
print(f"已添加 {len(chunks)} 个文档块")

原因 :OllamaEmbeddingFunction 封装了调用 Ollama API 的逻辑,避免了手动构造请求。分段是为了让每个向量对应一个语义连贯的片段,提升检索精度。

3. 实现语义检索

当用户提问时,将问题向量化后在 ChromaDB 中搜索最相似的文档块。以下示例查询"如何配置 Ollama 模型?"。

复制代码
query = "如何配置 Ollama 模型?"

# 执行查询(返回前3个结果)
results = collection.query(
    query_texts=[query],
    n_results=3
)

print("检索结果:")
for doc, dist in zip(results['documents'][0], results['distances'][0]):
    print(f"距离 {dist:.4f}: {doc[:50]}...")

原因 :ChromaDB 会自动调用 OllamaEmbeddingFunction 对查询文本进行向量化,然后计算余弦距离。距离越小,语义越相似。

4. 最佳实践清单

  1. 选择合适的嵌入模型 :nomic-embed-text 适合通用场景,若涉及代码,可选用 mistral 或 llama3 的嵌入版本。
    原因:不同嵌入模型对领域语义的理解能力不同。
  2. 合理分段文档 :推荐 200-500 字符一段,段与段之间保留上下文重叠。
    示例 :使用 RecursiveCharacterTextSplitter 实现智能分割。
  3. 持久化存储 :使用 PersistentClient 而非临时内存,避免每次重启重新构建知识库。
    原因:ChromaDB 会将向量数据写入磁盘,重启后自动加载。
  4. 元数据过滤 :为每个文档块添加元数据(如来源文件、章节),在查询时可按条件过滤。
    示例 :collection.add(documents=..., ids=..., metadatas=[{"source": "knowledge.md"}])。
  5. 调整返回数量 :根据场景设置 n_results,一般 3-5 个足够,避免信息过载。

5. 集成到 Ollama 对话

将检索到的文档块作为上下文,结合用户问题发送给 Ollama 模型生成回答,实现 RAG(检索增强生成)。

复制代码
import requests

# 取检索结果的前 1000 字作为上下文
context = "\n".join(results['documents'][0])[:1000]
prompt = f"基于以下知识回答:\n{context}\n\n问题:{query}"

response = requests.post("http://localhost:11434/api/generate",
    json={"model": "llama3.2", "prompt": prompt, "stream": False})

print(response.json()['response'])

原因:仅靠大模型自身知识可能过时或缺失,本地知识库提供最新、私有的信息,大幅提升回答准确度。

通过以上步骤,你已成功搭建本地知识库,并实现语义检索与 RAG 对话。后续可以扩展为支持 PDF、Word 等多格式文档,或集成到前端聊天界面。

相关推荐
SuperHeroWu75 天前
TraeCode 国内版接入 DevEco CLI:用官方知识开发鸿蒙应用
ai编程·harmonyos·知识库·trae·aicoding·skills·deveco cli
独码侠11 天前
Dify 知识库 RAG 实战:把 100 页手册变成会回答的 AI
人工智能·向量·知识库·dify·rag
ZGi.ai11 天前
企业内网部署 Agent,先检查什么?
知识库·工作流·aiagent·人工确认·zgi·agentruntime·企业内网部署
ZGi.ai13 天前
AI Agent 和 Chatbot 有什么区别?
人工智能·知识库·工作流·chatbot·ai agent·智能体·agent workflow
啦啦啦!20 天前
RAG初阶学习
学习·ai·知识库·rag
ZGi.ai20 天前
开源 AI Agent Runtime:制度版本问答
知识库·版本管理·ai智能体·zgi·agentruntime·制度问答
Code_流苏20 天前
AI 知识库和数据库有什么区别?从“查订单”到“问规则”讲清楚
数据库·ai·agent·知识库
寻道码路20 天前
大模型工程化实战(十二):RAG 数据工程底座——采集到入库流水线(离线+在线双链路)
大模型·知识库·rag·ai工程化·llmops`·数据工程底座·文档采集