微信网站开发与网站实质区别,怎么做微信上的网站,信息网络传播视听节目许可证,微信管理系统文章目录 本节内容介绍集中接入#xff1a;将大模型统一管理起来当使用了大模型代理大模型代理示例 开源模型#xff1a;如何使用Hugging Face上的模型modelscope使用 pipeline 调用模型用底层实现调用模型流式输出 如何在项目中使用开源模型使用 LangChain使用集中接入开始使… 文章目录 本节内容介绍集中接入将大模型统一管理起来当使用了大模型代理大模型代理示例 开源模型如何使用Hugging Face上的模型modelscope使用 pipeline 调用模型用底层实现调用模型流式输出 如何在项目中使用开源模型使用 LangChain使用集中接入开始使用ollama 本节内容介绍
在本节中我们一起来使用one-api来模拟openai给应用提供对应的sk并尝试使用各种方式来使用本地的大模型尤其是最近deepseek爆火你更需要学习使用ollama上面提供的多个deepseek模型了
集中接入将大模型统一管理起来
集中接入就是把大模型的接入统一到一个地方管理起来下面这张图可以很好地帮我们理解集中接入 从这个图上你已经看出来了所谓的集中接入其实就是构建了一个代理我们后面就称它为大模型代理。
到这里你可能产生这样的疑问我直接用大模型不好吗为什么还要在中间加上一层代理呢
集中接入是一种架构上的调整顾名思义我需要是一个服务才会有架构调整的说法。如果只是像前面几讲如果在本地就可以运行起来的一些程序确实没有必要在中间加入一层。但在真实的项目中我们往往是要构建一个服务这时集中接入的价值就体现出来了。
之所以要有一个中间层最直接的一个问题就是限流问题。大模型服务本身资源消耗很大提供大模型服务的供应商为了保证尽可能多的用户享受到正常的服务所以它对单用户实施了限流。以 OpenAI API 为例下面就是它的限流标准其中 RPM 是 requests per minute每分钟请求数TPM 是 tokens per minute每分钟 Token 数。
如果我们是一个人或是规模比较小的服务这个限流标准大概是够用的但如果我们要对外提供服务这个标准大概率是不够用的。解决这个问题最简单的办法就是多申请一些账号形成一个号池这样限流标准对我们来说就大幅度提高了但随之而来的一个问题就是如何管理号池。
稍微仔细想一下你就会发现实现一个还不错的号池管理还是比较麻烦的。比如按什么方式在不同的账号之间进行选择怎样管理失效的账号等等。真的要实现好一个号池就等于实现了一个完整的运维工具可是你的应用目标是做一个 AI 应用。与其自己实现这么一套完整的功能还不如用已有的工具来完成这个目标。是的已经有一些现成的工具可以完成这个目标。
当使用了大模型代理
在介绍具体的工具之前我们先来看看如果把接入管理独立出来之后会产生怎样的变化。
首先肯定是解决了多账号管理的问题。所有的账号都配置在这个代理上而对于我们自己的应用而言只配置一个账号就好。这个大模型代理通常会采用 OpenAI 兼容的 API也就是说你完全可以用 OpenAI API 的使用方式使用它一般来说我们只要替换一下 API_BASE 和 API_KEY而其它的代码可以完全保持不变。这也是我们代理能够平滑接入的原因。
有了大模型代理之后我们还可以有一些其它的变化。一个典型的应用场景就是接入不同的供应商。虽然我们一直在讲 OpenAI API但由于众所周知的原因我们并不能直接访问 OpenAI API。
一个常见的解决办法是通过一些供应商来进行访问。一般来说我们并不会依赖于一家供应商所以配置多个供应商也是很常见的。有了大模型代理之后这些复杂性就从我们的应用中剥离出去了。 不同的供应商上提供的 API 可能会有所差异。比如微软的 Azure 也提供了 OpenAI 的服务但接口略有差异。如果是自己的代码我们就需要自己管理这种差异。有了大模型代理我们就可以把这种复杂性交给代理而让我们的代码采用统一的接口进行访问。
前面讨论的还都是 OpenAI 的模型。既然有了大模型代理我们完全可以再进一步通过它访问不同的模型。事实上很多供应商就提供了类似的能力比如 OpenRouter 就提供了许多不同模型的访问能力而它们都是基于 OpenAI 兼容接口的。通过大模型代理我们也可以访问不同的大模型。
不仅仅是使用别人的服务我们甚至可以访问自己本地部署的大模型。后面我们讲到本地部署大模型时我们会谈到如何利用大模型代理访问本地大模型。
总之有了大模型代理之后各种接入问题的复杂度就完全交给它了。在应用端来看接入就完全简化成一个 OpenAI 的接入接口。这也是我们前面重点介绍 OpenAI API 接口的原因。另外我们前面说过LangChain 在一些场景下是不适用的其中的一个原因就是它提供的一些抽象在某些情况下是失效的。有了大模型代理LangChain 提供的模型抽象就显得没有必要了。
好了现在你已经了解大模型代理在我们的应用中扮演的角色下面我们就来看如何使用搭建一个大模型代理。
大模型代理示例
能够提供大模型代理的工具有很多下面我以 One-API 为例介绍一下基本的用法。One-API 就是一个典型的大模型代理它提供了以 OpenAI API 接口访问各种大模型的能力。我们常见的一些大模型在 One-API 中都得到了支持比如GPT、Claude、文心一言、通义千问等等。它在行业内得到了很广泛地使用所以它在能力上也得到了很多扩展比如计费管理、渠道管理等等。
安装 One-API 最简单的方式是使用 Docker比如
docker run --name one-api -d --restart always -p 3000:3000 -e SQL_DSNroot:123456741852qtcp(101.42.44.178:2881)/oneapi -e TZAsia/Shanghai -v /home/zeng/soft/data/one-api:/data justsong/one-api在实际使用中我们会根据自己的实际情况修改数据库配置SQL_DSN如果配置了 SQL_DSNOne-API 会使用 MySQL 作为数据库。此外需要调整的配置就是映射目录这个目录里存放的是数据和日志
-v /home/zeng/soft/data/one-api:/data启动之后访问对应的地址比如在本地启动就是访问 http://localhost:3000/你就会看到它的界面。要想看到更多的配置项需要进行登录。 这里面的重点是渠道这对应的就是我们前面提到的服务供应商。我们可以添加新的渠道使用root/123456登录后才可配置渠道这里主要的几个选项是
类型它决定了在转发过程中采用什么 API 接入到后端的模型上比如OpenAI 就会采用 OpenAI API。模型这个渠道支持的模型比如gpt-4o-mini。每个渠道可以配置很多的模型。连接信息接入地址代理和 API Key密钥如果是同一个供应商的多个账号可以采用批量创建的方式输入多个 API Key。 在这个配置里有一个比较有意思的配置是模型重定向就是把一个模型名称转换成另外一个模型的名称。一种典型的用法是把一个比较昂贵的模型用另外一个便宜的模型代替。比如早期的 GPT-4 价格是很高的而后期的 GPT-4o 价格就要便宜不少而且性能会更强大。我们就可以在这里做一个映射让应用请求过来的 GPT 4而真正请求到后端都是 GPT-4o。 还有一种用法是给模型起一个新名称。这样一来我们的应用提供给用户的是一个自定义的名称请求到代理上之后再转成真正的模型发出去以此屏蔽掉后端真正的模型。我们在不少应用上见到的所谓自己的模型都可以这么实现出来。 如果配置了多个渠道之后我们可以在渠道列表看到后面截图里的选项。 在这里我们可以做一些运维类的工作比如禁用失效的渠道。还有一个点是优先级它是用来确定访问顺序的。比如多个渠道都提供了 gpt-4o-mini 这个模型我们会访问优先级高的渠道。
设置了模型之后我们还需要添加 API Key也就是这里的令牌。我们可以根据自己的需要设置相应的权限。 具体的 API Key 是自动生成的。我们创建好令牌之后可以在令牌列表中找到。只要在这里复制就可以得到所需的 API Key 了。 后面的操作我们都很熟悉了就是把 One API 的访问地址和 API Key 配置到我们的代码里和平时使用 OpenAI API 是一样的。 这里只讲了 One API 最基本的用法。这个工具已经开发了一段时间功能还是比较多的比如可以设置访问失败时自动禁用渠道出现问题时通知运维人员等等。你如果有需要可以去更多的探索。 开源模型如何使用Hugging Face上的模型
在传统开发中如果为这些企业服务一个重要的议题就是私有化部署但像 OpenAI 这样的服务显然是无法满足私有化部署的需求。在这种情况下一个能够运行在本地的大模型就显得至关重要了之所以我们可以在本地运行模型是因为有人把已经做好的模型开放了出来这就是开源的力量。
modelscope
如今的 Hugging Face 主要除了可以分享模型model还可以分享数据集dataset还有部署起来的应用Space。模型也不止是语言模型而是其它各式各样的模型比如图像生成模型、语音生成模型等等。为了让用户更好地使用其服务Hugging Face 还提供了很多的工具比如简化模型使用的 transformers 程序库、简化 AI 应用开发和部署的 Gradio 等等。 modelscope号称国内的Hugging Face由于网络限制所以下面都是使用modelscope作为示例 使用 pipeline 调用模型
调用 modelscope 模型有两种方式高层接口和底层接口。高层接口相当于是对底层接口做了封装让代码使用起来更容易相对而言底层接口则有更大的灵活性。在高层接口里我们核心要知道的一个概念就是管道pipeline。和软件领域所有叫管道的概念一样它要做的就是一步一步地进行处理一个阶段完成之后交给下一个阶段我们来看一个例子
# 首先使用命令将模型下载到本地
# modelscope download --model Qwen/Qwen2.5-3B-Instruct --local_dir ./Qwen2.5-3B-Instructimport torch
from transformers import pipelinedevice cuda if torch.cuda.is_available() else cpumessages [{role: user, content: 请写一首赞美秋天的五言绝句},
]
# 使用本地的
pipe pipeline(text-generation, model/home/zeng/llm/model/Qwen2.5-3B-Instruct, devicedevice, max_new_tokens100)
result pipe(messages)
print(result[-1][generated_text][-1][content])这段代码的核心就是这两句
pipe pipeline(text-generation, model/home/zeng/llm/model/Qwen2.5-3B-Instruct, devicedevice,
result pipe(messages)先构建了一个管道第一个参数指定了它的用途这里是文本生成text-generation pipeline 会根据不同的用途进行不同的管道配置。第二个参数是模型在这个例子里面我们使用的模型是阿里的通义千问Qwen引用模型的方式就是“用户名 / 模型名”在这里就是“Qwen/Qwen2.5-3B-Instruct”。
构建好了管道就可以调用模型了我们把消息传给模型它就会给我们产生一个结果。下面是我一次执行的结果
秋风送爽至落叶铺金地。
丰收稻谷香丰收喜悦起。前面说了pipeline 模型的第一个参数指定了用途。除了像大模型做文本生成modelscope 提供了大量的不同模型可以帮助我们完成其它的工作。具体请到modelscope模型库观看https://www.modelscope.cn/models
用底层实现调用模型
前面我们已经了解了管道的概念对高层接口有了基本的了解。不过管道封装起来的流程是什么样的呢这就需要我们了解一下底层实现。
下面就是一个使用底层的实现它实现的功能与上一段代码完全一样理解了它的实现你就基本上知道 pipeline 是怎样实现的了。
from transformers import AutoTokenizer, AutoModelForCausalLMtokenizer AutoTokenizer.from_pretrained(/home/zeng/llm/model/Qwen2.5-3B-Instruct)
model AutoModelForCausalLM.from_pretrained(/home/zeng/llm/model/Qwen2.5-3B-Instruct)messages [{role: user, content: 请写一首赞美春天的诗要求不包含春字},
]text tokenizer.apply_chat_template(messages,tokenizeFalse,add_generation_promptTrue
)
model_inputs tokenizer([text], return_tensorspt).to(model.device)generated_ids model.generate(**model_inputs,max_new_tokens512
)
generated_ids [output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]response tokenizer.batch_decode(generated_ids, skip_special_tokensTrue)[0]
print(response)从代码上看它的流程复杂多了。但实际上只要我们理解了大模型的处理过程这段代码就很容易理解了。这个过程的核心就是三步。
第一步把输入转换成 Token。
text tokenizer.apply_chat_template(messages,tokenizeFalse,add_generation_promptTrue
)
model_inputs tokenizer([text], return_tensorspt).to(model.device)第二步大模型根据输入生成相应的内容。
generated_ids model.generate(**model_inputs,max_new_tokens512
)第三步生成的结果是 Token还需要把它转成文本。
generated_ids [output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]response tokenizer.batch_decode(generated_ids, skip_special_tokensTrue)[0]基本上就是这样一个过程。因为过程中涉及到了 Token 和文本之间的转换所以这里还有一个 Tokenizer它就是负责转换的模型。一般来说大模型都要和对应的 Tokenizer 一起使用所以你会看到它俩往往给出的是同一个模型名字
tokenizer AutoTokenizer.from_pretrained(/home/zeng/llm/model/Qwen2.5-3B-Instruct)
model AutoModelForCausalLM.from_pretrained(/home/zeng/llm/model/Qwen2.5-3B-Instruct)流式输出
前面实现的功能都是由大模型一次性生成的。在聊天模式下我们还需要使用流式输出。在 Hugging Face 的 API 里我们可以使用 Streamer 来实现这一点从名字上就可以知道它是用来处理流式输出的。下面就是一个演示了流式输出的例子
from transformers import AutoTokenizer, AutoModelForCausalLM, TextStreamertokenizer AutoTokenizer.from_pretrained(/home/zeng/llm/model/Qwen2.5-3B-Instruct)
model AutoModelForCausalLM.from_pretrained(/home/zeng/llm/model/Qwen2.5-3B-Instruct)messages [{role: user, content: 请写一首赞美秋天的五言绝句},
]text tokenizer.apply_chat_template(messages,tokenizeFalse,add_generation_promptTrue
)
model_inputs tokenizer([text], return_tensorspt).to(model.device)streamer TextStreamer(tokenizer, skip_promptTrue, skip_special_tokensTrue)
generated_ids model.generate(**model_inputs,max_new_tokens512,streamerstreamer,
)在这个例子里我们用到了 TextStreamer它会直接把生成结果输出到控制台上。如果我们要实现一个控制台应用它是可以用的。但更多的情况下我们需要拿到输出结果再去做相应的处理比如服务端把生成的内容发送给客户端。这种情况下我们可以使用 TextIteratorStreamer下面是一个例子
from transformers import AutoTokenizer, AutoModelForCausalLM, TextStreamer, TextIteratorStreamer
from threading import Threadtokenizer AutoTokenizer.from_pretrained(/home/zeng/llm/model/Qwen2.5-3B-Instruct)
model AutoModelForCausalLM.from_pretrained(/home/zeng/llm/model/Qwen2.5-3B-Instruct)messages [{role: user, content: 请写一首赞美秋天的五言绝句},
]text tokenizer.apply_chat_template(messages,tokenizeFalse,add_generation_promptTrue
)
model_inputs tokenizer([text], return_tensorspt).to(model.device)
streamer TextIteratorStreamer(tokenizer, skip_promptTrue, skip_special_tokensTrue)
generation_kwargs dict(model_inputs, streamerstreamer, max_new_tokens20)
thread Thread(targetmodel.generate, kwargsgeneration_kwargs)
thread.start()for text in streamer:print(text)与之前最大的不同是这段代码启用了多线程这样一来生成和输出是异步处理的不会彼此阻塞更符合真实代码中的处理。正如 TextIteratorStreamer 这个名字所显示的它实现了 Iterator所以我们可以在其上进行迭代。 有了对 Streamer 的理解我们就可以回到 pipeline 上给 pipeline 增加流式输出的能力
import torch
from transformers import pipeline, TextIteratorStreamerdevice cuda if torch.cuda.is_available() else cpumessages [{role: user, content: 请写一首赞美秋天的五言绝句},
]pipe pipeline(text-generation, model/home/zeng/llm/model/Qwen2.5-3B-Instruct, devicedevice, max_new_tokens100)streamer TextIteratorStreamer(pipe.tokenizer, skip_promptTrue, skip_special_tokensTrue)generation_kwargs dict(text_inputsmessages, streamerstreamer)
thread Thread(targetpipe, kwargsgeneration_kwargs)
thread.start()for text in streamer:print(text)至此我们对如何调用 Hugging Face 上的模型有了一个初步的了解有了这个基础下面我们来看看如何在项目中使用这些模型。 如何在项目中使用开源模型
前面我们讲了如何使用 Hugging Face 上的开源模型。这一讲我们看看如何在实际的项目中使用这些模型。
这一讲我们就来谈谈两种常见的封装使用 LangChain 和使用集中接入。
使用 LangChain
LangChain 的模型就是 LangChain 给我们提供的一层封装屏蔽掉了不同大模型之间的差异让我们可以方便地在不同大模型之间进行切换。任何想要接入 LangChain 体系的大模型只要实现了相应的接口就可以无缝地嵌入到 LangChain 的体系中去Hugging Face 的模型就是这么做的。
我们之所以要把 Hugging Face 模型嵌入到 LangChain 的体系中主要是因为我们希望使用 LangChain 提供的其它抽象。
要使用 Hugging Face 相关的代码首先需要安装相应的包
pip install langchain-huggingfacelangchain-huggingface 是 Hugging Face 和 LangChain 共同维护的一个包其目标是缩短将 Hugging Face 生态的新功能带给 LangChain 用户的时间。它里面包含了很多功能
有各种模型的实现比如聊天模型和 Embedding 模型有数据集的实现它实现成了 DocumentLoader有工具的实现比如文本分类、文本转语音等。
从提供的内容上来看这个包封装了 Hugging Face 上的主要能力——模型和数据集。其中不同的模型因为能力上的差异做了不同归结属于大语言模型的就归结到了 LangChain 模型上而无法归结的就以工具的形式提供。
有了最基本的了解我们来实现一个简单的功能
import torch
from langchain_huggingface import HuggingFacePipeline, ChatHuggingFacedevice 0 if torch.cuda.is_available() else -1llm HuggingFacePipeline.from_model_id(model_id/home/zeng/llm/model/Qwen2.5-3B-Instruct,tasktext-generation,devicedevice,pipeline_kwargsdict(max_new_tokens512,return_full_textFalse,),
)chat_model ChatHuggingFace(llmllm)result chat_model.invoke(写一首赞美秋天的五言绝句。)
print(result.content)这里我们也是先构建了一个管道通过上一讲的学习这个构建管道的过程我们其实并不陌生无非就是设定模型 ID、模型用途task以及其它一些配置参数。虽然从命名上看我们是在构建一个管道但这里的 HuggingFacePipeline 是一个 LangChain 的 LLM 类型。
有了 HuggingFacePipeline我们再把它转成一个 ChatModel实际上就是做了一层封装
chat_model ChatHuggingFace(llmllm)ChatModel 我们之前已经谈了很多有了 ChatModel接下来它就可以与我们熟悉的那些 LangChain 抽象配合在一起了。在我们的示例里我们就是直接调用它。
result chat_model.invoke(写一首赞美秋天的五言绝句。)
print(result.content)前面我们说过在 LangChain 的体系下有 ChatModel 和 LLM 两种抽象都可以处理大模型。我们这里定义出的 HuggingFacePipeline 就是 LLM它也完全可以拿过来单独使用。
llm.invoke(写一首赞美秋天的五言绝句。)在我写下这段文字的时候langchain-huggingface 这个包的发布时间并不算很长实现上还有一些不够完善的地方。比如ChatHuggingFace 的流式应答支持得就不算特别好。在 langchain-community 这个包里还有一个旧版的 ChatHuggingFace它本身提供了流的支持只不过它需要与旧的一套代码配合使用而这套代码都处于被舍弃的状态Deprecated。
虽然我们可以在代码中支持不同模型的封装但其实我们还有另外一种选择就是采用集中接入的方案彻底摆脱在代码中集成模型。
使用集中接入
我们继续以一开始的 One-API 为例。在创建新渠道的时候类型是有很多选项的它决定着后端会接入到哪个供应商的模型上。其中的一个选项是 Ollama ollama是一个可以在本地运行大模型的轻量级框架。同我们在本地运行代码访问大模型类似它可以在本地启动一个服务我们可以通过这个服务去使用相应的大模型。类似的东西也有不少比如 vllm、gpt4all 等。
有一个运行在本地的大模型我们就可以做很多的事情了。比如搭建一个属于自己的聊天机器人尝试不同的大模型还有一些新的 AI 编码工具也是可以接入到本地的大模型。单纯从一个用户的角度我也推荐每个程序员尝试着在本地运行大模型做一些不同的事情它会加深你对大模型的理解。
开始使用ollama
下面我就以 Ollama 为例介绍一下基本的用法。安装 Ollama 只要找到对应的安装包即可如果是 Linux我们可以通过命令行进行安装
curl -fsSL https://ollama.com/install.sh | sh理解 Ollama 的使用可以类比于 Docker所以在 Ollama 的命令中我们会看到 pull、push、run 等命令。要想使用大模型我们首先要把大模型拉到本地
ollama pull qwen2.5同一个模型会有多个不同的版本比如通义千问 2.5 就有 0.5B、1.5B、3B、7B、14B、32B、72B 等不同规模的版本。即便是同一个规模还会有不同配置的版本。在 Ollama 中这些不同的版本是通过 Tag 区分的比如如果我们想使用 0.5B 版本的可以这样拉取。
ollama pull qwen2.5:0.5b如果想做一些简单的测试我们可以直接在本地把它运行起来。
ollama run qwen2.5启动之后就是一个命令行版的对话框对于程序员来说这就比较熟悉了。 写一首诗
春风吹绿江南岸芳草萋萋野花开。
千帆过尽江心月独坐闲庭听流水。风送花香满庭院鸟语花香醉晚晴。
时光荏苒如白驹岁月静好待人来。启动 Ollama 实际上是启动了一个服务所以我们也可以通过 API 访问这个服务。Ollama 提供了两类 API一类是它自身定义的 API另一类就是 OpenAI 兼容 API。下面就是通过它自身 API 访问服务的示例。
curl http://127.0.0.1:11434/api/chat -d {model: qwen2.5,messages: [{model: qwen2.5,prompt: 写一首关于AI的诗}]
}我们可以通过 list 命令查看已经安装的模型。
ollama listNAME ID SIZE MODIFIED
qwen2.5:0.5b a8b0c5157701 397 MB 16 hours ago
qwen2.5-coder:32b 4bd6cbf2d094 19 GB 2 days ago
qwen2.5:latest 845dbda0ea48 4.7 GB 7 days ago
llama3.2:latest a80c4f17acd5 2.0 GB 8 days ago在 One API 中填写的就是这里的 NAME 字段比如我们在配置中添加了 qwen2.5:0.5b。配置好之后我们就可以在代码中直接指定模型名为 qwen2.5:0.5b。
completion client.chat.completions.create(modelqwen2.5:0.5b,messagesself.messages,temperature0
)你看到了这里我们用到 OpenAI 的程序库但我在这里指定的模型是 qwen2.5:0.5b并不是 OpenAI 提供的模型。这也是我们集中接入采用 OpenAI 兼容 API 的意义所在。我们在代码层面上不用考虑模型的差异因为集中接入层做了这层封装把不同的供应商屏蔽了从而保证了我们代码的稳定性。
顺便说一下Ollama 本身也提供了一个程序库LangChain 也提供了 Ollama 的封装。如果有需要可以自行查看
细心的同学可能发现了我们在讨论 Ollama 的过程中并没有提到 Hugging Face。Ollama 相当于本身提供了一个仓库我们是从 Ollama 的仓库里拉取的模型。但说到模型的丰富程度肯定是 Hugging Face 更胜一筹的。我们可以使用 Hugging Face 的模型吗答案是可以。
在 Ollama 上使用模型运行的命令是后面这样。
ollama run hf.co/{username}/{repository}不过有一点要说明一下并不是所有的模型都可以使用 Ollama 运行的。为了确认这一点你可以在模型的说明页上查看一下。点击 “Use this model”如果下拉菜单中有 Ollama那就是可以使用你可以复制相应的命令去执行否则这个模型可能无法直接使用。