AI AinoCode AI 工具与基础设施
AI教程 4 分钟

预算<5000元,3人团队如何用开源LLM+Agent搭建企业知识库?完整部署实录

以一家3人技术团队为案例,记录从需求分析、模型选型、RAG搭建、Agent编排到生产部署的全流程,包含踩坑清单和真实成本核算。

AinoCode 编辑部

中小团队AI知识库部署实录

引子: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-7B7B8GB VRAM★★★★★中文最强,工具调用好
Qwen2.5-14B14B16GB VRAM★★★★★推理能力更强
Llama-3.1-8B8B8GB VRAM★★★☆☆英文强,中文一般
Mistral-7B7B8GB VRAM★★★☆☆轻量,但中文弱
DeepSeek-R1-Distill-7B7B8GB VRAM★★★★☆推理强,但回复风格不稳定

最终选择:Qwen2.5-7B-Instruct。理由很简单——中文场景下,7B 级别里它几乎没有对手,而且工具调用(function calling)支持最好,后续如果需要扩展 Agent 能力,这条路是通的。

第二步:选推理引擎

候选有三个:Ollama、vLLM、llama.cpp。

引擎优势劣势适用场景
Ollama一键部署,API 兼容 OpenAI并发能力弱,单实例开发/小团队
vLLM高并发,PagedAttention部署稍复杂生产环境
llama.cppCPU 可跑,极低内存速度慢极低配环境

最终选择:Ollama 用于开发和轻量部署。理由:3 人团队不需要 vLLM 级别的高并发,Ollama 的安装和运维成本最低,一个人就能搞定。

第三步:选 RAG 框架

候选:LangChain、LlamaIndex、Haystack。

我们选了 LlamaIndex。原因:

  • LangChain 太重了,学完它的概念就要花一天
  • LlamaIndex 的文档索引和检索 API 设计得更直接,SimpleDirectoryReaderVectorStoreIndexquery() 三步搞定
  • 对中文文档的解析支持更好(PDF、Word 解析)

第四步:选向量数据库

候选:Chroma、Qdrant、Milvus Lite。

选了 Chroma。理由:

  • 嵌入部署,不需要额外起服务
  • 对于这个规模的文档量(预计 5000-10000 条 chunk),Chroma 完全够用
  • 如果需要扩展,迁移到 Qdrant 或 Milvus 的成本很低

二、硬件选型与成本核算

方案对比

方案硬件价格适用场景
云服务器 GPUNVIDIA T4 (16GB)阿里云约 2.5 元/小时 ≈ 1800 元/月❌ 超预算
云服务器 CPU32C 64G (CPU 推理)约 800 元/月⚠️ 可以,但速度慢
本地 Mini PC4090 笔记本 / 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 2TB500 元
合计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-100msCPU,bge-small-zh
LLM 推理1500-2500msQwen2.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 个月就开始省钱


七、运维手册

日常运维

  1. 监控显存watch -n 5 nvidia-smi
  2. 监控服务状态systemctl status ollama
  3. 日志查看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+ 人时:

  1. 模型升级:Qwen2.5-7B → Qwen2.5-14B(需要 16GB 显存)
  2. 推理引擎升级:Ollama → vLLM(支持更高并发)
  3. 向量数据库升级:Chroma → Qdrant 或 Milvus(分布式)
  4. 架构升级:单节点 → 微服务(LLM 服务、检索服务、Web 服务分离)

本文基于 2026 年 5 月的实际部署经验。所有测试在一台 RTX 4060 8GB Mini PC 上完成。模型版本:Qwen2.5-7B-Instruct (Ollama), bge-small-zh-v1.5 (HuggingFace)。