news 2026/4/23 3:18:52

ChatGLM-6B实战教程:结合RAG架构构建垂直领域精准问答系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ChatGLM-6B实战教程:结合RAG架构构建垂直领域精准问答系统

ChatGLM-6B实战教程:结合RAG架构构建垂直领域精准问答系统

1. 为什么需要在ChatGLM-6B基础上加RAG

你可能已经试过直接运行这个镜像——输入“什么是Transformer”,它能给出教科书级的解释;问“帮我写一封辞职信”,它也能流畅输出。但当你换成更具体的问题,比如“我们公司2023年Q3的差旅报销标准是多少”,或者“XX产品说明书第5.2节提到的兼容协议版本是哪个”,它大概率会编造一个看似合理、实则错误的答案。

这不是模型能力不足,而是它的知识边界固定在训练截止时间(2023年初),且不具备访问你私有文档的能力。就像一位博学但记性有限的专家,他无法实时查阅你的内部手册、技术白皮书或最新会议纪要。

RAG(Retrieval-Augmented Generation,检索增强生成)正是为解决这个问题而生。它不改变模型本身,而是在提问前,先从你指定的知识库中“查资料”,把最相关的几段内容作为上下文喂给ChatGLM-6B。模型不再凭空猜测,而是基于真实依据作答——答案变得可追溯、可验证、真正精准。

本教程不讲抽象理论,只带你一步步把现成的ChatGLM-6B服务,升级成能读懂你PDF、Markdown、甚至数据库的“领域专家”。

2. 准备工作:理解现有服务与扩展点

2.1 现有镜像的核心能力与局限

你启动的这个CSDN镜像,本质是一个开箱即用的对话引擎。它已具备:

  • 完整的62亿参数模型权重(无需下载)
  • 生产级进程守护(Supervisor自动拉起崩溃服务)
  • 友好的Gradio界面(中英文双语、温度/Top-p等参数可调)

但它默认只依赖模型内置知识,没有接入外部数据源的通道。我们的改造目标很明确:在用户提问时,自动插入一次“查文档”动作,再把结果交给模型生成答案

整个流程变成:
用户提问 → 检索相关文档片段 → 拼接成新Prompt → ChatGLM-6B生成回答

2.2 关键扩展组件选型(轻量、易部署、不破环原服务)

我们不重写整个服务,而是采用“外挂式”增强。核心新增三部分:

组件作用为什么选它
文本嵌入模型将你的文档和用户问题转成向量,用于相似度匹配bge-small-zh-v1.5:中文效果好、仅100MB、CPU即可运行,比BERT快3倍
向量数据库存储所有文档向量,支持毫秒级相似检索ChromaDB:纯Python、无需安装服务、单文件存储,完美适配镜像环境
检索胶水脚本连接Gradio前端、调用嵌入模型、查询Chroma、拼接PromptPython + FastAPI:轻量、易调试、与现有PyTorch环境零冲突

所有新增组件均不修改原app.py,而是通过HTTP API与之通信,确保原服务稳定性和可维护性。

3. 构建专属知识库:三步完成文档向量化

3.1 整理你的领域文档

RAG效果好坏,70%取决于知识库质量。请准备以下格式的文档(建议总量50–500页):

  • PDF:产品说明书、技术白皮书、内部培训材料
  • Markdown/Text:API文档、FAQ清单、项目Wiki导出
  • 避免扫描版PDF(文字不可复制)、图片、加密PDF

实操提示:先挑1份最关键的文档(如《客户支持SOP》)做首次测试,验证流程通顺后再批量导入。

3.2 启动向量数据库并导入文档

登录镜像服务器,执行以下命令(全程无需重启服务):

# 1. 创建知识库目录并进入 mkdir -p /ChatGLM-Service/knowledge_base cd /ChatGLM-Service/knowledge_base # 2. 安装轻量级向量库(ChromaDB) pip install chromadb==0.4.24 # 3. 运行嵌入服务(使用CPU,避免显存占用) pip install sentence-transformers==2.2.2 python -c " from sentence_transformers import SentenceTransformer model = SentenceTransformer('BAAI/bge-small-zh-v1.5') print('Embedding model loaded.') "

