ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

LLaMA3-8B-Instruct 接入 LangChain:基于 self-llm 自定义 LLM 类的本地化集成实战指南

2026/9/12 18:40:30 拓冰建站 浏览量
LLaMA3-8B-Instruct 接入 LangChain:基于 self-llm 自定义 LLM 类的本地化集成实战指南 LLaMA3-8B-Instruct 接入 LangChain基于 self-llm 自定义 LLM 类的本地化集成实战指南【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm导读本文基于《开源大模型食用指南》仓库self-llm中 02-LLaMA3-8B-Instruct langchain 接入 一文系统讲解如何在本地部署的 Meta-Llama-3-8B-Instruct 基础上通过继承langchain.llms.base.LLM自定义 LLM 类将 LLaMA3 无缝接入 LangChain 框架。读完本文你将掌握从 AutoDL 环境准备、ModelScope 模型下载到自定义 LLM 类的完整实现、对话模板chat template手工构造以及基于 LangChain 统一接口调用本地大模型的完整方案为后续构建知识库问答、Agent 等 LangChain 应用打下基础。一、方案总览为什么要自定义 LLM 类接入 LangChainLangChain 之所以能成为当下最流行的 LLM 应用开发框架之一核心在于它对模型调用这一环节做了高度抽象无论底层是 OpenAI 等云端 API还是本地部署的开源模型在 LangChain 中最终都以统一的LLM接口对外呈现。应用层代码只依赖这一接口不关心底层是 HTTP 请求还是 GPU 推理。但 LLaMA3-8B-Instruct 是本地部署的开源模型LangChain 官方并不内置它的封装。因此为了让 LLaMA3 能够以完全一致的方式调用 LangChain 的接口而无需考虑底层模型调用的不一致我们需要基于本地部署的 LLaMA3 自定义一个 LLM 类。这个方案的核心思路并不复杂从langchain.llms.base.LLM类继承一个子类并重写构造函数与_call函数。构造函数负责在对象实例化时加载本地模型避免每次调用都重新加载模型导致耗时过长_call函数是 LLM 类的核心LangChain 会调用它来真正触发模型推理并返回结果。这一设计模式在仓库中具有通用性——例如 ChatGLM 知识库助手 LLM.py 与 Qwen 知识库助手 LLM.py 均采用同样的继承与重写结构只是将_call内部替换为各自模型的chat调用。二、环境准备2.1 租用 GPU 服务器本教程基于 AutoDL 平台建议租赁一张 3090 等24G 显存的显卡机器。创建实例时镜像选择如下组合框架PyTorch版本2.1.0Python 版本3.10 (ubuntu22.04)CUDA 版本12.1创建完成后打开 JupyterLab并开启其中的终端后续的环境配置、模型下载和代码运行都在该终端中进行。2.2 安装依赖考虑到国内网络环境建议先升级 pip 并切换清华 PyPI 源以加速依赖安装# 升级pip python -m pip install --upgrade pip # 更换 pypi 源加速库的安装 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple pip install modelscope1.11.0 pip install langchain0.1.15 pip install transformers4.40.0 accelerate tiktoken einops scipy transformers_stream_generator0.1.16 pip install -U huggingface_hub各依赖的作用简要说明如下依赖包版本要求作用modelscope1.11.0从 ModelScope 下载 LLaMA3 模型权重langchain0.1.15LangChain 框架本体提供LLM基类与统一接口transformers4.40.0加载与运行 LLaMA3 模型LLaMA3 需要较新版本支持accelerate最新支持device_mapauto多设备自动加载tiktoken/einops/scipy最新LLaMA3 分词与注意力计算相关的运行依赖transformers_stream_generator0.1.16流式生成支持为后续 WebDemo 等场景预留huggingface_hub最新HF Hub 工具库升级以确保兼容性为降低环境配置门槛self-llm 仓库在 AutoDL 平台准备了 LLaMA3 环境镜像该镜像适用于该仓库的所有部署环境可一键创建 AutoDL 示例直接使用。三、模型下载在/root/autodl-tmp路径下新建model_download.py文件内容如下import torch from modelscope import snapshot_download, AutoModel, AutoTokenizer import os model_dir snapshot_download(LLM-Research/Meta-Llama-3-8B-Instruct, cache_dir/root/autodl-tmp, revisionmaster)说明snapshot_download是 ModelScope 提供的模型快照下载函数第一个参数为模型名称此处为LLM-Research/Meta-Llama-3-8B-Instructcache_dir参数指定模型的下载路径这里设置为/root/autodl-tmpAutoDL 的数据盘空间充足revisionmaster指定下载 master 分支版本模型大小约15 GB保存文件后运行python /root/autodl-tmp/model_download.py执行下载大约需要 2 分钟。下载完成后模型将位于/root/autodl-tmp/LLM-Research/Meta-Llama-3-8B-Instruct该路径将作为后续代码中的mode_name_or_path。四、代码准备基于本地 LLaMA3 自定义 LLM 类4.1 完整实现LLaMA3_LLM 类为便捷构建 LLM 应用我们需要基于本地部署的 LLaMA3 自定义一个LLaMA3_LLM类将 LLaMA3 接入到 LangChain 框架中。完成自定义后就可以以完全一致的方式调用 LangChain 的接口而无需考虑底层模型调用的不一致。在/root/autodl-tmp下新建LLM.py文件输入以下内容粘贴后记得保存from 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 LLaMA3_LLM(LLM): # 基于本地 llama3 自定义 LLM 类 tokenizer: AutoTokenizer None model: AutoModelForCausalLM None def __init__(self, mode_name_or_path :str): super().__init__() print(正在从本地加载模型...) self.tokenizer AutoTokenizer.from_pretrained(mode_name_or_path, use_fastFalse) self.model AutoModelForCausalLM.from_pretrained(mode_name_or_path, torch_dtypetorch.bfloat16, device_mapauto) self.tokenizer.pad_token self.tokenizer.eos_token print(完成本地模型的加载) def bulid_input(self, prompt, history[]): user_format|start_header_id|user|end_header_id|\n\n{content}|eot_id| assistant_format|start_header_id|assistant|end_header_id|\n\n{content}|eot_id| history.append({role:user,content:prompt}) prompt_str # 拼接历史对话 for item in history: if item[role]user: prompt_struser_format.format(contentitem[content]) else: prompt_strassistant_format.format(contentitem[content]) return prompt_str def _call(self, prompt : str, stop: Optional[List[str]] None, run_manager: Optional[CallbackManagerForLLMRun] None, **kwargs: Any): input_str self.bulid_input(promptprompt) input_ids self.tokenizer.encode(input_str, add_special_tokensFalse, return_tensorspt).to(self.model.device) outputs self.model.generate( input_idsinput_ids, max_new_tokens512, do_sampleTrue, top_p0.9, temperature0.5, repetition_penalty1.1, eos_token_idself.tokenizer.encode(|eot_id|)[0] ) outputs outputs.tolist()[0][len(input_ids[0]):] response self.tokenizer.decode(outputs).strip().replace(|eot_id|, ).replace(|start_header_id|assistant|end_header_id|\n\n, ).strip() return response property def _llm_type(self) - str: return LLaMA3_LLM4.2 逐模块拆解构造函数、对话模板与 _call 核心逻辑1构造函数__init__模型的一次性加载self.tokenizer AutoTokenizer.from_pretrained(mode_name_or_path, use_fastFalse) self.model AutoModelForCausalLM.from_pretrained(mode_name_or_path, torch_dtypetorch.bfloat16, device_mapauto) self.tokenizer.pad_token self.tokenizer.eos_tokenuse_fastFalse使用 LLaMA3 原生的慢速分词器避免 fast tokenizer 在特殊 token 处理上的差异torch_dtypetorch.bfloat16以 BF16 精度加载模型在保持推理精度的同时显著降低显存占用这也是 24G 显存可运行 8B 模型的关键device_mapauto由accelerate自动将模型各层分配到可用设备上self.tokenizer.pad_token self.tokenizer.eos_tokenLLaMA3 原分词器未定义 pad_token这里将其设置为 eos_token避免后续批量编码时因缺少 padding 标记而报错运行时出现的 attention mask and pad token id were not set 警告即与此相关。2对话模板构造bulid_input手工拼接 LLaMA3 chat 模板LLaMA3 采用了新的对话式特殊 token 体系其 chat 模板由|start_header_id|、|end_header_id|角色头与内容边界和|eot_id|一轮对话结束标记构成。bulid_input的核心逻辑是将当前prompt以{role:user,content:prompt}形式追加进history遍历历史对话将每条消息按角色格式化为user_format或assistant_format片段拼接成完整的提示词字符串后返回。手工构造模板的意义在于LLaMA3 对输入格式极其敏感缺少|eot_id|等边界标记会导致模型无法正确识别对话轮次因此接入时必须严格按官方模板组织输入。值得一提的是仓库中 LLaMA3 的 FastApi 部署文档01-LLaMA3-8B-Instruct FastApi 部署调用中的bulid_input额外加入了|begin_of_text|前缀与system角色格式WebDemo03-LLaMA3-8B-Instruct WebDemo 部署同样使用本模板三处实现保持一致的 token 语义方便读者对照。3核心推理_callLangChain 与模型的桥接点_call函数是 LLM 类的核心函数LangChain 会调用该函数来调用 LLM。其执行链路为input_str self.bulid_input(promptprompt) # ① 构造对话模板输入 input_ids self.tokenizer.encode(input_str, add_special_tokensFalse, return_tensorspt).to(self.model.device) # ② 编码 outputs self.model.generate(input_idsinput_ids, max_new_tokens512, do_sampleTrue, top_p0.9, temperature0.5, repetition_penalty1.1, eos_token_idself.tokenizer.encode(|eot_id|)[0]) # ③ 生成 outputs outputs.tolist()[0][len(input_ids[0]):] # ④ 截取新增部分 response self.tokenizer.decode(outputs).strip()... # ⑤ 解码并清洗各步骤细节编码add_special_tokensFalse避免重复添加 BOS 等特殊 token并将输入移动到模型所在设备生成参数max_new_tokens512限制生成长度do_sampleTrue开启采样top_p0.9、temperature0.5控制随机性与多样性温度越低输出越保守repetition_penalty1.1抑制重复最关键的是eos_token_idself.tokenizer.encode(|eot_id|)[0]——将生成终止符从默认的 eos 改为 LLaMA3 的对话结束标记|eot_id|否则模型会一直生成到 eos 才停止导致输出包含多余内容截取只保留新生成的 tokenoutputs[len(input_ids[0]):]丢弃输入部分清洗解码后去除|eot_id|与|start_header_id|assistant|end_header_id|\n\n前缀得到纯净的助手回复。4_llm_type属性property def _llm_type(self) - str: return LLaMA3_LLM_llm_type是 LangChainLLM基类要求实现的属性用于标识 LLM 类型LangChain 内部及日志系统中会使用该标识。4.3 调用验证在整体项目中上述代码被封装为LLM.py后续直接从该文件中引入自定义的 LLM 类即可from LLM import LLaMA3_LLM llm LLaMA3_LLM(mode_name_or_path /root/autodl-tmp/LLM-Research/Meta-Llama-3-8B-Instruct) llm(你是谁)运行后终端会先打印 正在从本地加载模型...随后加载模型权重分片Loading checkpoint shards加载完成后打印 完成本地模型的加载。调用llm(你好呀!)即可获得模型回复例如你好呀! 我是人工智能语言模型很高兴和你交流! ...说明自定义 LLM 类已成功接入 LangChain 接口。图片中出现的 Special tokens have been added 与 attention mask and pad token id were not set 均为 transformers 的提示性警告不影响单轮对话的正常运行若在批量场景中处理可通过显式传入attention_mask与设置pad_token_id来消除。五、为什么_call是接入的关键LangChain LLM 抽象机制从源码层面看langchain.llms.base.LLM基类对外暴露的调用入口是__call__而__call__内部会经过缓存、回调callbacks等一系列 LangChain 框架逻辑后最终调用子类实现的_call完成真正的模型推理。因此应用层如 Chain、Agent、记忆组件只需调用llm(prompt)框架会自动将prompt与stop、run_manager等参数透传给_call子类通过重写_call就完成了与任意底层模型的适配——这正是以完全一致的方式调用 LangChain 接口的原理所在。这种模式在仓库的多个模型中反复出现如 InternLM 知识库助手的 LLM.py、Qwen 知识库助手 LLM.py 均重写__init__与_call区别仅在于_call内部是调用model.chat(tokenizer, prompt, history[])原生 chat 接口还是手工构造模板后调用model.generate如 LLaMA3。理解了这一点读者可以轻松将任意本地模型接入 LangChain。六、接入后的扩展向 LangChain 应用迈进完成LLaMA3_LLM的封装后该对象即可作为标准 LLM 注入 LangChain 的各种组件中。仓库为此提供了完整的进阶参考知识库问答参考 ChatGLM3 接入 LangChain 搭建知识库助手对应代码 LLM.py、create_db.py、run_gradio.py以及 Qwen 接入 LangChain 搭建知识库助手Web 演示在 03-LLaMA3-8B-Instruct WebDemo 部署 中基于同一套对话模板与生成参数用 Streamlit 构建了可交互的聊天界面API 服务在 01-LLaMA3-8B-Instruct FastApi 部署调用 中同一模型以 FastAPI 服务形式对外提供 POST 接口供其他系统调用。上述三篇文档与本篇共同构成 LLaMA3 本地化的完整矩阵本篇文章解决的是让 LangChain 认识 LLaMA3这一核心适配问题其余文档则在此基础上叠加了对话界面、HTTP 服务等外围能力。七、常见问题与注意事项模型加载失败或路径错误请确认mode_name_or_path与 ModelScope 下载目录一致/root/autodl-tmp/LLM-Research/Meta-Llama-3-8B-Instruct可通过ls /root/autodl-tmp/LLM-Research/Meta-Llama-3-8B-Instruct检查权重文件是否完整输出包含|eot_id|等特殊标记说明解码后的清洗未生效请确认_call中保留了replace(|eot_id|, )与 assistant 头前缀的替换逻辑若生成一直不停止检查eos_token_id是否指向|eot_id|缺少 pad_token 报错在加载 tokenizer 后执行self.tokenizer.pad_token self.tokenizer.eos_token自定义类中已包含显存不足本方案基于 24G 显存如 3090设计使用torch_dtypetorch.bfloat16与device_mapauto双保险若仍不足可考虑后续章节的 LoRA 4bit/8bit 量化方案见 04-LLaMA3-8B-Instruct Lora 微调多轮对话当前_call仅传入当前 promptbulid_input已支持传入history参数拼接历史可在后续应用中按需扩展。八、总结本文完整演示了将本地部署的 LLaMA3-8B-Instruct 接入 LangChain 的全过程从 AutoDL 镜像选型与依赖安装、ModelScope 下载 15GB 权重到继承LLM基类实现LLaMA3_LLM包括构造函数的一次性加载、LLaMA3 chat 模板的手工构造、_call中的生成参数与结果清洗最终以统一接口完成对话调用。掌握这一适配模式后你不仅能在 LangChain 生态中自由使用 LLaMA3也能举一反三地将仓库中的其他开源模型如 Qwen、ChatGLM 等以同样方式接入为构建知识库助手、Agent 等复杂 LLM 应用铺平道路。【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考