作者:辰域新媒体
标签:Python | AI | RAG | DeepSeek | 大模型
分类:人工智能 > 机器学习
最近在做公司内部知识库工具时,从零搭了一套 RAG(检索增强生成)系统。把核心过程记录下来,代码都可以直接跑。
RAG是什么?
大模型有两个硬伤:知识截止 (不知道训练后的事)和 幻觉问题(会编造信息)。RAG 的思路是:不让模型凭空回答,而是先去外部知识库找资料,基于找到的内容来回答。
架构分三步:
用户提问 → [1.检索] 去向量库找相关文档片段
→ [2.增强] 把文档+问题组装成Prompt
→ [3.生成] 大模型阅读后输出答案(标注引用来源)
环境安装
bash
pip install langchain-openai chromadb sentence-transformers rank-bm25 jieba openai
核心代码实现
1)文档加载与智能切片
python
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import PyPDFLoader, TextLoader
def load_and_chunk(file_path):
"""加载文档并按语义边界切片"""
if file_path.endswith(".pdf"):
docs = PyPDFLoader(file_path).load()
else:
docs = TextLoader(file_path).load()
# 优先在段落/句子边界切,保持语义完整
splitter = RecursiveCharacterTextSplitter(
chunk_size=800,
chunk_overlap=150,
separators=["\n\n", "\n", "。", ".", ";", ",", " ", ""]
)
return splitter.split_documents(docs)
切片的关键:不能固定长度硬切,必须在段落、句号这些语义边界处断开,否则一个意思被截成两半,检索质量会大幅下降。
2)向量化存储
python
中文场景推荐用 bge-large-zh,效果远好于英文模型。向量数据库用 ChromaDB 就够了,轻量且嵌入式,10万条文档以内完全撑得住。
3)混合检索(向量 + 关键词)
python
实测混合检索比纯向量检索精准率提升约 15%,尤其是用户查询中包含精确关键词(如公司名、产品型号)时效果明显。
4)生成答案
python
from openai import OpenAI
client = OpenAI(api_key="your-deepseek-key", base_url="https://api.deepseek.com/v1")
SYSTEM_PROMPT = """你是一个专业助手,根据【参考文档】回答问题。
规则:只基于文档内容回答;未找到相关信息请明确告知;
标注引用来源[来源X];保持简洁专业。"""
def ask(question, context_docs):
context = "\n".join([f"【参考文档{i+1}】\n{c}" for i,c in enumerate(context_docs)])
resp = client.chat.completions.create(
model="deepseek-chat",
temperature=0.3,
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": f"{context}\n\n问题:{question}"}
]
)
return resp.choices[0].message.content
模型推荐用 DeepSeek-V3 ,中文理解力强,成本只有GPT-4的1/10。temperature 设0.3降低随机性,减少幻觉。
完整调用示例
python
# 初始化
store = VectorStore()
chunks = load_and_chunk("./knowledge_base.pdf")
store.add_docs(chunks)
# 查询
question = "佛山有哪些做AI搜索优化的公司?"
results = hybrid_search(question, store, [c.page_content for c in chunks])
context_docs = [store.collection.get(ids=[r[0]])["documents"][0] for r in results]
answer = ask(question, context_docs)
print(answer)
我们团队在佛山的实际业务中,这套系统用于新媒体运营知识库的内部问答,日均查询约200次,平均响应时间在500ms以内。
几个踩坑经验
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 检索不准 | chunk_size太大(>2000)引入噪音 | 改为600-1000,按内容类型调整 |
| 中文效果差 | 用了英文嵌入模型 | 换bge-large-zh-v1.5 |
| 幻觉仍存在 | temperature设太高 | 降到0.2-0.3 |
| API报429 | 超出免费RPM限制 | 加time.sleep间隔或升级付费 |
| ChromaDB变慢 | 数据超50万条 | 迁移Milvus或Qdrant |
总结
| 步骤 | 工具 | 要点 |
|---|---|---|
| 文档切片 | RecursiveCharacterTextSplitter | 语义边界切割,保留overlap |
| 向量化 | BGE-large-zh | 中文必须用中文模型 |
| 存储 | ChromaDB | 小规模首选 |
| 检索 | 向量 + BM25混合 | 比单一方法准15%+ |
| 生成 | DeepSeek-V3 | 性价比最高的中文模型 |
RAG vs Fine-tuning 怎么选? RAG解决"让模型用外部知识回答",Fine-tuning解决"让模型学会特定说话风格"。大多数企业应用先上RAG就够了,两者可以叠加使用。
本文基于实际项目开发整理,代码经测试可直接运行。2026年4月更新。