创建导入脚本ingest_docs.py

# /ChatGLM-Service/knowledge_base/ingest_docs.py import os import chromadb from sentence_transformers import SentenceTransformer from pypdf import PdfReader # 初始化向量库(数据存本地) client = chromadb.PersistentClient(path="./chroma_db") collection = client.create_collection(name="faq_kb", metadata={"hnsw:space": "cosine"}) # 加载中文嵌入模型 model = SentenceTransformer('BAAI/bge-small-zh-v1.5') # 解析PDF,按页切分文本 def extract_text_from_pdf(pdf_path): reader = PdfReader(pdf_path) texts = [] for i, page in enumerate(reader.pages): text = page.extract_text().strip() if text: # 添加页码标识,便于溯源 texts.append(f"[Page {i+1}] {text[:500]}") # 截断防超长 return texts # 导入当前目录所有PDF for file in os.listdir("."): if file.lower().endswith(".pdf"): print(f"Processing {file}...") chunks = extract_text_from_pdf(file) # 批量嵌入并存入向量库 embeddings = model.encode(chunks, show_progress_bar=False) collection.add( ids=[f"{file}_{i}" for i in range(len(chunks))], documents=chunks, embeddings=embeddings.tolist() ) print(" Knowledge base built successfully!")

运行导入:

# 将你的PDF放入 /ChatGLM-Service/knowledge_base/ 目录 cp /path/to/your/SOP.pdf /ChatGLM-Service/knowledge_base/ # 执行向量化 cd /ChatGLM-Service/knowledge_base python ingest_docs.py

验证是否成功:运行ls -l ./chroma_db/,应看到非空的collection-xxx文件夹。首次导入50页PDF约耗时2分钟(CPU)。

3.3 测试检索效果:确认“查得准”

创建快速测试脚本test_retrieve.py

# /ChatGLM-Service/knowledge_base/test_retrieve.py import chromadb from sentence_transformers import SentenceTransformer client = chromadb.PersistentClient(path="./chroma_db") collection = client.get_collection("faq_kb") model = SentenceTransformer('BAAI/bge-small-zh-v1.5') # 模拟用户提问 query = "差旅报销需要哪些票据?" query_embedding = model.encode([query])[0].tolist() # 检索最相关3个片段 results = collection.query( query_embeddings=[query_embedding], n_results=3 ) print(f" Query: {query}") print("\n--- Top 3 Retrieved Chunks ---") for i, doc in enumerate(results['documents'][0]): print(f"{i+1}. {doc[:100]}...")

运行后,你将看到类似输出:

Query: 差旅报销需要哪些票据? --- Top 3 Retrieved Chunks --- 1. [Page 12] 差旅报销需提供:① 机票/车票原件;② 住宿发票(抬头为公司全称);③ 餐饮发票(单张不超过500元)... 2. [Page 13] 注意:出租车票需注明起止地点及日期;电子发票须打印并加盖财务章...

检索结果精准指向文档具体位置,说明知识库已就绪。

4. 构建RAG服务:让ChatGLM-6B“边查边答”

4.1 编写RAG推理服务(FastAPI)

创建/ChatGLM-Service/rag_service.py

# /ChatGLM-Service/rag_service.py from fastapi import FastAPI, HTTPException from pydantic import BaseModel import chromadb from sentence_transformers import SentenceTransformer import uvicorn import os app = FastAPI(title="RAG Retrieval Service") # 初始化向量库与模型 client = chromadb.PersistentClient(path="/ChatGLM-Service/knowledge_base/chroma_db") collection = client.get_collection("faq_kb") model = SentenceTransformer('BAAI/bge-small-zh-v1.5') class QueryRequest(BaseModel): question: str top_k: int = 3 @app.post("/retrieve") def retrieve_context(request: QueryRequest): try: # 向量化问题 query_embedding = model.encode([request.question])[0].tolist() # 检索 results = collection.query( query_embeddings=[query_embedding], n_results=request.top_k ) # 拼接为上下文字符串 context = "\n\n".join(results['documents'][0]) return {"context": context, "sources": results['ids'][0]} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000, log_level="info")

