从零搭建企业知识库:用 Claude 让内部资料真正可问可查
Claude 企业知识库搭建|附完整命令
在企业内部,知识往往分散在不同系统中:产品文档在 Confluence,制度流程在飞书/语雀,技术资料在 Git 仓库,客户问答沉淀在工单系统,销售资料散落在共享盘。随着资料规模不断扩大,员工想要快速找到准确答案变得越来越困难。
如果能把企业内部资料构建成一个可检索、可问答、可持续更新的知识库,再接入 Claude 这样擅长长文本理解、总结与推理的大模型,就可以搭建一个企业级 AI 知识助手。员工可以直接提问,例如:
- “我们公司的报销流程是什么?”
- “某产品的 API 鉴权方式有哪些?”
- “上个月客户反馈最多的问题是什么?”
- “请根据内部资料整理一份销售话术。”
- “研发代码规范中关于日志打印有什么要求?”
本文将从架构设计、环境准备、数据处理、向量数据库、Claude 接入、检索增强生成、接口开发到部署上线,完整介绍如何搭建 Claude 企业知识库,并附上可直接执行的命令。
一、企业知识库的核心思路
Claude 本身并不会自动知道企业内部资料。要让 Claude 回答企业私有知识,通常有两种方式:
第一种是直接把资料全部塞进 Prompt,但这种方式不适合企业场景。因为资料量大、上下文有限、成本高,而且难以保证每次都带入完整资料。
第二种是使用 RAG,也就是 Retrieval-Augmented Generation,中文通常叫“检索增强生成”。
RAG 的基本流程如下:
- 收集企业内部文档;
- 将文档切分成多个小片段;
- 使用 Embedding 模型将文本转成向量;
- 存入向量数据库;
- 用户提问时,将问题也转成向量;
- 从向量数据库中检索最相关的文档片段;
- 把检索结果和用户问题一起发给 Claude;
- Claude 基于检索到的企业资料生成答案。
这种方式的好处是:
- 不需要训练模型;
- 可以快速接入企业私有数据;
- 资料更新后可重新索引;
- 成本相对可控;
- 答案可以附带引用来源;
- 适合权限控制和多知识库管理。
二、整体技术架构
本文采用一套相对通用、易部署的方案:
- 大模型:Claude
- 后端语言:Python
- Web 框架:FastAPI
- 向量数据库:Chroma
- 文档解析:LangChain Community
- 向量模型:OpenAI Embedding 或本地 Embedding 模型
- 容器化:Docker
- 可选前端:任意 Chat UI
整体架构如下:
企业文档
↓
文档加载器
↓
文本清洗与切分
↓
Embedding 向量化
↓
Chroma 向量数据库
↓
用户问题
↓
相似度检索
↓
拼接上下文 Prompt
↓
Claude 生成答案
↓
返回答案与引用来源
为了便于演示,本文会使用本地目录作为企业知识文档来源。你可以将企业制度、产品说明、API 文档、FAQ、会议纪要等放到 data/docs 目录中,然后通过命令完成索引构建。
三、准备环境
1. 安装 Python
建议使用 Python 3.10 或以上版本。
查看版本:
python3 --version
如果还没有安装 Python,可以在 Ubuntu 上执行:
sudo apt update
sudo apt install -y python3 python3-pip python3-venv
macOS 用户可以使用 Homebrew:
brew install python
2. 创建项目目录
mkdir claude-enterprise-kb
cd claude-enterprise-kb
创建基础目录:
mkdir -p data/docs
mkdir -p data/chroma
mkdir -p app
mkdir -p scripts
项目结构如下:
claude-enterprise-kb/
├── app/
│ ├── main.py
│ ├── rag.py
│ ├── config.py
│ └── schemas.py
├── scripts/
│ └── ingest.py
├── data/
│ ├── docs/
│ └── chroma/
├── requirements.txt
├── .env
└── README.md
四、安装依赖
创建虚拟环境:
python3 -m venv .venv
激活虚拟环境:
source .venv/bin/activate
如果是 Windows PowerShell:
.venv\Scripts\Activate.ps1
创建 requirements.txt:
cat > requirements.txt << 'EOF'
fastapi==0.115.6
uvicorn==0.34.0
python-dotenv==1.0.1
anthropic==0.42.0
chromadb==0.5.23
langchain==0.3.13
langchain-community==0.3.13
langchain-text-splitters==0.3.4
sentence-transformers==3.3.1
pydantic==2.10.4
pypdf==5.1.0
python-docx==1.1.2
unstructured==0.16.12
markdown==3.7
EOF
安装依赖:
pip install -r requirements.txt
如果你希望使用国内镜像源,可以执行:
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
五、配置 Claude API Key
创建 .env 文件:
cat > .env << 'EOF'
ANTHROPIC_API_KEY=你的_Claude_API_Key
CLAUDE_MODEL=claude-3-5-sonnet-20241022
CHROMA_DIR=./data/chroma
DOCS_DIR=./data/docs
EMBEDDING_MODEL=BAAI/bge-small-zh-v1.5
TOP_K=5
EOF
说明:
ANTHROPIC_API_KEY:Claude API Key
CLAUDE_MODEL:使用的 Claude 模型
CHROMA_DIR:Chroma 向量库保存路径
DOCS_DIR:企业文档目录
EMBEDDING_MODEL:Embedding 模型
TOP_K:每次检索返回的文档片段数量
这里使用 BAAI/bge-small-zh-v1.5 作为中文向量模型,适合中文企业文档。它可以本地运行,不需要额外调用外部 Embedding API,适合对数据安全要求较高的场景。
六、准备企业知识文档
你可以把文档放到 data/docs 目录中。
例如:
cat > data/docs/company_policy.md << 'EOF'
# 公司报销制度
员工因公产生的合理费用可以申请报销。报销必须提供真实、有效、合规的发票。
## 报销流程
1. 员工在费用发生后 30 天内提交报销申请。
2. 直属主管审批。
3. 财务部门审核发票和金额。
4. 审核通过后,费用将在 5 个工作日内打款。
## 注意事项
餐饮报销需注明参与人员、事由和时间。交通费用需提供行程记录。
EOF
再创建一个产品文档:
cat > data/docs/product_api.md << 'EOF'
# 产品 API 文档
## 鉴权方式
本产品 API 使用 Bearer Token 进行鉴权。调用接口时,需要在请求头中添加 Authorization 字段。
示例:
Authorization: Bearer your_access_token
## 限流规则
普通企业客户每分钟最多调用 600 次接口。高级企业客户每分钟最多调用 3000 次接口。
## 错误码
401 表示鉴权失败。
429 表示请求过于频繁。
500 表示服务端内部错误。
EOF
实际生产环境中,建议支持以下类型文件:
- Markdown
- TXT
- Word
- HTML
- CSV
- JSON
- 企业内部知识平台导出的文档
七、编写配置文件
创建 app/config.py:
cat > app/config.py << 'EOF'
import os
from dotenv import load_dotenv
load_dotenv()
ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY")
CLAUDE_MODEL = os.getenv("CLAUDE_MODEL", "claude-3-5-sonnet-20241022")
CHROMA_DIR = os.getenv("CHROMA_DIR", "./data/chroma")
DOCS_DIR = os.getenv("DOCS_DIR", "./data/docs")
EMBEDDING_MODEL = os.getenv("EMBEDDING_MODEL", "BAAI/bge-small-zh-v1.5")
TOP_K = int(os.getenv("TOP_K", "5"))
if not ANTHROPIC_API_KEY:
raise ValueError("请在 .env 中配置 ANTHROPIC_API_KEY")
EOF
八、构建文档入库脚本
下面编写核心的文档索引脚本,它会完成:
- 扫描企业文档目录;
- 加载 Markdown、TXT、PDF、DOCX 等文档;
- 将文档切分成文本块;
- 使用中文 Embedding 模型生成向量;
- 写入 Chroma 向量数据库。
创建 scripts/ingest.py:
cat > scripts/ingest.py << 'EOF'
import os
import sys
from pathlib import Path
sys.path.append(str(Path(__file__).resolve().parents[1]))
from langchain_community.document_loaders import (
TextLoader,
PyPDFLoader,
Docx2txtLoader,
UnstructuredMarkdownLoader,
)
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import HuggingFaceEmbeddings
from app.config import DOCS_DIR, CHROMA_DIR, EMBEDDING_MODEL
def load_documents(docs_dir: str):
docs = []
docs_path = Path(docs_dir)
if not docs_path.exists():
raise FileNotFoundError(f"文档目录不存在:{docs_dir}")
for file_path in docs_path.rglob("*"):
if file_path.is_dir():
continue
suffix = file_path.suffix.lower()
try:
if suffix in [".txt"]:
loader = TextLoader(str(file_path), encoding="utf-8")
elif suffix in [".md", ".markdown"]:
loader = UnstructuredMarkdownLoader(str(file_path))
elif suffix in [".pdf"]:
loader = PyPDFLoader(str(file_path))
elif suffix in [".docx"]:
loader = Docx2txtLoader(str(file_path))
else:
print(f"跳过不支持的文件:{file_path}")
continue
loaded = loader.load()
for doc in loaded:
doc.metadata["source"] = str(file_path)
docs.extend(loaded)
print(f"已加载:{file_path}")
except Exception as e:
print(f"加载失败:{file_path},原因:{e}")
return docs
def split_documents(documents):
splitter = RecursiveCharacterTextSplitter(
chunk_size=800,
chunk_overlap=120,
separators=["\n\n", "\n", "。", "!", "?", ".", "!", "?", " ", ""],
)
return splitter.split_documents(documents)
def build_vector_store(chunks):
embeddings = HuggingFaceEmbeddings(
model_name=EMBEDDING_MODEL,
model_kwargs={"device": "cpu"},
encode_kwargs={"normalize_embeddings": True},
)
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory=CHROMA_DIR,
collection_name="enterprise_knowledge",
)
vectorstore.persist()
return vectorstore
def main():
print("开始加载企业文档...")
documents = load_documents(DOCS_DIR)
print(f"原始文档数量:{len(documents)}")
if not documents:
print("没有可入库的文档,请先将文档放入 data/docs 目录。")
return
print("开始切分文档...")
chunks = split_documents(documents)
print(f"切分后的文本块数量:{len(chunks)}")
print("开始构建向量数据库...")
build_vector_store(chunks)
print(f"知识库构建完成,向量数据库目录:{CHROMA_DIR}")
if __name__ == "__main__":
main()
EOF
执行入库命令:
python scripts/ingest.py
第一次运行时会下载 Embedding 模型,耗时取决于网络环境。
如果模型下载较慢,可以设置 Hugging Face 镜像:
export HF_ENDPOINT=https://hf-mirror.com
python scripts/ingest.py
九、编写 RAG 核心逻辑
创建 app/rag.py:
cat > app/rag.py << 'EOF'
from typing import List, Dict, Any
from anthropic import Anthropic
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import HuggingFaceEmbeddings
from app.config import (
ANTHROPIC_API_KEY,
CLAUDE_MODEL,
CHROMA_DIR,
EMBEDDING_MODEL,
TOP_K,
)
SYSTEM_PROMPT = """
你是企业内部知识库助手。你的任务是基于提供的企业知识库资料回答用户问题。
要求:
1. 优先依据【知识库资料】回答,不要编造不存在的信息。
2. 如果资料中没有相关内容,请明确说明“根据当前知识库资料,无法确认该问题”。
3. 回答要结构清晰,适合企业员工阅读。
4. 如果涉及流程、制度、技术规范,请尽量分点说明。
5. 回答末尾列出引用来源。
"""
def get_vectorstore():
embeddings = HuggingFaceEmbeddings(
model_name=EMBEDDING_MODEL,
model_kwargs={"device": "cpu"},
encode_kwargs={"normalize_embeddings": True},
)
return Chroma(
persist_directory=CHROMA_DIR,
embedding_function=embeddings,
collection_name="enterprise_knowledge",
)
def format_docs(docs) -> str:
formatted = []
for i, doc in enumerate(docs, start=1):
source = doc.metadata.get("source", "未知来源")
page = doc.metadata.get("page")
source_text = f"{source}"
if page is not None:
source_text += f",第 {page + 1} 页"
formatted.append(
f"【资料 {i}】\n来源:{source_text}\n内容:\n{doc.page_content}"
)
return "\n\n".join(formatted)
def ask_claude(question: str, context: str) -> str:
client = Anthropic(api_key=ANTHROPIC_API_KEY)
user_prompt = f"""
请基于以下企业知识库资料回答用户问题。
【知识库资料】
{context}
【用户问题】
{question}
请直接给出答案。
"""
response = client.messages.create(
model=CLAUDE_MODEL,
max_tokens=1200,
temperature=0.2,
system=SYSTEM_PROMPT,
messages=[
{
"role": "user",
"content": user_prompt,
}
],
)
return response.content[0].text
def query_knowledge_base(question: str) -> Dict[str, Any]:
vectorstore = get_vectorstore()
retriever = vectorstore.as_retriever(
search_type="similarity",
search_kwargs={"k": TOP_K},
)
docs = retriever.get_relevant_documents(question)
context = format_docs(docs)
answer = ask_claude(question, context)
sources = []
for doc in docs:
item = {
"source": doc.metadata.get("source", "未知来源"),
"page": doc.metadata.get("page"),
"content_preview": doc.page_content[:160],
}
sources.append(item)
return {
"question": question,
"answer": answer,
"sources": sources,
}
EOF
这里有几个关键点:
temperature=0.2:让回答更稳定,降低胡编概率;TOP_K=5:每次取 5 个最相关文本块;SYSTEM_PROMPT:约束 Claude 必须基于知识库回答;sources:返回引用来源,便于员工核验。
十、编写 API 服务
创建请求与响应模型 app/schemas.py:
cat > app/schemas.py << 'EOF'
from typing import List, Optional
from pydantic import BaseModel
class AskRequest(BaseModel):
question: str
class SourceItem(BaseModel):
source: str
page: Optional[int] = None
content_preview: str
class AskResponse(BaseModel):
question: str
answer: str
sources: List[SourceItem]
EOF
创建 app/main.py:
cat > app/main.py << 'EOF'
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from app.schemas import AskRequest, AskResponse
from app.rag import query_knowledge_base
app = FastAPI(
title="Claude 企业知识库 API",
description="基于 Claude 和 RAG 的企业内部知识库问答服务",
version="1.0.0",
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/health")
def health():
return {"status": "ok"}
@app.post("/ask", response_model=AskResponse)
def ask(req: AskRequest):
question = req.question.strip()
if not question:
raise HTTPException(status_code=400, detail="问题不能为空")
try:
return query_knowledge_base(question)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
EOF
启动服务:
uvicorn app.main:app --host 0.0.0.0 --port 8000
访问健康检查:
curl http://localhost:8000/health
返回:
{
"status": "ok"
}
十一、测试企业知识库问答
使用 curl 提问:
curl -X POST "http://localhost:8000/ask" \
-H "Content-Type: application/json" \
-d '{"question":"公司的报销流程是什么?"}'
你可能会得到类似结果:
{
"question": "公司的报销流程是什么?",
"answer": "公司的报销流程如下:\n\n1. 员工在费用发生后 30 天内提交报销申请。\n2. 直属主管进行审批。\n3. 财务部门审核发票和金额。\n4. 审核通过后,费用将在 5 个工作日内打款。\n\n引用来源:data/docs/company_policy.md",
"sources": [
{
"source": "data/docs/company_policy.md",
"page": null,
"content_preview": "公司报销制度..."
}
]
}
测试产品 API:
curl -X POST "http://localhost:8000/ask" \
-H "Content-Type: application/json" \
-d '{"question":"产品 API 的鉴权方式是什么?"}'
十二、使用 Docker 部署
如果希望在服务器上部署,可以使用 Docker。
创建 Dockerfile:
cat > Dockerfile << 'EOF'
FROM python:3.11-slim
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
RUN apt-get update && apt-get install -y \
build-essential \
curl \
libmagic1 \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
EOF
创建 .dockerignore:
cat > .dockerignore << 'EOF'
.venv
__pycache__
*.pyc
.git
.env
data/chroma
EOF
构建镜像:
docker build -t claude-enterprise-kb:1.0 .
运行容器:
docker run -d \
--name claude-enterprise-kb \
-p 8000:8000 \
--env-file .env \
-v $(pwd)/data:/app/data \
claude-enterprise-kb:1.0
查看日志:
docker logs -f claude-enterprise-kb
进入容器重新构建知识库:
docker exec -it claude-enterprise-kb python scripts/ingest.py
停止容器:
docker stop claude-enterprise-kb
删除容器:
docker rm claude-enterprise-kb
十三、使用 Docker Compose 部署
创建 docker-compose.yml:
cat > docker-compose.yml << 'EOF'
services:
claude-kb:
build: .
container_name: claude-enterprise-kb
ports:
- "8000:8000"
env_file:
- .env
volumes:
- ./data:/app/data
restart: unless-stopped
EOF
启动:
docker compose up -d
查看日志:
docker compose logs -f
重新构建知识库:
docker compose exec claude-kb python scripts/ingest.py
停止服务:
docker compose down
十四、企业级优化建议
上面的方案可以完成一个可运行的企业知识库原型,但如果要投入生产,还需要进一步优化。
1. 权限控制
企业知识库不能所有人都看所有资料。建议按部门、岗位、项目组做权限隔离。
例如:
- HR 文档只允许 HR 和员工本人查询;
- 财务制度对全员开放,但财务报表只允许管理层访问;
- 技术文档只允许研发、测试、运维访问;
- 客户资料需要按销售团队或区域隔离。
实现方式可以是在文档 metadata 中加入权限字段:
{
"source": "finance/report_2024.pdf",
"department": "finance",
"acl": ["cfo", "finance_manager"]
}
检索时根据当前用户身份过滤:
search_kwargs={
"k": 5,
"filter": {
"department": "finance"
}
}
2. 引用来源与可追溯
企业知识库最重要的是可信。回答必须能告诉用户“依据什么资料得出结论”。
建议每个回答都返回:
- 文档名称;
- 文档路径;
- 页码;
- 段落;
- 更新时间;
- 文档负责人;
- 版本号。
这样当答案涉及制度、合同、技术规范时,员工可以回到原文核实。
3. 文档增量更新
原型中每次执行 ingest.py 都是重新构建知识库。生产环境建议做增量更新:
- 给文档计算 hash;
- 只有文档内容变化时才重新切分;
- 删除已不存在的文档;
- 保留文档版本;
- 建立定时同步任务。
可以使用以下命令生成文件 hash:
sha256sum data/docs/company_policy.md
也可以写定时任务每天凌晨同步:
crontab -e
加入:
0 2 * * * cd /opt/claude-enterprise-kb && /opt/claude-enterprise-kb/.venv/bin/python scripts/ingest.py >> logs/ingest.log 2>&1
创建日志目录:
mkdir -p logs
4. 检索质量优化
RAG 的效果很大程度上取决于检索质量。常见优化手段包括:
- 调整 chunk size;
- 使用更强的 Embedding 模型;
- 使用 reranker 重排序;
- 加入关键词检索;
- 使用混合检索;
- 对标题、目录、摘要加权;
- 保留文档层级结构。
中文场景可以考虑:
BAAI/bge-small-zh-v1.5
BAAI/bge-base-zh-v1.5
BAAI/bge-large-zh-v1.5
moka-ai/m3e-base
shibing624/text2vec-base-chinese
如果服务器性能允许,可以将配置改成:
EMBEDDING_MODEL=BAAI/bge-base-zh-v1.5
重新入库:
python scripts/ingest.py
5. 防止模型幻觉
Claude 虽然能力很强,但在资料不足时仍可能生成看似合理但不准确的回答。因此 Prompt 中必须明确要求:
- 只能基于知识库资料回答;
- 不知道就说不知道;
- 不允许编造制度和数据;
- 需要列出引用来源;
- 涉及高风险内容时提示人工确认。
可以在系统提示词中加入:
如果知识库资料不足以支持结论,请不要猜测。
如果用户要求你给出法律、财务、合规结论,请提示用户咨询对应负责人。
6. 日志与审计
企业场景中,必须记录关键日志:
- 用户 ID;
- 提问时间;
- 用户问题;
- 检索到的文档;
- Claude 返回答案;
- Token 消耗;
- 响应时间;
- 用户反馈。
但要注意隐私和合规,不建议在日志中明文保存敏感数据。可以对问题和答案做脱敏处理。
7. 接入企业 IM
知识库 API 建好后,可以接入:
- 企业微信;
- 飞书;
- 钉钉;
- Slack;
- Microsoft Teams;
- 内部 Web 门户。
员工无需打开额外系统,只需在聊天工具中提问即可。
例如飞书机器人收到消息后,将用户问题转发到:
POST http://your-server:8000/ask
然后把返回答案发送回群聊或私聊。
十五、常见问题排查
1. Chroma 没有检索到内容
检查是否已经执行入库:
python scripts/ingest.py
检查向量库目录是否存在:
ls -lah data/chroma
检查文档目录:
find data/docs -type f
2. Claude API Key 报错
检查 .env:
cat .env
确认环境变量加载:
python -c "from app.config import ANTHROPIC_API_KEY; print(bool(ANTHROPIC_API_KEY))"
3. Embedding 模型下载失败
设置镜像:
export HF_ENDPOINT=https://hf-mirror.com
python scripts/ingest.py
或者提前下载模型到本地,然后将 EMBEDDING_MODEL 改成本地路径。
4. PDF 解析效果不好
PDF 如果是扫描件,需要先做 OCR。可以使用:
sudo apt install -y tesseract-ocr tesseract-ocr-chi-sim
对扫描 PDF 做 OCR 后再入库。
十六、完整启动流程汇总
如果你只想快速跑起来,可以按下面命令执行。
mkdir claude-enterprise-kb
cd claude-enterprise-kb
mkdir -p data/docs data/chroma app scripts
python3 -m venv .venv
source .venv/bin/activate
cat > requirements.txt << 'EOF'
fastapi==0.115.6
uvicorn==0.34.0
python-dotenv==1.0.1
anthropic==0.42.0
chromadb==0.5.23
langchain==0.3.13
langchain-community==0.3.13
langchain-text-splitters==0.3.4
sentence-transformers==3.3.1
pydantic==2.10.4
pypdf==5.1.0
python-docx==1.1.2
unstructured==0.16.12
markdown==3.7
EOF
pip install -r requirements.txt
然后创建代码文件,配置 .env,放入企业文档,执行:
python scripts/ingest.py
uvicorn app.main:app --host 0.0.0.0 --port 8000
测试:
curl -X POST "http://localhost:8000/ask" \
-H "Content-Type: application/json" \
-d '{"question":"公司的报销流程是什么?"}'
十七、总结
Claude 企业知识库的核心不是简单地“把文档丢给大模型”,而是通过 RAG 架构把企业资料、检索系统、权限控制、引用溯源和大模型生成能力结合起来。
本文提供的方案具备以下特点:
- 使用 Claude 作为问答生成模型;
- 使用本地中文 Embedding 模型保护数据安全;
- 使用 Chroma 存储企业文档向量;
- 使用 FastAPI 提供标准接口;
- 支持 Markdown、TXT、PDF、DOCX 等文档;
- 提供完整命令,可快速本地运行;
- 可进一步扩展到权限控制、增量更新、企业 IM 和生产部署。
对于企业来说,知识库的价值不只是“回答问题”,更重要的是降低信息查找成本、提升新人上手速度、减少重复沟通、沉淀组织知识,并让内部知识真正流动起来。
如果后续要继续升级,可以重点投入三个方向:第一是权限和安全,第二是检索质量,第三是与企业现有系统的深度集成。只要这三点做好,Claude 企业知识库就可以从一个 AI Demo 变成真正可用的企业效率工具。