基于 ChatGLM3-6B 与 LangChain 搭建私有知识库助手:从语料入库、检索问答到 Gradio Web Demo 全流程实战

发布时间:2026/9/19 12:48:35
基于 ChatGLM3-6B 与 LangChain 搭建私有知识库助手:从语料入库、检索问答到 Gradio Web Demo 全流程实战 基于 ChatGLM3-6B 与 LangChain 搭建私有知识库助手从语料入库、检索问答到 Gradio Web Demo 全流程实战【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/datawhalechina/self-llm本文是 self-llm 项目ChatGLM3-6B 接入 LangChain 搭建知识库助手的完整实战指南基于检索增强生成RAG技术讲解如何将 Datawhale 系列开源教程作为语料经文本加载、分块、向量化后存入 Chroma 向量数据库再将本地部署的 ChatGLM3-6B 封装为自定义 LLM 接入 LangChain最终构建可回答私有知识问题的检索问答链并通过 Gradio 部署为 Web Demo。读完本文你将掌握语料入库 → 语义检索 → 增强问答 → 网页化的完整技术链路可直接复现一个能基于自身文档回答问题的知识库助手。一、方案概览用 RAG 为 ChatGLM3-6B 补充私有知识基础大模型虽然具备强大的通用对话能力但其知识存在截止时间与领域空白对于仓库文档、业务手册等私有语料模型无法凭空回答。本方案采用检索增强生成RAG思路让模型在回答前先查资料把语料切块后向量化入库收到用户提问时先做语义检索取回相关片段再连同问题一起交给 ChatGLM3-6B 生成有依据的回答。整个方案由四个环节组成与本项目中的组件一一对应文本加载递归遍历语料目录使用 LangChain 的UnstructuredMarkdownLoader/UnstructuredFileLoader将.md、.txt文件解析为纯文本对象文本分块使用RecursiveCharacterTextSplitter将长文本切成便于检索的小块向量化与入库使用开源多语言词向量模型Sentence Transformer将文本块编码为向量写入 Chroma 向量数据库并持久化到磁盘检索问答基于本地部署的 ChatGLM3-6B 自定义 LLM 类与向量检索器、Prompt 模板一起组装成RetrievalQA检索问答链再用 Gradio 封装成网页对话界面。相比裸模型直接回答检索问答链的回答以检索到的文档片段为依据能显著降低幻觉、给出更贴合语料内容的答案这一点在第五节的对比测试中会直观体现。二、环境配置依赖安装与模型准备2.1 前置条件本方案建立在 ChatGLM3-6B 已完成本地部署的基础上可先参考 01-ChatGLM3-6B Transformer部署调用.md 完成模型下载与调用验证。教程默认运行环境为 AutoDL 平台模型参数文件存储在本地/root/autodl-tmp/ZhipuAI/chatglm3-6b路径下。2.2 安装知识库相关依赖在已部署 ChatGLM3 的基础上还需要安装以下依赖包pip install langchain0.0.292 pip install gradio4.4.0 pip install chromadb0.4.15 pip install sentence-transformers2.2.2 pip install unstructured0.10.30 pip install markdown3.3.7各依赖的职责如下依赖包版本在本方案中的职责langchain0.0.292提供文档加载器、文本分割器、Embeddings 接口、向量库封装与检索问答链gradio4.4.0搭建 Web 聊天界面chromadb0.4.15向量数据库存储与检索文本向量sentence-transformers2.2.2加载开源词向量模型完成文本向量化unstructured0.10.30文档解析底层依赖支撑UnstructuredFileLoader等加载器markdown3.3.7Markdown 文档解析依赖需要说明的是本教程代码基于langchain0.0.292这一版本编写如langchain.llms.base.LLM、langchain.vectorstores.Chroma、langchain.chains.RetrievalQA等导入路径均为该版本 API。若使用更高版本的 LangChain部分导入路径与接口签名可能发生变化建议按本教程固定版本复现。上述依赖与 ChatGLM3-6B 部署所需依赖transformers、torch 等已一并记录在 models/ChatGLM/requirements.txt 中可据此核对环境。2.3 下载开源词向量模型我们需要使用开源词向量模型 sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2Sentence Transformer 系列的多语言句子嵌入模型对中文支持良好。可以仿照下载 ChatGLM3 模型参数的方式将其下载到本地/root/autodl-tmp/sentence-transformer目录# 在 AutoDL 等平台可先开启学术资源加速再下载 source /etc/network_turbo # 使用 huggingface-cli 或模型下载脚本将模型保存到指定目录 # 下载完成后关闭加速 unset http_proxy unset https_proxy下载完成后HuggingFaceEmbeddings(model_nameautodl-tmp/sentence-transformer)即可直接从本地加载该模型无需联网。2.4 目录与路径约定本节统一约定以下路径后续所有代码均基于这些路径ChatGLM3-6B 模型/root/autodl-tmp/ZhipuAI/chatglm3-6b词向量模型/root/autodl-tmp/sentence-transformer语料仓库根目录/root/autodl-tmp/下的 self-llm、llm-universe、prompt-engineering-for-developers、so-large-lm、hugging-llm向量数据库持久化路径data_base/vector_db/chroma相对当前工作目录三、知识库搭建从原始文档到向量数据库3.1 语料来源Datawhale 系列开源教程本方案选择 Datawhale 的一系列 LLM 开源教程作为语料库来源覆盖大模型使用、应用开发、Prompt 工程、预训练原理等多个维度Self LLM即当前项目 self-llm一个围绕开源大模型、针对国内初学者、基于 AutoDL 平台的开源大模型食用指南涵盖国内外开源 LLM/MLLM 的快速微调全参数/Lora与部署教程LLM Universe面向小白开发者的大模型应用开发教程结合个人知识库助手项目通过一个课程完成大模型开发的重点入门LLM tutorial for Developers面向开发者的 LLM 入门教程基于吴恩达老师大模型系列课程内容实现So Large LLM大规模预训练语言模型教程覆盖数据准备、模型构建、训练策略到模型评估与改进以及模型在安全、隐私、环境和法律道德方面的开源知识Hugging LLM介绍 ChatGPT 原理、使用和应用降低使用门槛让更多非 NLP 或算法专业人士能够无障碍使用 LLM 创造价值。首先将上述远程开源仓库 Clone 到本地以当前 self-llm 仓库为例其余仓库以同样方式克隆到同一目录# 进入到数据库盘 cd /root/autodl-tmp # 打开学术资源加速 source /etc/network_turbo # clone self-llm 仓库 git clone https://gitcode.com/datawhalechina/self-llm.git # 以同样方式克隆 llm-universe、prompt-engineering-for-developers、so-large-lm、hugging-llm 仓库 # 关闭学术资源加速 unset http_proxy unset https_proxy为方便语料处理我们将选用上述仓库中所有的 markdown、txt 文件作为示例语料库。注意也可以选用其中的代码文件加入知识库但需要针对代码文件格式进行额外处理例如为代码文件编写专用的解析器。3.2 递归遍历获取目标文件路径首先定义一个函数递归遍历指定文件夹路径返回其中所有后缀名为.md或.txt的文件路径import os def get_files(dir_path): # argsdir_path目标文件夹路径 file_list [] for filepath, dirnames, filenames in os.walk(dir_path): # os.walk 函数将递归遍历指定文件夹 for filename in filenames: # 通过后缀名判断文件类型是否满足要求 if filename.endswith(.md): # 如果满足要求将其绝对路径加入到结果列表 file_list.append(os.path.join(filepath, filename)) elif filename.endswith(.txt): file_list.append(os.path.join(filepath, filename)) return file_listos.walk会自顶向下遍历目录树返回每个目录下的文件路径、子目录列表与文件列表因此该函数可以一次性收集语料目录树中所有符合条件的文档无需手动罗列文件。3.3 按文件类型加载纯文本内容得到目标文件路径列表后使用 LangChain 提供的 FileLoader 系列对象加载目标文件得到由文件解析出的纯文本内容。由于不同类型的文件需要对应不同的 Loader这里按后缀名分派UnstructuredMarkdownLoader处理.md与UnstructuredFileLoader处理.txt并调用load()方法得到加载后的纯文本对象from tqdm import tqdm from langchain.document_loaders import UnstructuredFileLoader from langchain.document_loaders import UnstructuredMarkdownLoader def get_text(dir_path): # argsdir_path目标文件夹路径 # 首先调用上文定义的函数得到目标文件路径列表 file_lst get_files(dir_path) # docs 存放加载之后的纯文本对象 docs [] # 遍历所有目标文件 for one_file in tqdm(file_lst): file_type one_file.split(.)[-1] if file_type md: loader UnstructuredMarkdownLoader(one_file) elif file_type txt: loader UnstructuredFileLoader(one_file) else: # 如果是不符合条件的文件直接跳过 continue docs.extend(loader.load()) return docstqdm用于在遍历大量文件时展示进度条便于观察加载耗时。最终得到的docs是一个纯文本对象Document列表每个对象既包含文本内容也携带来源元数据可直接进入 LangChain 后续的切分与向量化流程。3.4 文本分块RecursiveCharacterTextSplitter长文档直接向量化会带来两个问题一是单条向量难以精确命中局部语义二是超出模型的上下文窗口。因此需要先分块。LangChain 提供了多种文本分块工具此处使用字符串递归分割器并选择分块大小为 500、块重叠长度为 150from langchain.text_splitter import RecursiveCharacterTextSplitter text_splitter RecursiveCharacterTextSplitter( chunk_size500, chunk_overlap150) split_docs text_splitter.split_documents(docs)参数含义与调优要点chunk_size500每个文本块的目标最大字符数。块越小检索越精细但可能截断完整语义块越大语义越完整但检索精度下降可根据语料特性调整chunk_overlap150相邻块之间的重叠字符数。重叠可以保证被切在边界上的关键信息如一句话被拆到两个块仍能在检索时被完整召回一般取chunk_size的 20%30% 左右为宜。RecursiveCharacterTextSplitter会优先按段落、句子等自然边界递归切分尽可能避免在语义中断处硬切。3.5 向量化并持久化到 Chroma接着选用多语言词向量模型 sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 进行文本向量化。LangChain 提供了直接引入 HuggingFace 开源社区模型的向量化接口HuggingFaceEmbeddings指定本地模型路径即可加载from langchain.embeddings.huggingface import HuggingFaceEmbeddings embeddings HuggingFaceEmbeddings(model_nameautodl-tmp/sentence-transformer)同时选择 Chroma 作为向量数据库。基于上文分块后的文档以及加载的向量化模型将语料写入指定路径下的向量数据库并通过persist()持久化到磁盘from langchain.vectorstores import Chroma # 定义持久化路径 persist_directory data_base/vector_db/chroma # 加载数据库 vectordb Chroma.from_documents( documentssplit_docs, embeddingembeddings, persist_directorypersist_directory # 允许我们将persist_directory目录保存到磁盘上 ) # 将加载的向量数据库持久化到磁盘上 vectordb.persist()Chroma.from_documents会依次完成调用 embeddings 对每个文本块编码 → 写入向量库 → 关联持久化目录三个动作。运行一次后向量数据已固化在data_base/vector_db/chroma目录后续应用启动时直接加载该目录即可无需重复构建详见第五节。3.6 整合为 create_db.py 一键脚本将上述步骤整合为知识库搭建的完整脚本与仓库中的 create_db.py 一致# 首先导入所需第三方库 from langchain.document_loaders import UnstructuredFileLoader from langchain.document_loaders import UnstructuredMarkdownLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.vectorstores import Chroma from langchain.embeddings.huggingface import HuggingFaceEmbeddings from tqdm import tqdm import os # 获取文件路径函数 def get_files(dir_path): # argsdir_path目标文件夹路径 file_list [] for filepath, dirnames, filenames in os.walk(dir_path): # os.walk 函数将递归遍历指定文件夹 for filename in filenames: # 通过后缀名判断文件类型是否满足要求 if filename.endswith(.md): # 如果满足要求将其绝对路径加入到结果列表 file_list.append(os.path.join(filepath, filename)) elif filename.endswith(.txt): file_list.append(os.path.join(filepath, filename)) return file_list # 加载文件函数 def get_text(dir_path): # argsdir_path目标文件夹路径 # 首先调用上文定义的函数得到目标文件路径列表 file_lst get_files(dir_path) # docs 存放加载之后的纯文本对象 docs [] # 遍历所有目标文件 for one_file in tqdm(file_lst): file_type one_file.split(.)[-1] if file_type md: loader UnstructuredMarkdownLoader(one_file) elif file_type txt: loader UnstructuredFileLoader(one_file) else: # 如果是不符合条件的文件直接跳过 continue docs.extend(loader.load()) return docs # 目标文件夹 tar_dir [ /root/autodl-tmp/self-llm, /root/autodl-tmp/llm-universe, /root/autodl-tmp/prompt-engineering-for-developers, /root/autodl-tmp/so-large-lm, /root/autodl-tmp/hugging-llm, ] # 加载目标文件 docs [] for dir_path in tar_dir: docs.extend(get_text(dir_path)) # 对文本进行分块 text_splitter RecursiveCharacterTextSplitter( chunk_size500, chunk_overlap150) split_docs text_splitter.split_documents(docs) # 加载开源词向量模型 embeddings HuggingFaceEmbeddings(model_nameautodl-tmp/sentence-transformer) # 构建向量数据库 # 定义持久化路径 persist_directory data_base/vector_db/chroma # 加载数据库 vectordb Chroma.from_documents( documentssplit_docs, embeddingembeddings, persist_directorypersist_directory # 允许我们将persist_directory目录保存到磁盘上 ) # 将加载的向量数据库持久化到磁盘上 vectordb.persist()运行上述脚本即可在本地构建已持久化的向量数据库。这里有一处实践细节值得注意仓库中的 create_db.py 在加载词向量模型时使用的是绝对路径/root/autodl-tmp/sentence-transformer而文档正文使用相对路径写法autodl-tmp/sentence-transformer两者指向同一目录实际部署时建议统一使用绝对路径避免因脚本运行目录不同导致模型加载失败。脚本执行完毕后后续应用直接导入该数据库即可无需重复构建。四、自定义 LLM 类将 ChatGLM3-6B 接入 LangChain为便捷构建 LLM 应用需要基于本地部署的 ChatGLM3-6B 自定义一个 LLM 类将 ChatGLM 接入 LangChain 框架。完成自定义 LLM 类之后可以以完全一致的方式调用 LangChain 的接口而无需考虑底层模型调用的不一致。基于本地部署的 ChatGLM3-6B 自定义 LLM 类并不复杂只需从langchain.llms.base.LLM继承一个子类并重写构造函数与_call函数即可。该类的完整实现见仓库中的 LLM.pyfrom langchain.llms.base import LLM from typing import Any, List, Optional from langchain.callbacks.manager import CallbackManagerForLLMRun from transformers import AutoTokenizer, AutoModelForCausalLM import torch class ChatGLM_LLM(LLM): # 基于本地 ChatGLM3-6B 自定义 LLM 类 tokenizer : AutoTokenizer None model: AutoModelForCausalLM None def __init__(self, model_path :str): # model_path: ChatGLM 模型路径 # 从本地初始化模型 super().__init__() print(正在从本地加载模型...) self.tokenizer AutoTokenizer.from_pretrained(model_path, trust_remote_codeTrue) self.model AutoModelForCausalLM.from_pretrained(model_path, trust_remote_codeTrue).to(torch.bfloat16).cuda() self.model self.model.eval() print(完成本地模型的加载) def _call(self, prompt : str, stop: Optional[List[str]] None, run_manager: Optional[CallbackManagerForLLMRun] None, **kwargs: Any): # 重写调用函数 response, history self.model.chat(self.tokenizer, prompt , history[]) return response property def _llm_type(self) - str: return ChatGLM3-6B核心要点解读构造函数__init__在对象实例化的一开始加载本地部署的 ChatGLM3-6B 模型从而避免每一次调用都重新加载模型带来的时间开销。trust_remote_codeTrue允许加载 ChatGLM3 自定义的模型代码.to(torch.bfloat16).cuda()以 bf16 精度将模型加载到 GPU.eval()切换到推理模式关闭 dropout 等训练期行为_call函数这是 LLM 类的核心函数LangChain 在调用 LLM 时会调用该方法。这里调用已实例化模型的chat方法即 ChatGLM3 的对话接口传入 prompt 与空的历史记录返回生成的回答文本_llm_type属性返回模型类型的标识字符串供 LangChain 内部识别与日志展示使用。源码中类内注释沿用了 InternLM 教程模板中的基于本地 InternLM 自定义 LLM 类字样实际服务对象是本地部署的 ChatGLM3-6B功能上不影响使用读者阅读时可留意此历史遗留注释。在整体项目中上述代码被封装为LLM.py后续直接以from LLM import ChatGLM_LLM的方式引入自定义 LLM 类。五、构建检索问答链RAG 全流程封装LangChain 通过提供检索问答链对象实现对 RAG 全流程的封装调用一个 LangChain 提供的RetrievalQA对象在初始化时填入已构建的数据库和自定义 LLM 作为参数即可简便完成检索增强问答的全流程。LangChain 会自动完成基于用户提问进行检索 → 获取相关文档 → 拼接为合适的 Prompt → 交给 LLM 问答的全部流程。5.1 加载已构建的向量数据库首先将第三节构建的向量数据库导入进来。直接通过Chroma与上文的词向量模型加载已构建的数据库目录from langchain.vectorstores import Chroma from langchain.embeddings.huggingface import HuggingFaceEmbeddings import os # 定义 Embeddings embeddings HuggingFaceEmbeddings(model_nameautodl-tmp/sentence-transformer) # 向量数据库持久化路径 persist_directory data_base/vector_db/chroma # 加载数据库 vectordb Chroma( persist_directorypersist_directory, embedding_functionembeddings )注意这里使用的是Chroma(...)构造函数而非Chroma.from_documents因为数据库已经构建并持久化只需按路径加载即可。得到的vectordb对象即为已构建的向量数据库对象它可以针对用户的query进行语义向量检索得到与用户提问相关的知识片段。5.2 实例化自定义 LLM 并验证接着实例化基于 ChatGLM3-6B 自定义的 LLM 对象from LLM import ChatGLM_LLM llm ChatGLM_LLM(model_path autodl-tmp/ZhipuAI/chatglm3-6b) llm.predict(你是谁)llm.predict(你是谁)用于验证自定义 LLM 是否正常工作若正常则会返回模型的自我介绍式回答。这一步在构建问答链前完成可以快速隔离问题——先确认模型调用通再排查检索环节。5.3 设计 Prompt Template构建检索问答链还需要一个 Prompt Template。该 Template 本质是一个带变量的字符串在检索之后LangChain 会将检索到的相关文档片段填入 Template 的变量中从而实现带知识的 Prompt构建。基于 LangChain 的 Template 基类实例化from langchain.prompts import PromptTemplate # 我们所构造的 Prompt 模板 template 使用以下上下文来回答最后的问题。如果你不知道答案就说你不知道不要试图编造答案。尽量使答案简明扼要。总是在回答的最后说“谢谢你的提问”。 {context} 问题: {question} 有用的回答: # 调用 LangChain 的方法来实例化一个 Template 对象该对象包含了 context 和 question 两个变量在实际调用时这两个变量会被检索到的文档片段和用户提问填充 QA_CHAIN_PROMPT PromptTemplate(input_variables[context,question],templatetemplate)模板设计有三个要点其一通过{context}占位符注入检索到的文档片段其二通过{question}占位符注入用户提问其三通过如果你不知道答案就说你不知道不要试图编造答案约束模型在语料中找不到依据时不要强行编造从而缓解幻觉。5.4 组装 RetrievalQA 问答链最后调用 LangChain 提供的检索问答链构造函数基于自定义 LLM、Prompt Template 和向量知识库构建检索问答链from langchain.chains import RetrievalQA qa_chain RetrievalQA.from_chain_type(llm,retrievervectordb.as_retriever(),return_source_documentsTrue,chain_type_kwargs{prompt:QA_CHAIN_PROMPT})参数说明llm自定义的 ChatGLM3-6B LLM 对象负责最终的答案生成retrievervectordb.as_retriever()将向量数据库转换为检索器。as_retriever()默认按相似度返回 top-k 个相关文档块k 默认为 4后续可基于此做检索参数调优return_source_documentsTrue在结果中同时返回命中的源文档片段便于排查回答依据与后续展示chain_type_kwargs{prompt: QA_CHAIN_PROMPT}将自定义 Prompt 模板注入问答链替换默认 Prompt。得到的qa_chain对象即可实现核心功能——基于 ChatGLM3-6B 模型的专业知识库助手。5.5 对比测试知识库问答 vs 裸模型问答可以对比检索问答链与纯 LLM 的问答效果# 检索问答链回答效果 question 什么是 Self LLM result qa_chain({query: question}) print(检索问答链回答 question 的结果) print(result[result]) # 仅 LLM 回答效果 result_2 llm(question) print(大模型回答 question 的结果) print(result_2)qa_chain({query: question})返回一个字典其中result键为最终答案source_documents键为命中的源文档。由于 self-llm 仓库本身的教程文档已作为语料入库检索问答链对什么是 Self LLM这类问题的回答将以仓库文档内容为依据展开而纯 LLM 回答仅依赖模型内部参数化知识无法精确引用语料内容。两种回答的差异正是检索增强带来的核心价值。六、部署 Web Demo基于 Gradio 的对话界面在完成核心功能后可以基于 Gradio 框架将其部署到 Web 网页搭建一个小型 Demo便于测试与使用。完整代码见仓库中的 run_gradio.py。6.1 封装问答链加载函数首先将上文代码封装为一个返回检索问答链对象的函数并在启动 Gradio 的第一时间调用该函数得到检索问答链对象后续直接使用该对象进行问答对话从而避免重复加载模型from langchain.vectorstores import Chroma from langchain.embeddings.huggingface import HuggingFaceEmbeddings import os from LLM import ChatGLM_LLM from langchain.prompts import PromptTemplate from langchain.chains import RetrievalQA def load_chain(): # 加载问答链 # 定义 Embeddings embeddings HuggingFaceEmbeddings(model_nameautodl-tmp/sentence-transformer) # 向量数据库持久化路径 persist_directory data_base/vector_db/chroma # 加载数据库 vectordb Chroma( persist_directorypersist_directory, # 允许我们将persist_directory目录保存到磁盘上 embedding_functionembeddings ) # 加载自定义 LLM llm ChatGLM_LLM(model_path autodl-tmp/ZhipuAI/chatglm3-6b) # 定义一个 Prompt Template template 使用以下上下文来回答最后的问题。如果你不知道答案就说你不知道不要试图编造答案。尽量使答案简明扼要。总是在回答的最后说“谢谢你的提问”。 {context} 问题: {question} 有用的回答: QA_CHAIN_PROMPT PromptTemplate(input_variables[context,question],templatetemplate) # 运行 chain qa_chain RetrievalQA.from_chain_type(llm,retrievervectordb.as_retriever(),return_source_documentsTrue,chain_type_kwargs{prompt:QA_CHAIN_PROMPT}) return qa_chain该函数一次性完成加载词向量模型 → 加载向量数据库 → 加载 ChatGLM3-6B → 组装 Prompt → 组装问答链的全部初始化动作返回值即就绪的qa_chain。6.2 设计 Model_center 核心类接着定义一个类负责加载并存储检索问答链并响应 Web 界面中调用检索问答链进行回答的动作class Model_center(): 存储检索问答链的对象 def __init__(self): # 构造函数加载检索问答链 self.chain load_chain() def qa_chain_self_answer(self, question: str, chat_history: list []): 调用问答链进行回答 if question None or len(question) 1: return , chat_history try: chat_history.append( (question, self.chain({query: question})[result])) # 将问答结果直接附加到问答历史中Gradio 会将其展示出来 return , chat_history except Exception as e: return e, chat_historyModel_center在构造函数中完成问答链的加载与缓存确保模型只加载一次qa_chain_self_answer负责接收用户问题、调用问答链、把(问题, 回答)二元组追加到聊天历史中并将异常兜底展示在输入框避免页面直接崩溃。6.3 搭建 Gradio 聊天界面按照 Gradio 的框架使用方法实例化一个 Web 界面并将点击动作绑定到上述类的回答方法import gradio as gr # 实例化核心功能对象 model_center Model_center() # 创建一个 Web 界面 block gr.Blocks() with block as demo: with gr.Row(equal_heightTrue): with gr.Column(scale15): # 展示的页面标题 gr.Markdown(h1centerSelf LLM/center/h1 centerSelf LLM/center ) with gr.Row(): with gr.Column(scale4): # 创建一个聊天机器人对象 chatbot gr.Chatbot(height450, show_copy_buttonTrue) # 创建一个文本框组件用于输入 prompt。 msg gr.Textbox(labelPrompt/问题) with gr.Row(): # 创建提交按钮。 db_wo_his_btn gr.Button(Chat) with gr.Row(): # 创建一个清除按钮用于清除聊天机器人组件的内容。 clear gr.ClearButton( components[chatbot], valueClear console) # 设置按钮的点击事件。当点击时调用上面定义的 qa_chain_self_answer 函数并传入用户的消息和聊天历史记录然后更新文本框和聊天机器人组件。 db_wo_his_btn.click(model_center.qa_chain_self_answer, inputs[ msg, chatbot], outputs[msg, chatbot]) gr.Markdown(提醒br 1. 初始化数据库时间可能较长请耐心等待。 2. 使用中如果出现异常将会在文本输入框进行展示请不要惊慌。 br ) gr.close_all() # 直接启动 demo.launch()界面组件与事件流的对应关系gr.Chatbot聊天机器人展示组件height450设定高度show_copy_buttonTrue允许复制回答gr.Textbox用户输入框label 为Prompt/问题gr.Button(Chat)提交按钮通过.click(model_center.qa_chain_self_answer, inputs[msg, chatbot], outputs[msg, chatbot])将点击事件绑定到回答方法输入为用户消息与聊天历史输出回写输入框与聊天组件gr.ClearButton一键清空聊天记录。6.4 启动与访问将上述代码封装为run_gradio.py脚本后直接运行python run_gradio.py即可在本地启动知识库助手的 Web Demo默认在 7860 端口运行。由于 ChatGLM3-6B 与向量数据库均在首次启动时加载初始化阶段耗时较长属正常现象。在 AutoDL 等云服务器上使用类似于部署模型的方式将服务器 7860 端口映射到本地端口如通过 AutoDL 的开放端口功能参见 02-AutoDL开放端口.md即可在浏览器中访问如上图所示界面标题为 Self LLM用户提出Self LLM 项目是干什么的后助手结合知识库中该项目的教程语料给出了关于项目目标、技术方向的详细回答——这正是检索增强问答在真实场景下的运行效果。七、工程落地脚本文件与运行流程总结本方案共包含三个脚本均位于 05-ChatGLM3-6B接入LangChain搭建知识库助手 目录下脚本文件对应章节职责create_db.py第三节遍历语料、加载文本、分块、向量化并持久化到 ChromaLLM.py第四节将本地 ChatGLM3-6B 封装为 LangChain 自定义 LLM 类run_gradio.py第五、六节加载向量库与自定义 LLM组装 RetrievalQA启动 Gradio Web Demo推荐运行顺序参照第二节完成依赖安装与模型下载ChatGLM3-6B 与词向量模型运行create_db.py构建并持久化向量数据库只需执行一次运行run_gradio.py启动 Web Demo在浏览器中测试问答效果。若更换语料例如替换为个人文档目录只需调整create_db.py中的tar_dir列表后重新构建数据库即可问答链代码无需改动。如需将本方案扩展到其他模型可参考仓库中同主题的其他实现例如 Qwen-7B-Chat 接入langchain搭建知识库助手 等整体架构一致仅需替换自定义 LLM 类的内部调用逻辑。八、常见问题与优化方向1. 初始化/加载耗时过长run_gradio.py启动时需要依次加载词向量模型、向量数据库与 ChatGLM3-6B 大模型首次启动耗时较长。这是正常现象界面中也已给出提示可通过减少语料规模或先运行create_db.py预构建数据库来缩短启动流程。2. 分块参数如何调优chunk_size500与chunk_overlap150是经验取值。若回答答非所问可适当减小chunk_size提升检索粒度若回答上下文断裂可增大chunk_overlap保留跨块语义。修改后需重新运行create_db.py重建数据库。3. 检索结果相关性不理想可从三个方向排查其一检查词向量模型是否支持中文paraphrase-multilingual-MiniLM-L12-v2 为多语言模型支持中文其二调整vectordb.as_retriever()的search_kwargs如增大k值召回更多候选块其三优化 Prompt 模板中对上下文使用的引导。4. 想加入代码文件作为语料当前get_files仅收集.md与.txt文件文档中已说明可以选用代码文件加入知识库但需要针对代码文件格式进行额外处理如使用专门的代码加载器或对代码块做格式清理否则解析出的纯文本噪声较大会影响检索质量。5. LangChain 版本兼容本文代码基于langchain0.0.292参见 requirements.txt。LangChain 高版本中langchain.llms.base.LLM、langchain.vectorstores、langchain.chains等导入路径均有调整若升级版本需同步迁移自定义 LLM 类的继承基类与问答链的组装方式。通过以上八个环节你已经可以从零构建一个基于 ChatGLM3-6B 与 LangChain 的私有知识库助手语料入库、语义检索、增强问答与 Web 化展示一条链路全部打通。将create_db.py的语料目录替换为任意自有文档即可把本方案快速迁移到团队文档问答、产品手册答疑等真实场景中。【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/datawhalechina/self-llm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考