预算<5000元,3人团队如何用开源LLM+Agent搭建企业知识库?完整部署实录
以一家3人技术团队为案例,记录从需求分析、模型选型、RAG搭建、Agent编排到生产部署的全流程,包含踩坑清单和真实成本核算。
AinoCode 编辑部
引子:5000块预算,能做出什么样的企业知识库?
上个月,一个做跨境电商的朋友找到我。他们公司 12 个人,每天要处理大量的产品咨询、售后问题、平台规则查询。客服团队 3 个人,每天花 6 个小时在重复性问题上。
他的需求很明确:
- 把公司所有的产品文档、FAQ、平台规则、历史工单整理成一个知识库
- 员工提问,AI 自动回答,回答不了再转人工
- 预算 5000 元以内,运维成本要低,最好一个人就能维护
我花了一周时间,从选型到部署到压测,跑完全流程。今天把完整的部署实录、踩坑清单和成本明细都写出来。
一、需求拆解与技术选型
需求优先级
| 优先级 | 需求 | 为什么 |
|---|---|---|
| P0 | 回答准确率 > 85% | 客服场景,答错了比不答更糟 |
| P0 | 响应时间 < 3 秒 | 员工不能等太久,否则就直接问人了 |
| P1 | 支持多轮对话 | 很多追问场景,“那这个产品有库存吗?“ |
| P1 | 数据来源可追溯 | 每次回答要给出引用来源 |
| P2 | 支持文档自动更新 | 产品文档每周更新 |
| P2 | 成本可控 | 预算有限 |
技术选型决策树
第一步:选模型
预算 5000 元,月 API 预算最多 200-300 元。如果走云端 API,按 GPT-4 的价格,一个月大概能撑 2000 次调用——对于一个 12 人公司来说完全不够。
所以结论很明确:必须本地部署开源模型。
在开源模型里,我们对比了以下几个候选:
| 模型 | 参数量 | 最低硬件要求 | 中文能力 | 推荐理由 |
|---|---|---|---|---|
| Qwen2.5-7B | 7B | 8GB VRAM | ★★★★★ | 中文最强,工具调用好 |
| Qwen2.5-14B | 14B | 16GB VRAM | ★★★★★ | 推理能力更强 |
| Llama-3.1-8B | 8B | 8GB VRAM | ★★★☆☆ | 英文强,中文一般 |
| Mistral-7B | 7B | 8GB VRAM | ★★★☆☆ | 轻量,但中文弱 |
| DeepSeek-R1-Distill-7B | 7B | 8GB VRAM | ★★★★☆ | 推理强,但回复风格不稳定 |
最终选择:Qwen2.5-7B-Instruct。理由很简单——中文场景下,7B 级别里它几乎没有对手,而且工具调用(function calling)支持最好,后续如果需要扩展 Agent 能力,这条路是通的。
第二步:选推理引擎
候选有三个:Ollama、vLLM、llama.cpp。
| 引擎 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| Ollama | 一键部署,API 兼容 OpenAI | 并发能力弱,单实例 | 开发/小团队 |
| vLLM | 高并发,PagedAttention | 部署稍复杂 | 生产环境 |
| llama.cpp | CPU 可跑,极低内存 | 速度慢 | 极低配环境 |
最终选择:Ollama 用于开发和轻量部署。理由:3 人团队不需要 vLLM 级别的高并发,Ollama 的安装和运维成本最低,一个人就能搞定。
第三步:选 RAG 框架
候选:LangChain、LlamaIndex、Haystack。
我们选了 LlamaIndex。原因:
- LangChain 太重了,学完它的概念就要花一天
- LlamaIndex 的文档索引和检索 API 设计得更直接,
SimpleDirectoryReader→VectorStoreIndex→query()三步搞定 - 对中文文档的解析支持更好(PDF、Word 解析)
第四步:选向量数据库
候选:Chroma、Qdrant、Milvus Lite。
选了 Chroma。理由:
- 嵌入部署,不需要额外起服务
- 对于这个规模的文档量(预计 5000-10000 条 chunk),Chroma 完全够用
- 如果需要扩展,迁移到 Qdrant 或 Milvus 的成本很低
二、硬件选型与成本核算
方案对比
| 方案 | 硬件 | 价格 | 适用场景 |
|---|---|---|---|
| 云服务器 GPU | NVIDIA T4 (16GB) | 阿里云约 2.5 元/小时 ≈ 1800 元/月 | ❌ 超预算 |
| 云服务器 CPU | 32C 64G (CPU 推理) | 约 800 元/月 | ⚠️ 可以,但速度慢 |
| 本地 Mini PC | 4090 笔记本 / RTX 4060 台式机 | 一次性 4000-5000 元 | ✅ 最优解 |
| 本地 Mini PC (低配) | RTX 4060 8GB | 一次性 3500 元 | ✅ 够用 |
最终选择了 RTX 4060 8GB 的 Mini PC(机械革命无界 14X,约 3800 元)。为什么是 Mini PC 而不是云服务器?
算一笔账:
| 项目 | 云服务器方案(月) | Mini PC 方案(一次性) |
|---|---|---|
| GPU 计算 | 1800 元/月 | 3800 元(一次性) |
| 带宽 | 200 元/月 | 50 元/月(家庭宽带) |
| 存储 | 100 元/月 | 500 元(SSD 2TB) |
| 6 个月总成本 | 12,600 元 | 4,350 元 |
6 个月回本,之后每月只需 50 元电费。
硬件配置清单
| 项目 | 型号 | 价格 |
|---|---|---|
| Mini PC | 机械革命无界 14X(RTX 4060 8GB,32GB 内存,1TB SSD) | 3,800 元 |
| 额外 SSD | 致态 TiPlus7100 2TB | 500 元 |
| 合计 | 4,300 元 |
剩余 700 元作为备用金。
三、部署全流程
第一步:系统环境准备
# Ubuntu 22.04 LTS
sudo apt update && sudo apt upgrade -y
# 安装 NVIDIA 驱动
sudo ubuntu-drivers autoinstall
sudo reboot
# 验证 GPU
nvidia-smi
# 输出应该显示 RTX 4060 和 CUDA 版本
# 安装 Docker(可选,用于隔离服务)
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
第二步:部署 Ollama + Qwen2.5-7B
# 安装 Ollama
curl -fsSL https://ollama.com/install.sh | sh
# 拉取模型
ollama pull qwen2.5:7b-instruct
# 验证
ollama run qwen2.5:7b-instruct "用一句话解释什么是 RAG"
# 正常输出即可
# 设置开机自启
sudo systemctl enable ollama
关键配置:Ollama 默认监听 127.0.0.1:11434,如果需要从其他机器访问,需要修改 systemd 配置:
sudo systemctl edit ollama
# 添加:
[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"
sudo systemctl restart ollama
第三步:搭建 RAG Pipeline
# requirements.txt
llama-index
llama-index-embeddings-huggingface
llama-index-llms-ollama
llama-index-vector-stores-chroma
chromadb
openai # 仅用于 API 兼容
# rag_pipeline.py
import os
from llama_index.core import (
Settings,
VectorStoreIndex,
SimpleDirectoryReader,
StorageContext,
)
from llama_index.llms.ollama import Ollama
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.vector_stores.chroma import ChromaVectorStore
import chromadb
# === 配置 ===
# 使用本地 embedding 模型,不需要额外 API
Settings.embed_model = HuggingFaceEmbedding(
model_name="BAAI/bge-small-zh-v1.5", # 中文优化
device="cpu" # embedding 模型小,CPU 够用
)
# LLM 通过 Ollama 本地调用
Settings.llm = Ollama(
model="qwen2.5:7b-instruct",
base_url="http://localhost:11434",
request_timeout=120.0,
)
# === 文档索引 ===
def build_index(docs_dir: str, persist_dir: str = "./chroma_db"):
"""构建文档索引"""
# 读取文档
documents = SimpleDirectoryReader(docs_dir).load_data()
print(f"加载了 {len(documents)} 个文档")
# 创建 Chroma 向量存储
chroma_client = chromadb.PersistentClient(path=persist_dir)
chroma_collection = chroma_client.get_or_create_collection("knowledge_base")
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
# 构建索引
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(
documents,
storage_context=storage_context,
chunk_size=512, # 中文场景建议 512-1024
chunk_overlap=50, # 保留上下文重叠
)
index.storage_context.persist(persist_dir=persist_dir)
print(f"索引已保存到 {persist_dir}")
return index
# === 查询 ===
def query_knowledge(question: str, persist_dir: str = "./chroma_db"):
"""查询知识库"""
chroma_client = chromadb.PersistentClient(path=persist_dir)
chroma_collection = chroma_client.get_collection("knowledge_base")
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
index = VectorStoreIndex.from_vector_store(vector_store)
query_engine = index.as_query_engine(
similarity_top_k=3, # 检索 3 个最相关 chunk
response_mode="compact",
)
response = query_engine.query(question)
return {
"answer": str(response),
"sources": [
{"text": node.text[:200], "score": node.score}
for node in response.source_nodes
]
}
# === 使用示例 ===
if __name__ == "__main__":
# 首次运行:构建索引
# build_index("./docs")
# 后续运行:直接查询
result = query_knowledge("退换货流程是什么?")
print(f"回答: {result['answer']}")
print(f"\n引用来源:")
for src in result['sources']:
print(f" [{src['score']:.3f}] {src['text']}...")
第四步:Agent 编排(进阶)
如果需要在知识库回答基础上,增加工具调用能力(比如查库存、查订单),可以用 Hermes Agent 或 LangGraph 做一层 Agent 编排:
# agent_with_tools.py
from openai import OpenAI
# Ollama 的 API 兼容 OpenAI 接口
client = OpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama", # 随便填
)
# 定义工具
tools = [
{
"type": "function",
"function": {
"name": "query_knowledge_base",
"description": "查询企业知识库",
"parameters": {
"type": "object",
"properties": {
"question": {
"type": "string",
"description": "用户的问题"
}
},
"required": ["question"]
}
}
},
{
"type": "function",
"function": {
"name": "check_inventory",
"description": "查询产品库存",
"parameters": {
"type": "object",
"properties": {
"product_name": {
"type": "string",
"description": "产品名称"
}
},
"required": ["product_name"]
}
}
},
]
def agent_dispatch(user_input: str):
"""Agent 路由:判断调用知识库还是业务 API"""
response = client.chat.completions.create(
model="qwen2.5:7b-instruct",
messages=[{"role": "user", "content": user_input}],
tools=tools,
tool_choice="auto",
)
# 解析工具调用
if response.choices[0].message.tool_calls:
tool_call = response.choices[0].message.tool_calls[0]
tool_name = tool_call.function.name
if tool_name == "query_knowledge_base":
import json
args = json.loads(tool_call.function.arguments)
return query_knowledge_base(args["question"])
elif tool_name == "check_inventory":
import json
args = json.loads(tool_call.function.arguments)
return check_inventory_api(args["product_name"])
else:
# 直接回复
return response.choices[0].message.content
第五步:前端 Web 界面
最简单的方案是用 Gradio 快速搭建一个 Web UI:
# web_ui.py
import gradio as gr
from rag_pipeline import query_knowledge
def chat_with_knowledge(message, history):
result = query_knowledge(message)
# 构建带引用来源的回复
answer = result["answer"]
sources = result["sources"]
# 添加引用
if sources:
answer += "\n\n---\n**引用来源:**\n"
for i, src in enumerate(sources, 1):
answer += f"{i}. [{src['score']:.3f}] {src['text'][:150]}...\n"
return answer
demo = gr.ChatInterface(
fn=chat_with_knowledge,
title="企业知识库助手",
description="基于 Qwen2.5 + RAG 构建的企业知识库",
)
demo.launch(server_name="0.0.0.0", server_port=7860)
启动后访问 http://<你的IP>:7860 即可使用。
四、踩坑清单
坑 1:中文 embedding 模型选择
问题:一开始用了默认的 all-MiniLM-L6-v2,检索出来的结果完全不相关。
原因:这个模型是英文优化的,中文语义理解很差。
解决:换成 BAAI/bge-small-zh-v1.5(智源中文优化 embedding),检索质量提升了 60% 以上。
坑 2:chunk_size 设置
问题:chunk_size 设为 1024 时,检索到的内容太泛,回答不精准;设为 128 时,上下文太碎,丢失关键信息。
解决:对于中文技术文档,512 chunk_size + 50 overlap 是甜点。产品文档和 FAQ 可以用 256,因为每段本身就不长。
坑 3:PDF 解析乱码
问题:客户提供的产品手册是 PDF,SimpleDirectoryReader 解析出来全是乱码。
原因:PDF 是扫描件或使用了特殊字体。
解决:
- 方案 A(推荐):让客户提供 Word/Markdown 版本
- 方案 B:用
pdfplumber替代默认解析器 - 方案 C:扫描件用 OCR(PaddleOCR),但成本高
from llama_index.readers.file import PDFReader
# pdfplumber 版本
reader = PDFReader()
documents = reader.load_data(file_path="manual.pdf")
坑 4:Ollama 并发限制
问题:3 个人同时提问时,偶尔出现 timeout。
原因:Ollama 默认 num_ctx 是 4096,7B 模型在 8GB 显存下,单次推理约 2-3 秒。3 个并发就需要排队。
解决:
- 设置
OLLAMA_NUM_PARALLEL=2允许 2 个并发请求 - 如果超过 2 人同时使用,建议升级到 14B 模型 + 16GB 显存
- 或者用 vLLM 替换 Ollama(支持 continuous batching)
坑 5:索引更新
问题:文档更新后,旧索引不会自动刷新。
解决:写一个 cron job 每天凌晨重建索引:
# crontab -e
0 2 * * * cd /opt/knowledge-base && python rebuild_index.py >> /var/log/kb-rebuild.log 2>&1
# rebuild_index.py
import shutil
from rag_pipeline import build_index
# 备份旧索引
shutil.move("./chroma_db", "./chroma_db_backup")
# 重建
try:
build_index("./docs", "./chroma_db")
except Exception as e:
# 失败时恢复旧索引
shutil.move("./chroma_db_backup", "./chroma_db")
raise e
五、性能数据
响应时间(本地 RTX 4060)
| 环节 | 耗时 | 备注 |
|---|---|---|
| Embedding 检索 | 50-100ms | CPU,bge-small-zh |
| LLM 推理 | 1500-2500ms | Qwen2.5-7B,首 token 约 500ms |
| 端到端 | 2-3 秒 | 包含网络传输 |
准确率测试
我们用 50 个真实客服问题做了测试:
| 指标 | 结果 | 备注 |
|---|---|---|
| Top-3 检索命中率 | 92% | 正确答案在前 3 个 chunk 里 |
| 回答准确率 | 86% | 人工标注判断 |
| 幻觉率 | 8% | 编造不存在的信息 |
| 拒答率 | 6% | 知识库没有相关信息时正确拒答 |
86% 的准确率达到了 P0 要求(>85%)。主要改进空间在于减少幻觉——可以通过增加 system prompt 的约束和降低 temperature 来优化。
六、成本总表
| 项目 | 费用 | 备注 |
|---|---|---|
| Mini PC(一次性) | 3,800 元 | RTX 4060 8GB |
| 额外 SSD(一次性) | 500 元 | 2TB |
| 域名 + 内网穿透(年) | 200 元 | 如果需要外网访问 |
| 首年总成本 | 4,500 元 | |
| 后续年成本 | 200 元/年 | 仅域名续费 |
| 每月均摊(首年) | 375 元/月 | |
| 每月均摊(后续) | 17 元/月 |
对比云端 API 方案(GPT-4 级别,每月约 2000-3000 元),第 2 个月就开始省钱。
七、运维手册
日常运维
- 监控显存:
watch -n 5 nvidia-smi - 监控服务状态:
systemctl status ollama - 日志查看:
journalctl -u ollama -f
备份策略
# 每周备份索引和配置
0 3 * * 0 tar czf /backup/kb-$(date +\%Y\%m\%d).tar.gz ./chroma_db ./docs ./rag_pipeline.py
扩展路径
当团队从 12 人增长到 50+ 人时:
- 模型升级:Qwen2.5-7B → Qwen2.5-14B(需要 16GB 显存)
- 推理引擎升级:Ollama → vLLM(支持更高并发)
- 向量数据库升级:Chroma → Qdrant 或 Milvus(分布式)
- 架构升级:单节点 → 微服务(LLM 服务、检索服务、Web 服务分离)
本文基于 2026 年 5 月的实际部署经验。所有测试在一台 RTX 4060 8GB Mini PC 上完成。模型版本:Qwen2.5-7B-Instruct (Ollama), bge-small-zh-v1.5 (HuggingFace)。