搜「AI知识库怎么搭建和使用教程」的人,多数不是从零开始,而是卡在“我已经有模型和文档,但从哪一步接上、怎么验证它真的在用自己的资料回答”这个位置。要判断这件事能不能做,先别急着选向量库:确认版本、权限、入口位置这三个前提,再用一条最短路径把“上传—切分—检索—回答”跑通一次,最后用真实文档做一次能核对答案的提问。版本、限速、额度这类会变的参数,请在模型服务商控制台的「模型列表 / API 文档 / 用量与配额」页面当场查,不要照抄教程里的旧值。
搭建 AI 知识库的最小闭环是:准备可读的文档 → 切分成带元数据的片段 → 写入向量库或检索服务 → 提问时先检索再让模型按片段作答。适用场景是内部文档问答、产品手册检索这类资料可控的需求;不适合把大量非结构化数据直接丢进去指望模型自己归纳。操作时先跑通 10 份文档的小闭环,验证方式是用一个只有原文里才有的细节去提问,看回答是否命中且能给出片段出处;边界是检索命中不等于答案正确,命中率低时优先改切分和元数据,而不是先换模型。
AI知识库之前先确认这三件事
这三件事缺一件,后面都会以“看起来在跑但答非所问”的形式卡住,而且报错往往不指向真正原因。
第一,版本。包括模型服务端能调的模型名,以及本地依赖的版本。模型名在服务商控制台的「模型列表」或 API 文档的 models 字段里看;本地依赖用命令核对,避免装了个和教程不一致的大版本:
python -V
pip show openai
pip show langchain
pip show 输出的 Version 行就是实际安装版本。如果教程里的调用方式和你看到的接口字段对不上,以控制台当前文档为准,不要硬改参数去迁就旧例子。
第二,权限。要确认两件事:调用模型的 API Key 有没有读写知识库/文件上传的权限,以及你要导入的文档所在的存储你有没有读权限。API Key 的权限范围通常在控制台的「API Keys」页面按 key 查看;文件权限在 Linux 下用 ls -l 看属主和读写位,用当前运行账号实测一次能否读到:
ls -l /data/kb/docs/
head -c 200 /data/kb/docs/sample.md
head 能正常输出内容,说明运行账号可读;报 Permission denied 就是权限问题,先解决权限再谈切分。
第三,入口位置。即你的代码从哪里发起请求:是官方 SDK、兼容 OpenAI 协议的地址,还是自建服务。入口写成什么,取决于控制台「API 文档」里给出的 base_url 和鉴权方式。把入口先写进环境变量,后面所有脚本都读同一份配置,避免到处改:
export KB_BASE_URL="https://<控制台给出的地址>/v1"
export KB_API_KEY="<你的 key>"
export KB_MODEL="<模型列表里的模型名>"
入口地址、模型名、鉴权方式这三项都会变,请以控制台「API 文档」和「模型列表」页面当时显示的内容为准。
AI知识库:最短可用路径
目标不是搭完整系统,而是先让一次“基于自有文档的回答”成立。下面五步,每步一个动作,做完都有可观察的结果。
- 把文档放到一个固定目录。建议统一成纯文本或 Markdown 先跑通,PDF 等多格式放到第二轮。做完该看到:目录下每个文件都能被 head 正常读取。
- 切分并写入检索库。下面是一个可替换的骨架,用本地一个轻量向量库跑通闭环,参数按你的模型维度改:
# requirements: pip install chromadb
import os, glob, chromadb
client = chromadb.PersistentClient(path="./kb_store")
col = client.get_or_create_collection("docs")
chunk_size = 500 # 按字符切,中文场景先从小值试
overlap = 80
for path in glob.glob("/data/kb/docs/*.md"):
text = open(path, encoding="utf-8").read()
for i in range(0, len(text), chunk_size - overlap):
piece = text[i:i + chunk_size]
if not piece.strip():
continue
col.add(
ids=[f"{os.path.basename(path)}-{i}"],
documents=[piece],
metadatas=[{"source": path, "offset": i}],
)
print(col.count())
做完该看到:终端打印出一个大于 0 的片段数,并且 ./kb_store 目录里出现持久化文件。metadatas 里的 source 和 offset 是后面核对出处用的,不要省。
- 写一条检索加回答的调用。先检索再让模型只依据片段作答,这是知识库和直接聊天的分界线:
import os
from openai import OpenAI
import chromadb
client = chromadb.PersistentClient(path="./kb_store")
col = client.get_collection("docs")
question = "<换成一个只有你文档里才有的问题>"
hits = col.query(query_texts=[question], n_results=4)
context = "\n\n".join(hits["documents"][0])
llm = OpenAI(base_url=os.environ["KB_BASE_URL"], api_key=os.environ["KB_API_KEY"])
resp = llm.chat.completions.create(
model=os.environ["KB_MODEL"],
messages=[
{"role": "system", "content": "只依据给定资料回答;资料里没有就回答“资料中未提及”。"},
{"role": "user", "content": f"资料:\n{context}\n\n问题:{question}"},
],
)
print(resp.choices[0].message.content)
做完该看到:回答里出现你文档中的具体说法。如果模型说“资料中未提及”,先打印 hits["documents"][0] 看检索是不是就没召回,而不是怀疑模型。

