LLaMA3-8B-Instruct 接入 LangChain:基于 self-llm 自定义 LLM 类的本地化集成实战指南
2026/9/12 18:40:26 网站建设 项目流程

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 类接入 LangChain

LangChain 之所以能成为当下最流行的 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.0
  • Python 版本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 modelscope==1.11.0 pip install langchain==0.1.15 pip install "transformers>=4.40.0" accelerate tiktoken einops scipy transformers_stream_generator==0.1.16 pip install -U huggingface_hub

各依赖的作用简要说明如下:

依赖包版本要求作用
modelscope1.11.0从 ModelScope 下载 LLaMA3 模型权重
langchain0.1.15LangChain 框架本体,提供LLM基类与统一接口
transformers>=4.40.0加载与运行 LLaMA3 模型,LLaMA3 需要较新版本支持
accelerate最新支持device_map="auto"多设备自动加载
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', revision='master')

说明:

  • snapshot_download是 ModelScope 提供的模型快照下载函数,第一个参数为模型名称(此处为LLM-Research/Meta-Llama-3-8B-Instruct);
  • cache_dir参数指定模型的下载路径,这里设置为/root/autodl-tmp(AutoDL 的数据盘,空间充足);
  • revision='master'指定下载 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_fast=False) self.model = AutoModelForCausalLM.from_pretrained(mode_name_or_path, torch_dtype=torch.bfloat16, device_map="auto") 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_str+=user_format.format(content=item['content']) else: prompt_str+=assistant_format.format(content=item['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(prompt=prompt) input_ids = self.tokenizer.encode(input_str, add_special_tokens=False, return_tensors='pt').to(self.model.device) outputs = self.model.generate( input_ids=input_ids, max_new_tokens=512, do_sample=True, top_p=0.9, temperature=0.5, repetition_penalty=1.1, eos_token_id=self.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_LLM"

4.2 逐模块拆解:构造函数、对话模板与 _call 核心逻辑

(1)构造函数__init__:模型的一次性加载

self.tokenizer = AutoTokenizer.from_pretrained(mode_name_or_path, use_fast=False) self.model = AutoModelForCausalLM.from_pretrained(mode_name_or_path, torch_dtype=torch.bfloat16, device_map="auto") self.tokenizer.pad_token = self.tokenizer.eos_token
  • use_fast=False:使用 LLaMA3 原生的慢速分词器,避免 fast tokenizer 在特殊 token 处理上的差异;
  • torch_dtype=torch.bfloat16:以 BF16 精度加载模型,在保持推理精度的同时显著降低显存占用,这也是 24G 显存可运行 8B 模型的关键;
  • device_map="auto":由accelerate自动将模型各层分配到可用设备上;
  • self.tokenizer.pad_token = self.tokenizer.eos_token:LLaMA3 原分词器未定义 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的核心逻辑是:

  1. 将当前prompt{'role':'user','content':prompt}形式追加进history
  2. 遍历历史对话,将每条消息按角色格式化为user_formatassistant_format片段;
  3. 拼接成完整的提示词字符串后返回。

手工构造模板的意义在于:LLaMA3 对输入格式极其敏感,缺少<|eot_id|>等边界标记会导致模型无法正确识别对话轮次,因此接入时必须严格按官方模板组织输入。值得一提的是,仓库中 LLaMA3 的 FastApi 部署文档(01-LLaMA3-8B-Instruct FastApi 部署调用)中的bulid_input额外加入了<|begin_of_text|>前缀与system角色格式,WebDemo(03-LLaMA3-8B-Instruct WebDemo 部署)同样使用本模板,三处实现保持一致的 token 语义,方便读者对照。

(3)核心推理_call:LangChain 与模型的桥接点

_call函数是 LLM 类的核心函数,LangChain 会调用该函数来调用 LLM。其执行链路为:

input_str = self.bulid_input(prompt=prompt) # ① 构造对话模板输入 input_ids = self.tokenizer.encode(input_str, add_special_tokens=False, return_tensors='pt').to(self.model.device) # ② 编码 outputs = self.model.generate(input_ids=input_ids, max_new_tokens=512, do_sample=True, top_p=0.9, temperature=0.5, repetition_penalty=1.1, eos_token_id=self.tokenizer.encode('<|eot_id|>')[0]) # ③ 生成 outputs = outputs.tolist()[0][len(input_ids[0]):] # ④ 截取新增部分 response = self.tokenizer.decode(outputs).strip()... # ⑤ 解码并清洗

各步骤细节:

  • 编码add_special_tokens=False避免重复添加 BOS 等特殊 token,并将输入移动到模型所在设备;
  • 生成参数max_new_tokens=512限制生成长度;do_sample=True开启采样;top_p=0.9temperature=0.5控制随机性与多样性(温度越低输出越保守);repetition_penalty=1.1抑制重复;最关键的是eos_token_id=self.tokenizer.encode('<|eot_id|>')[0]——将生成终止符从默认的 eos 改为 LLaMA3 的对话结束标记<|eot_id|>,否则模型会一直生成到 eos 才停止,导致输出包含多余内容;
  • 截取:只保留新生成的 token(outputs[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),框架会自动将promptstoprun_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 服务等外围能力。

七、常见问题与注意事项

  1. 模型加载失败或路径错误:请确认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检查权重文件是否完整;
  2. 输出包含<|eot_id|>等特殊标记:说明解码后的清洗未生效,请确认_call中保留了replace('<|eot_id|>', "")与 assistant 头前缀的替换逻辑;若生成一直不停止,检查eos_token_id是否指向<|eot_id|>
  3. 缺少 pad_token 报错:在加载 tokenizer 后执行self.tokenizer.pad_token = self.tokenizer.eos_token(自定义类中已包含);
  4. 显存不足:本方案基于 24G 显存(如 3090)设计,使用torch_dtype=torch.bfloat16device_map="auto"双保险;若仍不足,可考虑后续章节的 LoRA 4bit/8bit 量化方案(见 04-LLaMA3-8B-Instruct Lora 微调);
  5. 多轮对话:当前_call仅传入当前 prompt,bulid_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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询