当前位置: 首页 > news >正文

[大模型]Qwen2-7B-Instruct 接入 LangChain 搭建知识库助手

环境准备

在 autodl 平台中租赁一个 3090 等 24G 显存的显卡机器,如下图所示镜像选择 PyTorch–>2.1.0–>3.10(ubuntu20.04)–>12.1

在这里插入图片描述

接下来打开刚刚租用服务器的 JupyterLab,并且打开其中的终端开始环境配置、模型下载和运行 demo。

pip 换源加速下载并安装依赖包

# 升级pip
python -m pip install --upgrade pip
# 更换 pypi 源加速库的安装
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simplepip install modelscope==1.11.0
pip install langchain==0.2.3
pip install "transformers>=4.41.2" accelerate tiktoken einops scipy transformers_stream_generator==0.0.4 peft deepspeed
pip install -U huggingface_hub

考虑到部分同学配置环境可能会遇到一些问题,我们在AutoDL平台准备了Qwen2的环境镜像,该镜像适用于该仓库除Qwen-GPTQ和vllm外的所有部署环境。点击下方链接并直接创建Autodl示例即可。
https://www.codewithgpu.com/i/datawhalechina/self-llm/Qwen2

模型下载

使用 modelscope 中的 snapshot_download 函数下载模型,第一个参数为模型名称,参数 cache_dir 为模型的下载路径。

在 /root/autodl-tmp 路径下新建 model_download.py 文件并在其中输入以下内容,粘贴代码后记得保存文件,如下图所示。并运行 python /root/autodl-tmp/model_download.py 执行下载,模型大小为 14 GB,下载模型大概需要 2 分钟。


import torch
from modelscope import snapshot_download, AutoModel, AutoTokenizer
import os
model_dir = snapshot_download('qwen/Qwen2-7B-Instruct', cache_dir='/root/autodl-tmp', revision='master')

代码准备

为便捷构建 LLM 应用,我们需要基于本地部署的 Qwen2-LM,自定义一个 LLM 类,将 Qwen2 接入到 LangChain 框架中。完成自定义 LLM 类之后,可以以完全一致的方式调用 LangChain 的接口,而无需考虑底层模型调用的不一致。

基于本地部署的 Qwen2 自定义 LLM 类并不复杂,我们只需从 LangChain.llms.base.LLM 类继承一个子类,并重写构造函数与 _call 函数即可:

from langchain.llms.base import LLM
from typing import Any, List, Optional
from langchain.callbacks.manager import CallbackManagerForLLMRun
from transformers import AutoTokenizer, AutoModelForCausalLM, GenerationConfig, LlamaTokenizerFast
import torchclass Qwen2_LLM(LLM):# 基于本地 Qwen2 自定义 LLM 类tokenizer: AutoTokenizer = Nonemodel: AutoModelForCausalLM = Nonedef __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.model.generation_config = GenerationConfig.from_pretrained(mode_name_or_path)print("完成本地模型的加载")def _call(self, prompt : str, stop: Optional[List[str]] = None,run_manager: Optional[CallbackManagerForLLMRun] = None,**kwargs: Any):messages = [{"role": "user", "content": prompt }]input_ids = self.tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)model_inputs = self.tokenizer([input_ids], return_tensors="pt").to('cuda')generated_ids = self.model.generate(model_inputs.input_ids,max_new_tokens=512)generated_ids = [output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)]response = self.tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]return response@propertydef _llm_type(self) -> str:return "Qwen2_LLM"

在上述类定义中,我们分别重写了构造函数和 _call 函数:对于构造函数,我们在对象实例化的一开始加载本地部署的 Qwen2 模型,从而避免每一次调用都需要重新加载模型带来的时间过长;_call 函数是 LLM 类的核心函数,LangChain 会调用该函数来调用 LLM,在该函数中,我们调用已实例化模型的 generate 方法,从而实现对模型的调用并返回调用结果。

在整体项目中,我们将上述代码封装为 LLM.py,后续将直接从该文件中引入自定义的 LLM 类。

调用

然后就可以像使用任何其他的langchain大模型功能一样使用了。

from LLM import Qwen2_LLM
llm = Qwen2_LLM(mode_name_or_path = "/root/autodl-tmp/qwen/Qwen2-7B-Instruct")
print(llm("你是谁"))

在这里插入图片描述

相关文章:

  • CSS实现经典打字小游戏《生死时速》
  • 【Windows】配置Flutter开发环境
  • ArrayList和LinkedList的区别!!!
  • 文献学习——PWM - PFM模式无缝转换的PFC变换器统一控制
  • LVS工作模式详解,NAT全方位剖析
  • PromptMRG: Diagnosis-Driven Prompts for Medical Report Generation
  • 还在用Flex布局?OUT了 快来看看grid布局吧!
  • 计算机二级Access选择题考点—代码篇
  • Java程序设计 第五章 循环
  • 微信小程序毕业设计-智慧消防系统项目开发实战(附源码+论文)
  • 今日成果2024-6-7 TrustZone TEE安全SDK开发指南
  • MySQL 保姆级教程(四):过滤数据
  • c语言回顾-结构体
  • redis 09 事务
  • 【Ardiuno】实验使用ESP32单片机根据光线变化控制LED小灯开关(图文)
  • 【译】JS基础算法脚本:字符串结尾
  • 〔开发系列〕一次关于小程序开发的深度总结
  • 230. Kth Smallest Element in a BST
  • 77. Combinations
  • Android框架之Volley
  • Hexo+码云+git快速搭建免费的静态Blog
  • React组件设计模式(一)
  • 动态规划入门(以爬楼梯为例)
  • - 概述 - 《设计模式(极简c++版)》
  • 巧用 TypeScript (一)
  • 少走弯路,给Java 1~5 年程序员的建议
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 终端用户监控:真实用户监控还是模拟监控?
  • puppet连载22:define用法
  • #pragma 指令
  • #控制台大学课堂点名问题_课堂随机点名
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (LeetCode 49)Anagrams
  • (Redis使用系列) Springboot 整合Redisson 实现分布式锁 七
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (含笔试题)深度解析数据在内存中的存储
  • (转)Google的Objective-C编码规范
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • ./configure,make,make install的作用
  • .NET 8 编写 LiteDB vs SQLite 数据库 CRUD 接口性能测试(准备篇)
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .NET命名规范和开发约定
  • .NET设计模式(7):创建型模式专题总结(Creational Pattern)
  • .NET中使用Redis (二)
  • @我的前任是个极品 微博分析
  • [ JavaScript ] JSON方法
  • [ vulhub漏洞复现篇 ] Apache Flink目录遍历(CVE-2020-17519)
  • [20160807][系统设计的三次迭代]
  • [ACTF2020 新生赛]Include
  • [Angular] 笔记 21:@ViewChild
  • [BJDCTF2020]The mystery of ip1
  • [bzoj1912]异象石(set)
  • [C]编译和预处理详解
  • [C++] 如何使用Visual Studio 2022 + QT6创建桌面应用