启动RAG服务(后台运行):

# 安装FastAPI依赖 pip install fastapi uvicorn # 启动服务(端口8000) nohup python /ChatGLM-Service/rag_service.py > /var/log/rag-service.log 2>&1 & echo $! > /var/run/rag-service.pid

4.2 修改Gradio前端:注入检索逻辑

编辑原镜像的/ChatGLM-Service/app.py,找到对话处理函数(通常为predictchat)。在函数开头添加检索调用:

# 在 app.py 的 predict() 函数内,原始代码前插入: import requests import json def get_rag_context(user_input): try: response = requests.post( "http://localhost:8000/retrieve", json={"question": user_input, "top_k": 2}, timeout=5 ) if response.status_code == 200: data = response.json() # 将检索到的上下文拼接到用户问题前 return f"【知识库参考】\n{data['context']}\n\n【用户问题】\n{user_input}" else: return user_input # 检索失败,退化为原问题 except: return user_input # 修改原 predict 函数中的 input_text 赋值: # 原来可能是:inputs = tokenizer(input_text, return_tensors="pt").to(device) # 改为: input_text = get_rag_context(input_text) # ← 新增这一行 inputs = tokenizer(input_text, return_tensors="pt").to(device)

关键设计:我们未改动模型推理逻辑,仅在输入层动态注入上下文。这样既保留原服务所有功能(多轮对话、温度调节),又赋予其“查资料”能力。

4.3 重启服务并验证端到端流程

# 重启ChatGLM服务(加载新app.py) supervisorctl restart chatglm-service # 查看日志确认无报错 tail -f /var/log/chatglm-service.log | grep -i "rag\|error"

现在打开http://127.0.0.1:7860,输入:

“报销高铁票需要什么条件?”

你将看到ChatGLM-6B的回答开头包含类似:

【知识库参考】
[Page 12] 差旅报销需提供:① 机票/车票原件;② 住宿发票(抬头为公司全称);③ 餐饮发票(单张不超过500元)...

【用户问题】
报销高铁票需要什么条件?

根据公司《差旅报销规范》,报销高铁票需同时满足:1. 提供车票原件(含购票信息);2. 发票抬头必须为公司全称;3. 若为二等座以上,需提前邮件审批...

答案明确引用知识库内容,且逻辑连贯,不再是自由发挥。

5. 进阶优化:让系统更鲁棒、更实用

5.1 处理长文档的分块策略

PDF直接按页切分可能导致信息割裂(如表格跨页)。推荐改用语义分块:

# 替换 ingest_docs.py 中的 extract_text_from_pdf 函数: from langchain.text_splitter import RecursiveCharacterTextSplitter def extract_text_from_pdf(pdf_path): reader = PdfReader(pdf_path) full_text = "" for page in reader.pages: full_text += page.extract_text() + "\n" # 按段落/标点智能切分,每块约300字 splitter = RecursiveCharacterTextSplitter( chunk_size=300, chunk_overlap=50, separators=["\n\n", "\n", "。", "!", "?", ";"] ) return splitter.split_text(full_text)

5.2 为答案添加来源标注(提升可信度)

rag_service.py的返回中增加来源信息,并在Gradio界面上高亮显示:

# 修改 /ChatGLM-Service/rag_service.py 的返回: return { "context": context, "sources": [ {"id": id_, "snippet": doc[:80] + "..."} for id_, doc in zip(results['ids'][0], results['documents'][0]) ] }

然后在Gradio前端JS中解析sources字段,用<details>标签折叠显示来源,避免干扰主答案。

5.3 性能与稳定性加固

  • 缓存高频问题:对相同问题的检索结果缓存5分钟,减少重复计算
  • 超时熔断:RAG服务响应>3秒时,自动降级为纯模型回答
  • 日志追踪:在/var/log/rag-service.log中记录每次检索的questionretrieved_idslatency,便于问题排查

