滴道网站建设,重庆装修网站建设,哪个网站做3d模型,wordpress html cdn06#xff5c;调用模型#xff1a;使用OpenAI API还是微调开源Llama2/ChatGLM#xff1f; 让我们带着下面的问题来开始这一节课的学习。大语言模型#xff0c;不止 ChatGPT 一种。调用 OpenAI 的 API#xff0c;当然方便且高效#xff0c;不过#xff0c;如果我就是想用…06调用模型使用OpenAI API还是微调开源Llama2/ChatGLM 让我们带着下面的问题来开始这一节课的学习。大语言模型不止 ChatGPT 一种。调用 OpenAI 的 API当然方便且高效不过如果我就是想用其他的模型比如说开源的 Llama2 或者 ChatGLM该怎么做再进一步如果我就是想在本机上从头训练出来一个新模型然后在 LangChain 中使用自己的模型又该怎么做
关于大模型的微调或称精调、预训练、重新训练、乃至从头训练这是一个相当大的话题不仅仅需要足够的知识和经验还需要大量的语料数据、GPU 硬件和强大的工程能力。别说一节课了我想两三个专栏也不一定能讲全讲透。不过我可以提纲挈领地把大模型的训练流程和使用方法给你缕一缕。这样你就能体验到在 LangChain 中使用自己微调的模型是完全没问题的。
大语言模型发展史
说到语言模型我们不妨先从其发展史中去了解一些关键信息。
Google 2018 年的论文名篇 Attention is all you need提出了 Transformer 架构也给这一次 AI 的腾飞点了火。Transformer 是几乎所有预训练模型的核心底层架构。基于 Transformer 预训练所得的大规模语言模型也被叫做“基础模型”Foundation Model 或 Base Model。
在这个过程中模型学习了词汇、语法、句子结构以及上下文信息等丰富的语言知识。这种在大量数据上学到的知识为后续的下游任务如情感分析、文本分类、命名实体识别、问答系统等提供了一个通用的、丰富的语言表示基础为解决许多复杂的 NLP 问题提供了可能。
在预训练模型出现的早期BERT 毫无疑问是最具代表性的也是影响力最大的模型。BERT 通过同时学习文本的前向和后向上下文信息实现对句子结构的深入理解。BERT 之后各种大型预训练模型如雨后春笋般地涌现自然语言处理NLP领域进入了一个新时代。这些模型推动了 NLP 技术的快速发展解决了许多以前难以应对的问题比如翻译、文本总结、聊天对话等等提供了强大的工具。 各种预训练语言模型
当然现今的预训练模型的趋势是参数越来越多模型也越来越大训练一次的费用可达几百万美元。这样大的开销和资源的耗费只有世界顶级大厂才能够负担得起普通的学术组织和高等院校很难在这个领域继续引领科技突破这种现象开始被普通研究人员所诟病。 模型越来越大参数越来越多
预训练 微调的模式
不过话虽如此大型预训练模型的确是工程师的福音。因为经过预训练的大模型中所习得的语义信息和所蕴含的语言知识能够非常容易地向下游任务迁移。NLP 应用人员可以对模型的头部或者部分参数根据自己的需要进行适应性的调整这通常涉及在相对较小的有标注数据集上进行有监督学习让模型适应特定任务的需求。
这就是对预训练模型的微调Fine-tuning。微调过程相比于从头训练一个模型要快得多且需要的数据量也要少得多这使得作为工程师的我们能够更高效地开发和部署各种 NLP 解决方案。 预训练微调的应用模式
图中的“具体任务”其实也可以更换为“具体领域”。那么总结来说
预训练在大规模无标注文本数据上进行模型的训练目标是让模型学习自然语言的基础表达、上下文信息和语义知识为后续任务提供一个通用的、丰富的语言表示基础。微调在预训练模型的基础上可以根据特定的下游任务对模型进行微调。现在你经常会听到各行各业的人说我们的优势就是领域知识嘛我们比不过国内外大模型我们可以拿开源模型做垂直领域嘛做垂类模型—— 啥叫垂类指的其实就是根据领域数据微调开源模型这件事儿。
这种预训练 微调的大模型应用模式优势明显。首先预训练模型能够将大量的通用语言知识迁移到各种下游任务上作为应用人员我们不需要自己寻找语料库从头开始训练大模型这减少了训练时间和数据需求其次微调过程可以快速地根据特定任务进行优化简化了模型部署的难度最后预训练 微调的架构具有很强的可扩展性可以方便地应用于各种自然语言处理任务大大提高了 NLP 技术在实际应用中的可用性和普及程度给我们带来了巨大的便利。
好下面咱们开始一步步地使用开源模型。今天我要带你玩的模型主要是 MetaFacebook推出的 Llama2。当然你可以去 Llama 的官网下载模型然后通过 Llama 官方 GitHub 中提供的方法来调用它。但是我还是会推荐你从 HuggingFace 下载并导入模型。因为啊前天百川昨天千问今天流行 Llama明天不就流行别的了嘛。模型总在变但是 HuggingFace 一直在那里支持着各种开源模型。我们学东西尽量选择学一次能够复用的知识。
用 HuggingFace 跑开源模型
注册并安装 HuggingFace
第一步还是要登录 HuggingFace 网站并拿到专属于你的 Token。如果你做了前面几节课的实战案例那么你应该已经有这个 API Token 了
第二步用 pip install transformers 安装 HuggingFace Library。详见这里。
第三步在命令行中运行 huggingface-cli login设置你的 API Token。 当然也可以在程序中设置你的 API Token但是这不如在命令行中设置来得安全。
# 导入HuggingFace API Token
import os
os.environ[HUGGINGFACEHUB_API_TOKEN] 你的HuggingFace API Token
申请使用 Meta 的 Llama2 模型
在 HuggingFace 的 Model 中找到 meta-llama/Llama-2-7b。注意各种各样版本的 Llama2 模型多如牛毛我们这里用的是最小的 7B 版。此外还有 13b\70b\chat 版以及各种各样的非 Meta 官方版。 选择 meta-llama/Llama-2-7b 这个模型后你能够看到这个模型的基本信息。如果你是第一次用 Llama你需要申请 Access因为我已经申请过了所以屏幕中间有句话“You have been granted access to this model”。从申请到批准大概是几分钟的事儿。 通过 HuggingFace 调用 Llama
好万事俱备现在我们可以使用 HuggingFace 的 Transformers 库来调用 Llama 啦
# 导入必要的库
from transformers import AutoTokenizer, AutoModelForCausalLM# 加载预训练模型的分词器
tokenizer AutoTokenizer.from_pretrained(meta-llama/Llama-2-7b-chat-hf)# 加载预训练的模型
# 使用 device_map 参数将模型自动加载到可用的硬件设备上例如GPU
model AutoModelForCausalLM.from_pretrained(meta-llama/Llama-2-7b-chat-hf, device_map auto) # 定义一个提示希望模型基于此提示生成故事
prompt 请给我讲个玫瑰的爱情故事?# 使用分词器将提示转化为模型可以理解的格式并将其移动到GPU上
inputs tokenizer(prompt, return_tensorspt).to(cuda)# 使用模型生成文本设置最大生成令牌数为2000
outputs model.generate(inputs[input_ids], max_new_tokens2000)# 将生成的令牌解码成文本并跳过任何特殊的令牌例如[CLS], [SEP]等
response tokenizer.decode(outputs[0], skip_special_tokensTrue)# 打印生成的响应
print(response)
这段程序是一个很典型的 HuggingFace 的 Transformers 库的用例该库提供了大量预训练的模型和相关的工具。
导入 AutoTokenizer这是一个用于自动加载预训练模型的相关分词器的工具。分词器负责将文本转化为模型可以理解的数字格式。导入 AutoModelForCausalLM这是用于加载因果语言模型用于文本生成的工具。使用 from_pretrained 方法来加载预训练的分词器和模型。其中device_map ‘auto’ 是为了自动地将模型加载到可用的设备上例如 GPU。然后给定一个提示prompt“请给我讲个玫瑰的爱情故事?”并使用分词器将该提示转换为模型可以接受的格式return_tensors“pt” 表示返回 PyTorch 张量。语句中的 .to(“cuda”) 是 GPU 设备格式转换因为我在 GPU 上跑程序不用这个的话会报错如果你使用 CPU可以试一下删掉它。最后使用模型的 .generate() 方法生成响应。max_new_tokens2000 限制生成的文本的长度。使用分词器的 .decode() 方法将输出的数字转化回文本并且跳过任何特殊的标记。
因为是在本地进行推理耗时时间比较久。在我的机器上大概需要 30s2min 产生结果。 这样的回答肯定不能直接用做商业文案而且我的意思是玫瑰花相关的故事它明显把玫瑰理解成一个女孩的名字了。所以开源模型尤其是 7B 的小模型和 Open AI 的 ChatGPT 还是有一定差距的。
LangChain 和 HuggingFace 的接口
讲了半天LangChain 未出场。下面让我们看一看如何把 HuggingFace 里面的模型接入 LangChain。
通过 HuggingFace Hub
第一种集成方式是通过 HuggingFace Hub。HuggingFace Hub 是一个开源模型中心化存储库主要用于分享、协作和存储预训练模型、数据集以及相关组件。
我们给出一个 HuggingFace Hub 和 LangChain 集成的代码示例。
# 导入HuggingFace API Token
import os
os.environ[HUGGINGFACEHUB_API_TOKEN] 你的HuggingFace API Token# 导入必要的库
from langchain import PromptTemplate, HuggingFaceHub, LLMChain# 初始化HF LLM
llm HuggingFaceHub(repo_idgoogle/flan-t5-small,#repo_idmeta-llama/Llama-2-7b-chat-hf,
)# 创建简单的question-answering提示模板
template Question: {question}Answer: # 创建Prompt
prompt PromptTemplate(templatetemplate, input_variables[question])# 调用LLM Chain --- 我们以后会详细讲LLM Chain
llm_chain LLMChain(promptprompt,llmllm
)# 准备问题
question Rose is which type of flower?# 调用模型并返回结果
print(llm_chain.run(question))
可以看出这个集成过程非常简单只需要在 HuggingFaceHub 类的 repo_id 中指定模型名称就可以直接下载并使用模型模型会自动下载到 HuggingFace 的 Cache 目录并不需要手工下载。
初始化 LLM创建提示模板生成提示的过程你已经很熟悉了。这段代码中有一个新内容是我通过 llm_chain 来调用了 LLM。这段代码也不难理解有关 Chain 的概念我们以后还会详述。
不过我尝试使用 meta-llama/Llama-2-7b-chat-hf 这个模型时出现了错误因此我只好用比较旧的模型做测试。我随便选择了 google/flan-t5-small问了它一个很简单的问题想看看它是否知道玫瑰是哪一种花。 模型告诉我玫瑰是花。对答案只有一个字flower。这…不得不说2023 年之前的模型和 2023 年之后的模型水平没得比。以前的模型能说话就不错了。 ChatGPT 本 T 的回答
通过 HuggingFace Pipeline
既然 HuggingFace Hub 还不能完成 Llama-2 的测试让我们来尝试另外一种方法HuggingFace Pipeline。HuggingFace 的 Pipeline 是一种高级工具它简化了多种常见自然语言处理NLP任务的使用流程使得用户不需要深入了解模型细节也能够很容易地利用预训练模型来做任务。
让我来看看下面的示例
# 指定预训练模型的名称
model meta-llama/Llama-2-7b-chat-hf# 从预训练模型中加载词汇器
from transformers import AutoTokenizer
tokenizer AutoTokenizer.from_pretrained(model)# 创建一个文本生成的管道
import transformers
import torch
pipeline transformers.pipeline(text-generation,modelmodel,torch_dtypetorch.float16,device_mapauto,max_length 1000
)# 创建HuggingFacePipeline实例
from langchain import HuggingFacePipeline
llm HuggingFacePipeline(pipeline pipeline, model_kwargs {temperature:0})# 定义输入模板该模板用于生成花束的描述
template 为以下的花束生成一个详细且吸引人的描述花束的详细信息{flower_details}# 使用模板创建提示
from langchain import PromptTemplate, LLMChain
prompt PromptTemplate(templatetemplate, input_variables[flower_details])# 创建LLMChain实例
from langchain import PromptTemplate
llm_chain LLMChain(promptprompt, llmllm)# 需要生成描述的花束的详细信息
flower_details 12支红玫瑰搭配白色满天星和绿叶包装在浪漫的红色纸中。# 打印生成的花束描述
print(llm_chain.run(flower_details))
这里简单介绍一下代码中使用到的 transformers pipeline 的配置参数。 生成的结果之一如下 此结果不敢恭维。但是后续的测试告诉我这很有可能是 7B 这个模型太小尽管有形成中文的相应能力但是能力不够强大也就导致了这样的结果。
至此通过 HuggingFace 接口调用各种开源模型的尝试成功结束。下面我们进行最后一个测试看看 LangChain 到底能否直接调用本地模型。
用 LangChain 调用自定义语言模型
最后我们来尝试回答这节课开头提出的问题假设你就是想训练属于自己的模型。而且出于商业秘密的原因不想开源它不想上传到 HuggingFace就是要在本机运行模型。此时应该如何利用 LangChain 的功能
我们可以创建一个 LLM 的衍生类自己定义模型。而 LLM 这个基类则位于 langchain.llms.base 中通过 from langchain.llms.base import LLM 语句导入。
这个自定义的 LLM 类只需要实现一个方法
_call 方法用于接收输入字符串并返回响应字符串。
以及一个可选方法
_identifying_params 方法用于帮助打印此类的属性。
下面让我们先从 HuggingFace 的这里下载一个 llama-2-7b-chat.ggmlv3.q4_K_S.bin 模型并保存在本地。 你可能会质疑我不是说自己训练自己微调不再用 HuggingFace 了吗
不好意思容许我解释一下。自己训练一个能用的模型没那么容易。这个模型它并不是原始的 Llama 模型而是 TheBloke 这位老兄用他的手段为我们量化过的新模型你也可以理解成他已经为我们压缩或者说微调了 Llama 模型。 量化是 AI 模型大小和性能优化的常用技术它将模型的权重简化到较少的位数以减少模型的大小和计算需求让大模型甚至能够在 CPU 上面运行。当你看到模型的后缀有 GGML 或者 GPTQ就说明模型已经被量化过其中 GPTQ 是一种仅适用于 GPU 的特定格式。GGML 专为 CPU 和 Apple M 系列设计但也可以加速 GPU 上的某些层。llama-cpp-python 这个包就是为了实现 GGML 而制作的。 所以这里你就假设咱们下载下来的 llama-2-7b-chat.ggmlv3.q4_K_S.bin 这个模型就是你自己微调过的。将来你真的微调了 Llama2、ChatGLM、百川或者千问的开源版甚至是自己从头训练了一个 mini-ChatGPT你也可以保存为 you_own_model.bin 的格式就按照下面的方式加载到 LangChain 之中。
然后为了使用 llama-2-7b-chat.ggmlv3.q4_K_S.bin 这个模型你需要安装 pip install llama-cpp-python 这个包。
# 导入需要的库
from llama_cpp import Llama
from typing import Optional, List, Mapping, Any
from langchain.llms.base import LLM# 模型的名称和路径常量
MODEL_NAME llama-2-7b-chat.ggmlv3.q4_K_S.bin
MODEL_PATH /home/huangj/03_Llama/# 自定义的LLM类继承自基础LLM类
class CustomLLM(LLM):model_name MODEL_NAME# 该方法使用Llama库调用模型生成回复def _call(self, prompt: str, stop: Optional[List[str]] None) - str:prompt_length len(prompt) 5# 初始化Llama模型指定模型路径和线程数llm Llama(model_pathMODEL_PATHMODEL_NAME, n_threads4)# 使用Llama模型生成回复response llm(fQ: {prompt} A: , max_tokens256)# 从返回的回复中提取文本部分output response[choices][0][text].replace(A: , ).strip()# 返回生成的回复同时剔除了问题部分和额外字符return output[prompt_length:]# 返回模型的标识参数这里只是返回模型的名称propertydef _identifying_params(self) - Mapping[str, Any]:return {name_of_model: self.model_name}# 返回模型的类型这里是custompropertydef _llm_type(self) - str:return custom# 初始化自定义LLM类
llm CustomLLM()# 使用自定义LLM生成一个回复
result llm(昨天有一个客户抱怨他买了花给女朋友之后两天花就枯了你说作为客服我应该怎么解释)# 打印生成的回复
print(result)
代码中需要解释的内容不多基本上就是 CustomLLM 类的构建和使用类内部通过 Llama 类来实现大模型的推理功能然后直接返回模型的回答。 似乎 Llama 经过量化之后虽然仍读得懂中文但是不会讲中文了。
翻译成中文他的回答是这样的。
当客户抱怨他们为女朋友买的花在两天内就枯萎了我会以礼貌和专业的方式这样解释
“感谢您把这个问题告诉我们。对于给您带来的任何不便我深感抱歉。有可能这些花没有被正确地存储或照料这可能影响了它们的生命期。我们始终以提供高质量的产品为荣但有时可能会出现意外的问题。请您知道我们非常重视您的满意度并随时为您提供帮助。您希望我为您提供替换或退款吗”
看上去除了中文能力不大灵光之外Llama2 的英文表现真的非常完美和 GPT3.5 差距不是很大要知道
这可是开源模型而且是允许商业的免费模型。这是在本机 CPU 的环境下运行的模型的推理速度还是可以接受的。这仅仅是 Llama 的最小版本也就是 7B 的量化版就达到了这么好的效果。