资讯动态

Atom-7B-Chat 接入 LangChain 搭建知识库助手:从向量库构建到 Gradio 部署的 RAG 实战

发布时间:2026/9/12 3:14:43 来源:尧图企业网站定制
Atom-7B-Chat 接入 LangChain 搭建知识库助手从向量库构建到 Gradio 部署的 RAG 实战【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm本篇指南基于 self-llm 仓库中《Atom-7B-Chat 接入 langchain 搭建知识库助手》教程整理讲解如何在单机 GPU24G 显存级别环境下将国产大模型 Atom-7B-Chat 通过自定义 LLM 类接入 LangChain使用 Chroma 向量库 多语言 Sentence Transformer 嵌入模型完成 RAG检索增强生成知识库建设并最终用 Gradio 部署为可交互的 Web 问答 Demo。读完后你可以独立复现依赖安装与模型下载、语料加载/分块/向量化全流程、自定义 LLM 封装、RetrievalQA 问答链构建以及带知识库的 Web 助手上线。配套的可运行代码集中在 03-Atom-7B-Chat 接入langchain搭建知识库助手/ 目录creat_db.py构建并持久化 Chroma 向量数据库的脚本LLM.py将 Atom-7B-Chat 封装为 LangChain 自定义 LLM 类的脚本run_gradio.py启动 Gradio Web Demo 的脚本。一、环境准备教程推荐在 AutoDL 平台租用一块 3090 等 24G 显存的 GPU 机器Atom-7B-Chat 全精度加载 嵌入模型24G 显存较为从容镜像选择 PyTorch → 2.0.0 → Python 3.8 (Ubuntu 20.04) → CUDA 11.8。租好机器后打开 JupyterLab 的终端进行后续操作。先升级 pip 并更换国内镜像源加速依赖安装# 升级pip python -m pip install --upgrade pip # 更换 pypi 源加速库的安装 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple pip install modelscope1.9.5 pip install transformers4.32.0 accelerate tiktoken einops scipy transformers_stream_generator0.0.4 peft deepspeed pip install -U huggingface_hub pip install -i https://test.pypi.org/simple/ bitsandbytes这一组依赖服务于底层模型加载modelscope用于从 ModelScope 拉取模型权重transformers4.32.0 以上accelerate支持device_mapauto的设备映射加载bitsandbytes支持 8bit 量化加载以进一步压缩显存。在已部署 Atom-7B-Chat 的基础上模型加载方式可参考 01-Atom-7B-chat-WebDemo.md还需要安装 RAG 应用栈依赖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其中chromadb是向量数据库后端sentence-transformers承载嵌入模型推理unstructured提供文档解析加载器本教程用到UnstructuredMarkdownLoader/UnstructuredFileLoadermarkdown是 unstructured 解析 md 文件的配套依赖gradio用于最后的 Web Demo。二、模型下载嵌入模型与 Atom-7B-Chat 本体2.1 下载多语言嵌入模型知识库方案使用开源嵌入模型sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2多语言 MiniLM适合中文语料向量化。由于 huggingface 直连在国内环境不稳定教程通过 hf-mirror 镜像下载。在/root/autodl-tmp路径下新建download.pyimport os # 设置环境变量 os.environ[HF_ENDPOINT] https://hf-mirror.com # 下载模型 os.system(huggingface-cli download --resume-download sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 --local-dir /root/autodl-tmp/embedding_model)运行python /root/autodl-tmp/download.py后嵌入模型落盘到/root/autodl-tmp/embedding_model后续HuggingFaceEmbeddings将以本地路径方式加载它。2.2 下载 Atom-7B-Chat 模型权重使用 ModelScope 的snapshot_download函数下载模型第一个参数为模型名称cache_dir参数为模型下载路径。同样新建download.pyimport torch from modelscope import snapshot_download, AutoModel, AutoTokenizer import os model_dir snapshot_download(FlagAlpha/Atom-7B-Chat, cache_dir/root/autodl-tmp, revisionmaster)运行python /root/autodl-tmp/download.py执行下载。模型大小约 13 GB下载时间大约 10~20 分钟。下载完成后模型位于/root/autodl-tmp/FlagAlpha/Atom-7B-Chat这也是后续 LLM 封装类中model_dir的取值。三、知识库建设语料加载、分块与向量化3.1 准备知识库语料教程选用两个开源仓库的文档作为知识库来源Atom-7B-Chat 模型仓库的文档以及 FlagAlpha/Llama2-Chinese 仓库。先将其 Clone 到本地数据盘# 进入到数据盘 cd /root/autodl-tmp # 打开学术资源加速 source /etc/network_turbo # clone 开源仓库 git clone https://github.com/FlagAlpha/Llama2-Chinese # 关闭学术资源加速 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_list3.3 按文件类型选择 FileLoader不同类型文件需要对应不同的 LangChain FileLoader。按后缀名判断并针对性调用对应类型的 Loader再调用 Loader 的load方法得到解析后的纯文本 Document 列表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 docsUnstructuredMarkdownLoader依赖markdown包把 md 文件还原为带结构的元素序列UnstructuredFileLoader处理普通 txt两者都基于 unstructured 解析这也是依赖列表里要装unstructured0.10.30和markdown3.3.7的原因。3.4 文本分块与向量化入库从纯文本对象构建向量数据库需要先分块再向量化。教程选用 LangChain 的字符串递归分割器RecursiveCharacterTextSplitter分块大小 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让相邻块保留重叠内容避免语义在块边界被生硬截断——这两个值是 RAG 效果调优中最直接的抓手。接着选用上文下载的开源嵌入模型进行文本向量化。LangChain 提供了直接引入 HuggingFace 模型的向量化接口from langchain.embeddings.huggingface import HuggingFaceEmbeddings embeddings HuggingFaceEmbeddings(model_name/root/autodl-tmp/embedding_model)最后选择 Chroma 作为向量数据库将分块后的文档与嵌入模型一起写入指定路径并持久化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()3.5 完整建库脚本将上述代码整合在一起即为仓库中 creat_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 import nltk nltk.download(punkt) # 获取文件路径函数 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/Llama2-Chinese, ] # 加载目标文件 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_name/root/autodl-tmp/embedding_model) # 构建向量数据库 # 定义持久化路径 persist_directory data_base/vector_db/chroma # 加载数据库 vectordb Chroma.from_documents( documentssplit_docs, embeddingembeddings, persist_directorypersist_directory # 允许我们将persist_directory目录保存到磁盘上 ) # 将加载的向量数据库持久化到磁盘上 vectordb.persist()脚本中有两个值得注意的细节开头nltk.download(punkt)预先下载 unstructured 分句所需的数据包避免运行中联网拉取失败tar_dir是列表结构后续要扩充语料只需追加目录路径。运行脚本后即可在本地得到已持久化的向量数据库后续直接导入即可无需重复构建。四、Atom 接入 LangChain自定义 LLM 类为便捷构建 LLM 应用需要基于本地部署的 Atom 自定义一个 LLM 类接入 LangChain 框架。完成封装后可以以完全一致的方式调用 LangChain 接口而无需关心底层模型调用的差异。实现并不复杂从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 Atom(LLM): # 基于本地 Atom 自定义 LLM 类 tokenizer : AutoTokenizer None model: AutoModelForCausalLM None def __init__(self, model_path :str): # model_path: Atom 模型路径 # 从本地初始化模型 super().__init__() print(正在从本地加载模型...) model_dir /root/autodl-tmp/FlagAlpha/Atom-7B-Chat self.tokenizer AutoTokenizer.from_pretrained(model_dir, trust_remote_codeTrue) self.model AutoModelForCausalLM.from_pretrained(model_dir, device_mapauto, trust_remote_codeTrue,torch_dtypetorch.float16,load_in_8bitTrue).eval() print(完成本地模型的加载) def _call(self, prompt: str, stop: Optional[List[str]] None, run_manager: Optional[CallbackManagerForLLMRun] None, **kwargs: Any): input_ids self.tokenizer([fsHuman: {prompt}\n/ssAssistant: ], return_tensorspt, add_special_tokensFalse).input_ids.to(cuda) generate_input { input_ids: input_ids, max_new_tokens: 512, do_sample: True, top_k: 50, top_p: 0.95, temperature: 0.3, repetition_penalty: 1.3, eos_token_id: self.tokenizer.eos_token_id, bos_token_id: self.tokenizer.bos_token_id, pad_token_id: self.tokenizer.pad_token_id } generate_ids self.model.generate(**generate_input) text self.tokenizer.decode(generate_ids[0]) return text property def _llm_type(self) - str: return Atom两个重写点的设计意图构造函数在对象实例化之初就加载本地 Atom 模型AutoTokenizer/AutoModelForCausalLM避免每次调用都重新加载权重带来的巨大时间开销。加载参数上device_mapauto让 accelerate 自动把权重铺到 GPUtorch_dtypetorch.float16以半精度降低显存占用load_in_8bitTrue再叠加 bitsandbytes 的 8bit 量化进一步压缩显存trust_remote_codeTrue是因为 Atom 使用自定义建模代码。仓库中 LLM.py 的参考实现未加load_in_8bit仅用torch.float16加载24G 显存下同样可行两种配置可按显存量选择_call方法这是LLM基类的核心抽象LangChain 统一通过它来调用模型。这里先按 Atom 的对话格式sHuman: {prompt}\n/ssAssistant:构造 prompt 并编码为 input_ids再调用model.generate生成。采样参数max_new_tokens512、top_k50、top_p0.95、temperature0.3、repetition_penalty1.3与 Atom-7B-Chat 官方 WebDemo 的推荐生成配置一致低温度 重复惩罚适合知识库问答这类追求准确、稳定输出的场景。从源码结构看_llm_type属性只是 LangChain 要求的标识性接口返回 Atom 用于类型识别。五、构建检索问答链RetrievalQALangChain 通过检索问答链对象封装 RAG 全流程只需初始化一个RetrievalQA对象并填入向量库和自定义 LLM它会自动完成“用户提问 → 向量检索 → 取相关文档 → 拼接 Prompt → 交给 LLM 作答”的全部环节。5.1 加载已持久化的向量库直接用 Chroma 与嵌入模型加载已构建的数据库from langchain.vectorstores import Chroma from langchain.embeddings.huggingface import HuggingFaceEmbeddings import os # 定义 Embeddings embeddings HuggingFaceEmbeddings(model_name/root/autodl-tmp/embedding_model) # 向量数据库持久化路径 persist_directory data_base/vector_db/chroma # 加载数据库 vectordb Chroma( persist_directorypersist_directory, embedding_functionembeddings )得到的vectordb对象即可针对用户 query 做语义向量检索取出与提问相关的知识片段。5.2 实例化 Atom LLM 并验证from LLM import Atom llm Atom(model_path /root/autodl-tmp/FlagAlpha/Atom-7B-Chat) llm.predict(你是谁)5.3 构建 Prompt Template检索问答链还需要一个 Prompt Template本质是一个带变量的字符串检索之后 LangChain 会把相关文档片段填入{context}变量、用户提问填入{question}变量从而生成带知识的 Promptfrom langchain.prompts import PromptTemplate # 我们所构造的 Prompt 模板 template 使用以下上下文来回答最后的问题。如果你不知道答案就说你不知道不要试图编造答案。尽量使答案简明扼要。总是在回答的最后说“谢谢你的提问”。 {context} 问题: {question} 有用的回答: # 调用 LangChain 的方法来实例化一个 Template 对象该对象包含了 context 和 question 两个变量在实际调用时这两个变量会被检索到的文档片段和用户提问填充 QA_CHAIN_PROMPT PromptTemplate(input_variables[context,question],templatetemplate)模板中“不知道答案就说不知道不要编造”的约束是抑制 RAG 场景下模型幻觉的关键设计。5.4 组装问答链并对比效果最后基于自定义 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})return_source_documentsTrue让结果里附带检索到的原始文档片段便于溯源调试。得到qa_chain后即可实现基于 Atom 的专业知识库助手。可以对比检索问答链与纯 LLM 的问答效果question 什么是Atom result qa_chain({query: question}) print(检索问答链回答 question 的结果) print(result[result]) # 仅 LLM 回答效果 result_2 llm(question) print(大模型回答 question 的结果) print(result_2)可以看到使用检索问答链生成的答案更贴近知识库里的内容如 Atom 的数据来源、中文优化、32K 上下文扩展等均来自语料而纯 LLM 的回答则带有明显的常识性偏差。六、部署 Gradio WebDemo核心功能完成后用 Gradio 把它部署成 Web 页面方便测试与使用。仓库中的 run_gradio.py 完整实现了这一层分为三部分。第一部分load_chain函数。封装“加载向量库 实例化 Atom 构建 PromptTemplate 组装 RetrievalQA”的完整流程返回问答链对象。在启动 Gradio 的第一时间调用该函数后续直接复用该对象进行问答避免重复加载模型# 导入必要的库 import gradio as gr from langchain.vectorstores import Chroma from langchain.embeddings.huggingface import HuggingFaceEmbeddings import os from LLM import Atom from langchain.prompts import PromptTemplate def load_chain(): # 加载问答链 # 定义 Embeddings embeddings HuggingFaceEmbeddings(model_name/root/autodl-tmp/embedding_model) # 向量数据库持久化路径 persist_directory data_base/vector_db/chroma # 加载数据库 vectordb Chroma( persist_directorypersist_directory, # 允许我们将persist_directory目录保存到磁盘上 embedding_functionembeddings ) llm Atom(model_path /root/autodl-tmp/FlagAlpha) template 使用以下上下文来回答最后的问题。如果你不知道答案就说你不知道不要试图编造答 案。尽量使答案简明扼要。总是在回答的最后说“谢谢你的提问”。 {context} 问题: {question} 有用的回答: QA_CHAIN_PROMPT PromptTemplate(input_variables[context,question], templatetemplate) # 运行 chain 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}) return qa_chain第二部分Model_center类。负责持有问答链实例并响应 Web 界面的问答请求class Model_center(): 存储问答 Chain 的对象 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])) return , chat_history except Exception as e: return e, chat_history def clear_history(self): self.chain.clear_history()qa_chain_self_answer的签名返回空字符串 新历史是与 Gradio 组件的inputs/outputs一一对应的它既清空输入框又追加新的对话轮次异常会被捕获并回显到输入框便于定位问题。第三部分Gradio 界面组装。实例化 Blocks 界面并把点击事件绑定到上述方法import gradio as gr model_center Model_center() block gr.Blocks() with block as demo: with gr.Row(equal_heightTrue): with gr.Column(scale15): gr.Markdown(h1centerAtom/center/h1 centerLlama2-chinese(教程来自DataWhale Self-LM团队)/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]) # 点击后清空后端存储的聊天记录 clear.click(model_center.clear_history) gr.Markdown(提醒br 1. 初始化数据库时间可能较长请耐心等待。 2. 使用中如果出现异常将会在文本输入框进行展示请不要惊慌。 br ) # threads to consume the request gr.close_all() # 启动新的 Gradio 应用设置分享功能为 True并使用环境变量 PORT1 指定服务器端口。 # demo.launch(shareTrue, server_portint(os.environ[PORT1])) # 直接启动 demo.launch()将上述代码保存为run_gradio.py在终端执行python run_gradio.py即可启动 Web Demo默认运行在 7860 端口。远程环境下使用类似端口映射的方式把服务器 7860 端口映射到本地即可访问界面效果如下七、小结与复现要点整套方案的分层结构很清晰creat_db.py离线建库可重复构建语料后重新执行LLM.py负责模型与 LangChain 的解耦封装run_gradio.py负责在线服务三者通过两个约定串联——本地嵌入模型路径/root/autodl-tmp/embedding_model与向量库持久化目录data_base/vector_db/chroma。复现时需要注意几个前提显存Atom-7B-Chat 以 fp16可叠加 8bit加载建议 24G 显存级别版本一致性教程基于langchain0.0.292等固定版本HuggingFaceEmbeddings、Chroma.from_documents等 API 形态与当前 LangChain 新版存在差异若升级依赖需对照新版 API 调整建库是一次性动作vectordb.persist()之后问答侧只需Chroma(persist_directory..., embedding_function...)加载不重嵌入路径替换所有/root/autodl-tmp前缀是 AutoDL 数据盘约定本地或其他环境请整体替换为自己的模型与数据目录。按此流程完成配置后就得到了一个可以基于自有语料问答、带来源约束的 Atom 知识库助手。小提示仓库 03 目录 readme 中对LLM.py的文件说明写成了 InternLM属于文档沿袭笔误以实际代码内容Atom 封装类为准。【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价