- 回到出处核对。用 hits["metadatas"][0] 里的 source 和 offset 打开原文件对应位置,确认这段话确实存在。做完该看到:回答与原文一致,或明确发现是切分把上下文切断了。
- 再加第二个问题。换一个和上一个问题不同的知识点重复第 3、4 步。两个问题都能命中,才算最短闭环跑通。
AI知识库:一个真实场景的完整做法
场景设定:一个内部产品团队有约 60 份 Markdown 格式的接口说明和操作手册,单个文件多在 5KB 到 40KB 之间,需要让同事提问“某个字段的含义”和“某个操作的前置条件”。数据量不大,用本地向量库足够,不必上集群。
配置取值和位置如下:
- 文档目录:/data/kb/docs/,在服务器上创建,权限用 chmod 让运行账号可读;
- 切分参数:chunk_size=500、overlap=80,写在上面脚本的常量区。手册类文档按段落切通常比拼字符更稳,若原文有小标题,可以先按“## ”切一次再按长度截断;
- 检索条数:n_results=4,写在 col.query 调用处。文档少时先给 3 到 5 条,太多会把无关片段带进上下文;
- 模型名与地址:来自控制台「模型列表」和「API 文档」,写进 KB_MODEL、KB_BASE_URL 环境变量,脚本不写死;
- 提示词约束:写在第 3 步 messages 的 system 里,明确“只依据资料回答”和“无依据就说未提及”。
实际跑的顺序是:先只导入 10 份接口说明形成第一版 kb_store,用“某个字段是否必填”这类问题验证;命中后再把剩下的手册全量导入。全量导入后要重跑同样的两个问题,确认旧问题没有被新片段挤掉。这个顺序的价值在于:出问题时你知道是切分变了还是数据变了。
这套做法不适用的地方也要说清楚:如果文档里有大量表格或扫描件,纯文本切分会丢结构,需要先做结构化提取;如果问题需要跨多份文档做汇总统计,单轮检索加回答容易漏,得改成多轮检索或先用脚本统计再交给模型表述。
AI知识库:跑不通先查这三处
按出现频率从高到低排,每处都给判断方法。
第一处:检索没召回,模型答“资料中未提及”
页面或终端提示通常是模型返回了“资料中未提及”这类句子,而不是报错。判断方法:在检索调用后立刻打印命中的片段和距离值,
print(hits["documents"][0][:300])
print(hits["distances"][0])
如果片段和问题明显无关,检查切分是否把一句话切断、文档是否真的写进了 kb_store(用 col.count() 对比文件数估算片段量)。这一步的修改优先顺序是:调切分方式 → 补元数据 → 换 embedding 模型,先不要换对话模型。
第二处:鉴权或地址错误
常见报错形如 401 Unauthorized、403 Forbidden,或连接超时、域名解析失败。判断方法:确认 KB_BASE_URL 是否带了正确的路径前缀(很多兼容接口要求以 /v1 结尾),确认 KB_API_KEY 没有多余空格,并查看控制台「API Keys」页面确认该 key 是否被禁用或权限不足。如果本机 curl 能通而脚本不通,问题通常在环境变量没有传进运行进程,用 env | grep KB_ 检查。
第三处:模型名或参数不被接受
常见报错形如 model not found、invalid request 或提示上下文长度超限。判断方法:到控制台「模型列表」核对模型名逐字符一致(大小写和连字符都算),并检查送进去的片段是否过多导致超长。降低 n_results 或 chunk_size 是最直接的收敛方式;不要靠删掉 system 里的约束去绕过长度限制,那会让回答失去依据。
这三处的共同点是:报错信息往往只说明“调用失败”,不说明“知识库有问题”。养成每次改动只动一个变量的习惯,并用同一个只有原文才有的细节问题做回归,判断成本会低很多。