尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

DeepSeek-Coder-V2-Lite-Instruct 接入 LangChain 实战:自定义 LLM 类、对话调用与代码生成全流程

DeepSeek-Coder-V2-Lite-Instruct 接入 LangChain 实战:自定义 LLM 类、对话调用与代码生成全流程 DeepSeek-Coder-V2-Lite-Instruct 接入 LangChain 实战自定义 LLM 类、对话调用与代码生成全流程【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm本文是《开源大模型食用指南》self-llm 仓库中 DeepSeek-Coder-V2-Lite-Instruct 系列教程的 LangChain 接入篇完整演示了如何在本地部署该模型的基础上通过继承langchain.llms.base.LLM自定义一个 LLM 类将 DeepSeek-Coder-V2-Lite-Instruct 无缝接入 LangChain 框架。读完本文你将掌握基于 ModelScope 的模型下载、自定义 LLM 类的_call核心实现以及如何以统一接口测试模型的日常对话能力与代码生成能力为后续基于 LangChain 搭建知识库助手、Agent 等上层应用打下基础。环境准备本文的基础环境如下---------------- ubuntu 22.04 python 3.12 cuda 12.1 pytorch 2.3.0 ----------------本文默认学习者已安装好以上 Pytorch(cuda) 环境如未安装请自行安装。接下来开始环境配置、模型下载和运行演示 ~首先通过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.16.1 pip install langchain0.2.3 pip install transformers4.43.2 pip install accelerate0.32.1考虑到部分同学配置环境可能会遇到一些问题我们在AutoDL平台准备了DeepSeek-Coder-V2-Lite-Instruct的环境镜像点击下方链接并直接创建Autodl示例即可。https://www.codewithgpu.com/i/datawhalechina/self-llm/Deepseek-coder-v2这里需要注意版本约束langchain0.2.3是自定义LLM类时所依赖的版本transformers4.43.2与accelerate0.32.1负责模型的加载与设备映射modelscope1.16.1用于国内网络环境下快速下载模型权重。模型下载使用modelscope中的snapshot_download函数下载模型第一个参数为模型名称参数cache_dir为自定义的模型下载路径参数revision为模型仓库分支版本master代表主分支也是一般模型上传的默认分支。先切换到autodl-tmp目录cd /root/autodl-tmp然后新建名为model_download.py的python脚本并在其中输入以下内容并保存# model_download.py import torch from modelscope import snapshot_download, AutoModel, AutoTokenizer model_dir snapshot_download(deepseek-ai/DeepSeek-Coder-V2-Lite-Instruct, cache_dir/root/autodl-tmp, revisionmaster)然后在终端中输入python model_download.py执行下载。注意该模型权重文件比较大本系列 WebDemo 教程中提到模型大小约为 40 GB因此这里需要耐心等待一段时间直到模型下载完成。注意记得修改cache_dir为你的模型下载路径哦~ 下载完成后模型权重会存放在/root/autodl-tmp/deepseek-ai/DeepSeek-Coder-V2-Lite-Instruct目录下后续代码中将直接使用该路径加载模型。代码准备自定义 DeepSeek_Coder_LLM 类为便捷构建LLM应用我们需要基于本地部署的DeepSeek_Coder_LLM自定义一个 LLM 类将DeepSeek-Coder-V2-Lite-Instruct接入到LangChain框架中。完成自定义LLM类之后可以以完全一致的方式调用LangChain的接口而无需考虑底层模型调用的不一致。基于本地部署的DeepSeek-Coder-V2-Lite-Instruct自定义LLM类并不复杂我们只需从langchain.llms.base.LLM类继承一个子类并重写构造函数与_call函数即可# langchain_deepseek_coder.ipynb [1] 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 torch class DeepSeek_Coder_LLM(LLM): # 定义一个继承自LLM的DeepSeek_Coder_LLM类 # 类变量初始化为None将在初始化方法中被赋值 tokenizer: AutoTokenizer None model: AutoModelForCausalLM None def __init__(self, mode_name_or_path: str): # 初始化方法接受模型路径或名称作为参数 super().__init__() # 调用父类的初始化方法 print(正在从本地加载模型...) # 打印加载模型的提示信息 # 使用AutoTokenizer从预训练模型加载分词器 self.tokenizer AutoTokenizer.from_pretrained(mode_name_or_path, use_fastFalse, trust_remote_codeTrue) # 使用AutoModelForCausalLM从预训练模型加载语言模型 self.model AutoModelForCausalLM.from_pretrained( mode_name_or_path, torch_dtypetorch.bfloat16, # 设置PyTorch数据类型为bfloat16 device_mapauto, # 让模型自动选择设备 trust_remote_codeTrue # 信任远程代码 ) # 从预训练模型加载生成配置 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): # 定义_call方法用于生成文本 messages [{role: user, content: prompt }] # 定义消息列表包含用户的角色和内容 # 应用聊天模板生成输入ID input_ids self.tokenizer.apply_chat_template(messages, tokenizeFalse, add_generation_promptTrue) # 将输入ID转换为模型需要的输入格式并转换为PyTorch张量 model_inputs self.tokenizer([input_ids], return_tensorspt).to(cuda) # 使用模型生成文本设置生成参数 generated_ids self.model.generate( model_inputs.input_ids, max_new_tokens512, # 最大新生成的token数 top_k5, # 每次采样的token数 top_p0.8, # 按概率分布采样 temperature0.3, # 温度参数影响生成文本的随机性 repetition_penalty1.1, # 重复惩罚避免重复生成相同的文本 do_sampleTrue # 是否使用采样 ) # 从生成的ID中提取实际生成的文本ID generated_ids [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] # 将生成的ID解码为文本并跳过特殊token response self.tokenizer.batch_decode(generated_ids, skip_special_tokensTrue)[0] return response # 返回生成的文本 property def _llm_type(self) - str: # 定义一个属性返回模型的类型 return DeepSeek_Coder_LLM在上述类定义中我们分别重写了构造函数和_call函数构造函数在对象实例化的一开始加载本地部署的DeepSeek-Coder-V2-Lite-Instruct模型从而避免每一次调用都需要重新加载模型带来的时间浪费。加载时指定了torch_dtypetorch.bfloat16半精度推理、device_mapauto自动设备映射以及trust_remote_codeTrue信任远程代码。由于 DeepSeek 系列模型依赖自定义的远程代码实现trust_remote_codeTrue与use_fastFalse两个参数缺一不可。_call函数这是 LLM 类的核心函数Langchain会调用该函数来调用LLM。在该函数中我们调用已实例化模型的generate方法从而实现对模型的调用并返回调用结果。整个生成流程分为四步将用户prompt包装为messages对话格式通过tokenizer.apply_chat_template(messages, tokenizeFalse, add_generation_promptTrue)应用模型的聊天模板拼接出模型期望的完整输入这一步与模型推理时的 Prompt Template 严格对应DeepSeek-Coder-V2 系列使用的模板以begin▁of▁sentence、User:、Assistant:等特殊标记组织多轮对话详见本系列 Lora 微调文档 中的模板说明将输入张量送入model.generate通过max_new_tokens、top_k、top_p、temperature、repetition_penalty、do_sample等参数控制解码过程截取新生成的 token 并用batch_decode解码为可读文本返回。_llm_type属性按照LangChain框架的要求返回一个字符串用于标识该 LLM 的类型这里返回DeepSeek_Coder_LLM。此外在实现自定义LLM类时按照Langchain框架的要求我们还需要定义_identifying_params属性。这个属性的作用是返回一个字典该字典包含了能够唯一标识这个LLM实例的参数。这个功能对于缓存和追踪非常重要因为它能够帮助系统识别不同的模型配置从而进行有效的缓存管理和日志追踪。在整体项目中我们将上述代码封装为deepseek_langchain.py后续将直接从该文件中引入自定义的DeepSeek_Coder_LLM类。在实际使用时读者既可以按文档中的方式在 Notebook 中逐段运行也可以将类定义保存为独立的.py模块以便复用。模型调用日常对话能力测试完成自定义 LLM 类后就可以像使用任何其他的Langchain大模型功能一样使用了。我们先来简单测试一下模型的日常对话能力# langchain_deepseek_coder.ipynb [2] # from deepseek_langchain import DeepSeek_Coder_LLM llm DeepSeek_Coder_LLM(mode_name_or_path /root/autodl-tmp/deepseek-ai/DeepSeek-Coder-V2-Lite-Instruct) print(llm(你是谁))得到的返回值如下所示我是DeepSeek Coder一个由深度求索公司开发的智能助手。我旨在通过自然语言处理和机器学习技术来提供信息查询、对话交流和解答问题等服务。调用示例结果如下图所示。从运行日志可以看到实例化时模型分片加载完成Loading checkpoint shards: 100%随后print(llm(你是谁))正常触发了生成并返回了回答一个小提示运行截图中的LangChainDeprecationWarning: The method BaseLLM.__call__ was deprecated... Use invoke instead是 LangChain 0.2.x 对旧式llm(prompt)调用方式的弃用警告。在新项目中建议使用llm.invoke(prompt)或llm.generate([prompt])等新接口但二者在底层都会路由到我们重写的_call方法不影响本教程的调用结果。模型调用代码生成能力测试根据官方的文档说明DeepSeek-Coder-V2-Lite-Instruct模型有着极强的代码能力。仓库配套的基准对比图中展示了 DeepSeek-Coder-V2 系列在 HumanEval、MBPP、MATH、GSM8K、Aider、LiveCodeBench、SWE-Bench 等多项代码与数学基准上与 GPT-4-Turbo、Gemini-1.5-Pro、Claude-3-Opus、Llama-3-70B、Codestral 等模型的横向对比所以我们不妨也来测试一个经典的代码问题# langchain_deepseek_coder.ipynb [3] print(llm(请帮我写一段贪吃蛇游戏的Python代码并给出必要的注释))得到的返回值如下所示当然以下是一个简单的贪吃蛇游戏Python代码带有详细的注释。这个版本使用curses库来处理键盘输入和图形界面。 python import curses import random # 初始化屏幕 stdscr curses.initscr() curses.curs_set(0) # 隐藏光标 sh, sw stdscr.getmaxyx() # 获取窗口大小 # 创建一个窗口用于显示游戏区域 win curses.newwin(sh, sw, 0, 0) win.keypad(1) # 启用键盘输入 win.timeout(100) # 设置超时时间控制刷新频率 # 定义贪吃蛇的初始位置和长度 snake [(4, 4), (4, 3), (4, 2)] food (random.randint(1, sh-1), random.randint(1, sw-1)) win.addch(food[0], food[1], #) # 定义方向键 key curses.KEY_RIGHT while True: win.border(0) # 画边框 win.clear() # 清除窗口内容 for y, x in snake: win.addch(y, x, *) # 绘制贪吃蛇的身体 win.addch(food[0], food[1], #) # 绘制食物 event win.getch() # 获取键盘事件 if event -1: # 如果没有按键继续当前方向 key key else: key event # 更新方向 # 解析新的头部位置 head snake[0] if key curses.KEY_DOWN: new_head (head[0] 1, head[1]) elif key curses.KEY_UP: new_head (head[0] - 1, head[1]) elif key curses.KEY_LEFT: new_head (head[0], head[1] - 1) elif key curses.KEY_RIGHT:调用示例结果如下图所示从返回结果可以看出模型不仅给出了完整可读的 Python 代码还在每个关键步骤屏幕初始化、窗口创建、蛇与食物的定义、游戏循环、方向控制补充了中文注释体现了良好的指令跟随与代码生成能力。自定义 LLM 类的设计要点与后续扩展总结本教程自定义 LLM 类时的几个关键设计要点这也是在 LangChain 中接入其他本地开源模型的通用范式继承LLM基类并实现_call_call是 LangChain 调用模型的统一入口只要返回字符串上层Chain、Agent就能无感使用本地模型在构造函数中一次性加载模型将模型加载与推理分离避免每次调用都重复加载权重这也是本地部署场景下性能优化的关键正确应用聊天模板通过apply_chat_template将messages转换为模型期望的输入格式保证对话历史与角色信息的正确传递实现_llm_type与_identifying_params前者用于标识模型类型后者返回唯一标识参数支撑 LangChain 的缓存管理与日志追踪。在此基础上读者可以进一步参考仓库中其他模型的 LangChain 接入案例例如 Qwen-7B-Chat 接入 langchain 搭建知识库助手、ChatGLM3-6B 接入 LangChain 搭建知识库助手、InternLM 接入 LangChain 搭建知识库助手利用向量数据库、Embedding 模型与自定义 LLM 组合出完整的 RAG 知识库应用。总结本文完整走通了 DeepSeek-Coder-V2-Lite-Instruct 接入 LangChain 的三大步骤环境准备与依赖安装langchain、transformers、modelscope等、基于 ModelScope 的模型下载snapshot_download模型约 40 GB、自定义 LLM 类并完成对话与代码生成验证。通过继承LLM基类并重写_call方法我们得以用统一的 LangChain 接口调用本地模型既验证了模型的日常对话能力也验证了其代码生成能力。后续无论是搭建知识库助手还是构建 Agent 应用都可以在此自定义 LLM 类的基础上直接扩展无需再关心底层推理实现的差异。若希望进一步了解该模型的其他部署与微调方式可继续阅读本系列文档FastAPI 部署调用见 01-DeepSeek-Coder-V2-Lite-Instruct FastApi 部署调用.mdWeb 界面部署见 03-DeepSeek-Coder-V2-Lite-Instruct WebDemo 部署.mdLoRA 微调含模型 Prompt Template 与微调数据集格式说明见 04-DeepSeek-Coder-V2-Lite-Instruct Lora 微调.md。【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调全参数/Lora、部署国内外开源大模型LLM/多模态大模型MLLM教程项目地址: https://gitcode.com/GitHub_Trending/se/self-llm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表