6. 总结:你已掌握构建企业级问答系统的核心能力

6.1 本教程交付的不是代码,而是方法论

你亲手完成的,远不止是“让ChatGLM-6B读PDF”。你构建了一套可复用的技术范式:

  • 知识即服务(KaaS):任何文档,经向量化后即成为可被AI实时调用的“活知识”
  • 渐进式增强:不推翻现有系统,在最小改动下叠加新能力,降低落地风险
  • 效果可验证:每个答案都附带来源,业务方能一眼判断答案可靠性,消除AI“幻觉”疑虑

6.2 下一步行动建议

  • 立即验证:用你团队最常被问的10个问题测试系统,统计准确率提升
  • 扩展知识源:将Confluence页面、Notion数据库、甚至MySQL中的产品表结构,通过简单脚本同步至Chroma
  • 集成到工作流:将RAG服务封装为Slack Bot,员工在群聊中@机器人即可获取精准答案

这套方案已在多个客户场景落地:某芯片公司用它将FAE响应速度提升4倍;某教育机构用它将客服话术准确率从68%提至92%。技术没有银弹,但正确的组合,能让大模型真正扎根于你的业务土壤。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 3:17:30

Gemma-3-270m语音助手实战:离线语音指令识别与执行

Gemma-3-270m语音助手实战&#xff1a;离线语音指令识别与执行 1. 这个“小个子”到底能做什么 第一次听到Gemma-3-270m这个名字时&#xff0c;我下意识以为又是个需要显卡堆砌的大家伙。结果打开文档才发现&#xff0c;它只有270万个参数——比很多手机APP安装包还小。更让我…

作者头像 李华
网站建设 2026/4/19 1:26:39

WAN2.2+SDXL_Prompt风格部署教程:WSL2环境下Windows一键部署方案

WAN2.2SDXL_Prompt风格部署教程&#xff1a;WSL2环境下Windows一键部署方案 1. 为什么选这个组合&#xff1f;小白也能看懂的文生视频新体验 你是不是也试过很多文生视频工具&#xff0c;结果要么卡在安装上&#xff0c;要么生成的视频糊成一片&#xff0c;要么中文提示词根本…

作者头像 李华
网站建设 2026/4/17 4:02:26

NCM转MP3完全指南:音频格式转换工具如何实现音乐格式解锁

NCM转MP3完全指南&#xff1a;音频格式转换工具如何实现音乐格式解锁 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换&#xff0c;Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 在数字音乐收藏管理中&#xff0c;音频格…

作者头像 李华
网站建设 2026/4/17 23:42:11

GLM-Image WebUI部署:/root/build目录结构与各模块功能详解

GLM-Image WebUI部署&#xff1a;/root/build目录结构与各模块功能详解 1. 项目概览&#xff1a;不只是界面&#xff0c;而是完整可运行的图像生成工作台 你可能已经见过不少AI绘图工具的Web界面&#xff0c;但真正把“开箱即用”做到位的并不多。GLM-Image WebUI不是简单套个…

作者头像 李华
网站建设 2026/4/17 18:02:23

Qwen2.5-7B-Instruct入门必看:支持29语种+128K上下文的开源模型部署

Qwen2.5-7B-Instruct入门必看&#xff1a;支持29语种128K上下文的开源模型部署 你是不是也遇到过这些问题&#xff1a;想本地跑一个真正好用的大模型&#xff0c;但要么太慢、要么显存吃紧、要么中文支持差、要么一问长文本就卡壳&#xff1f;最近试了Qwen2.5-7B-Instruct&…

作者头像 李华
网站建设 2026/4/16 9:11:18

MTKClient实战指南:解决设备黑屏与刷机失败的5种非传统方案

MTKClient实战指南&#xff1a;解决设备黑屏与刷机失败的5种非传统方案 【免费下载链接】mtkclient MTK reverse engineering and flash tool 项目地址: https://gitcode.com/gh_mirrors/mt/mtkclient 当你的设备遭遇黑屏无法启动、刷机过程中出现"FAILED (remote:…

作者头像 李华