大模型 LMDeploy 量化部署
1 模型部署
定义:
- 在软件工程中,部署通常指的是将开发完毕的软件投入使用的过程。
- 在人工智能领域,模型部署是实现深度学习算法落地应用的关键步骤。简单来说,模型部署就是将训练好的深度学习模型在特定环境中运行的过程。
场景:
- 服务器端:CPU部署,单GPU/TPU/NPU部署,多卡/集群
部署. - 移动端边缘端:移动机器人,手机……
2 大模型缓存推理技术
在大模型中,Transformer模型扮演着至关重要的角色。它通过自注意力机制(Self-Attention)来捕捉文本中的上下文信息,实现对文本的深入理解和推理。这种机制允许模型在处理每个token时都考虑到整个输入序列的上下文信息,从而提高了模型的表达能力和准确性。

- 对于新的请求Query,需要与历史的Key、Value计算注意力分数。
- 如果每次都重新计算历史的Key、Value,会浪费大量计算资源。
- 每轮新迭代时将Key、Value进行缓存,共下次迭代使用。
KV Cache的全称是key-value cache,可以简单理解为对大模型推理过程中的key-value缓存的优化。

LMDeploy 对 KV Cache 的实现:
- 预先申请策略,减少运行时因申请/释放内存的消耗时间。
- 通过设置
cache_max_entry_count参数来调节 KV Cache 占用内存的大小,为占用剩余显存的比例。
下图0.2表示KV Cache 可以占用的显存大小是在加载玩模型权重后所剩余的显存的20%。

3 大模型量化技术
量化技术将传统的表示方法中的浮点数转换为整数或其他离散形式,以减轻深度学习模型的存储和计算负担。
为什么要做量化:
- 提升推理的速度
- 增加上下文长度
- 速度更快的kernel
- 降低I/0延迟
- 降低推理成本
量化思路,将原来浮点数所在区间做一个线性映射,映射为一些列整数。以 INT8 的8位二进制数为例,通用公式:
Z P = min + max 2 量化: q = r o u n d ( f − Z P S ) S = max − min 255 反量化: f = q × S + Z P ZP=\frac{\min+\max} {2} \quad\text{量化:} \, q=\mathrm{round}\left(\frac{f-ZP}{S}\right) \\ S=\frac{\max-\min}{255}\quad \text{反量化:} \, f=q\times S+ZP ZP=2min+max量化:q=round(Sf−ZP)S=255max−min反量化:f=q×S+ZP

量化方法的分类:
(1)按量化对象分:
- KV Cache量化
- 模型权重量化
- 激活值量化 (例如对于一个线性层 y = w x y = wx y=wx 中 w w w为权重, x x x为激活值)
(2)按量化阶段分
- 量化感知训练(QAT)
- 量化感知微调(QAF)
- 训练后量化(PTQ,训练好模型后,在完成量化,常用这种方式)
由于QAT和QAF一般在模型训练后仍然需要做微调操作量化,通常不采用这两种方式。
3.1 LMDeploy 量化方案
LMDeploy 量化方式:KV Cache量化 + 模型权重量化 + 训练后量化
3.1.1 KV Cache量化
- 在线KVCacheINT4/INT8量化,粒度为 per-head per-token
- 与FP16相比,INT4/INT8的KVBlock数量分别可以提升4倍和2倍。意义:更长的上下文、更高的并发吞吐
- 精度上INT8几乎无损,INT4略有损失

3.1.2 模型权重量化(W4A16量化)
- 基于 AWQ 算法,对权重进行4bit量化,计算时返量化使用FP16
- 性能是FP16的2.4倍以上
- 权重大小、显存降为FP16的的1/4
3.1.3 AWQ 量化原理**:
参考论文:AWQ
核心观点1:权重并不等同重要,仅有0.1~1%小部分显著权重对推理结果影响较大。
如果有办法将这0.1~1%的小部分显著权重保持FP16,对其他权重进行低比特量化,可以大幅降低内存占用。那么问题来了:如果选出显著权重?
(1)随机挑选-听天由命
(2)基于权重分布挑选-好像应该这样
(3)基于激活值挑选-竟然是这样
AWQ 论文对三者做了实验对比,返实验结果表明基于激活值挑选显著权重效果显著。

基于激活值,按通道“组团”挑选显著权重权重。为了避免实现上过于复杂,在挑选显著权重时,并非在“元素”级别进行挑选,而是在“通道”级别进行挑选。 首先将激活值对每一列(channel)求绝对值的平均值,把平均值较大一列对应的通道视作显著权重。

但是,随之伴随问题:
- 显著权重INT4,非显著权重FP16?
- “显著”的阈值?
- 如何实现一个通道粒度上混合精度的kernel?
- 这是硬件不友好的行为!
- 这更是开发者不友好的行为!
核心观点2:量化前对显著权重进行放大可以降低量化误差。

考虑权重矩阵w,线性运算写作y=wx。对权重矩阵进行量化后,可以写作y=Q(w)x。Q(·)定义如下:实验表现:
- 随着s增大,假设成立的概率越来越低,但在s<2之前,概率还是很低的(<5%)
- 在一定范围内,随着s的增大,误差比值越来越小,完全支持作者观点
所有权重均低比特量化。显著权重乘以较大s,等效于降低量化误差。非显著权重乘以较小的s,等效于给予更少的关注。

LMDeploy 采用分组计算每个通道的缩放系数:

4 大模型外推技术
大模型长度外推性是一个训练和预测的长度不一致的问题。
外推引发的两大问题:
- 预测阶段用到了没训练过的位置编码
模型不可避免地在一定程度上对位置编码“过拟合” - 预测注意力时注意力机制所处理的token数量远超训练时的数量
导致计算注意力“熵”的差异较大
4.1 为什么需要位置编码
因为并行化的自注意力机制并不具备区分token相对位置的能力。位置编码用于为输入序列的每个位置添加一种表示其位置信息的编码。通过引入位置编码,Transformer模型可以更好地捕捉序列中不同位置之间的关系,从而更好地处理长距离依赖关系。
-
如果直接使用一个整数作为位置信息提供给模型,则会造成数值跨度过大,对梯度优化器不友好,模型学习困难。
-
如果将数值缩放到 [0-1] 区间,则会造成数值跨度过小,模型和优化器都难以分辨位置。
-
使用向量表示位置:
“10进制”为例,位置1234可以用4维向量[1 2 3 4]表示。一般地,位置N可以用如下向量表示:
∣ N 1 0 3 ∣ m o d 10 ∣ N 1 0 2 ∣ m o d 10 ∣ N 1 0 2 ∣ m o d 10 ∣ N 1 0 0 ∣ m o d 10 \left|\frac{N}{10^{3}}\right|\mathrm{mod}10\quad\left|\frac{N}{10^{2}}\right|\mathrm{mod}10\quad\left|\frac{N}{10^{2}}\right|\mathrm{mod}10\quad\left|\frac{N}{10^{0}}\right|\mathrm{mod}10 103N mod10 102N mod10 102N mod10 100N mod10
更一般地,果不是10进制,是β进制呢?第i位数是为:
⌊ N β i ⌋ m o d β \left\lfloor\frac{N}{\beta^i}\right\rfloor\mathrm{mod~}\beta ⌊βiN⌋mod β
这里的取余重在表示周期性。
Transformer使用的 Sinusoidal 位置编码:
p i , 2 j = sin ( i 1000 0 2 j / d ) , p i , 2 j + 1 = cos ( i 1000 0 2 j / d ) p_{i,2j}=\sin\left(\frac i{10000^{2j/d}}\right),\quad p_{i,2j+1}=\cos\left(\frac i{10000^{2j/d}}\right) pi,2j=sin(100002j/di),pi,2j+1=cos(100002j/di)
- "mod”的主要特性是周期性,因此与周期函数cos/sin具有一定的等效性
- 因此,Sinusoidal 位置编码可以认为是一种特殊的β进制编码
4.2 从位置编码角度解决外推引发的问题
方案:训练阶段就预留好足够的位数
Transformer的原作者就是这么想的,认为预留好位数后模型就能具备对位置编码的泛化性。

- 现实情况:模型并没有按照我们的期望进行泛化
- 训练阶段大多数高位都是“0”,因此这部分位数没有被充分训练,模型无法处理这些新编码。
线性内插法:
- 方案:把“新长度范围”,等比例缩放至训练阶段的长度范围。
- 如训练时使用1k训练,需外推至4k,就将 [0,4k] 的范围线性缩放至 [0,1k]。
n / k β d / 2 − 1 \frac{n/k}{\beta^{d/2-1}} βd/2−1n/k
但是这会使最低位非常“拥挤”,通常需要进行微调,使模型适应拥挤的映射关系。各维度差异较大!其他位置差异为1,个位差异较小,模型不易分辨,效果不佳。
进制转换法:
- 大模型其实并不知道我们输入的位置编码具体是多少“进制”的,他只对相对大小关系敏感
- 能否通过“进制转换”来等效“内插”?
如:10进制下,3位表示范围是0~999;16进制下,3位表示范围是0 ~ FFF(FFF16=4095)

虽然每一位上都有可能出现大于“9”的数,但相对大小差异仍为“1”,模型有能力进行泛化。把内插的压力平均分摊到了每一位上。
4.2.1 NTK-aware 外推技术
预测阶段,计算系数,对位置编码的底数base进行缩放,使得与线性内插法值相等:
n ( β λ ) d / 2 − 1 = n / k β d / 2 − 1 \frac{n}{(\beta\lambda)^{d/2-1}}=\frac{n/k}{\beta^{d/2-1}} (βλ)d/2−1n=βd/2−1n/k
n 是实际预测长度,k 是实际长度与训练长度的比值。求得:
λ = k 2 / ( d − 2 ) \lambda=k^{2/(d-2)} λ=k2/(d−2)
可得位置编码为:
sin ( n ( β λ ) i ) = sin ( n ( θ 2 / d k 2 / ( d − 2 ) ) i ) = sin ( n ( θ k d / ( d − 2 ) ) 2 i ) \sin\left(\frac{n}{(\beta\lambda)^{i}}\right)=\sin\left(\frac{n}{(\theta^{2/d}k^{2/(d-2)})^{i}}\right)=\sin\left(\frac{n}{(\theta k^{d/(d-2)})^{2i}}\right) sin((βλ)in)=sin((θ2/dk2/(d−2))in)=sin((θkd/(d−2))2in)
5 Function Calling
什么是Function Calling?为什么要有FunctionCalling?
FunctionCalling,即为让LLM调用外部函数解决问题,从而拓展LLM的能力边界。
- 指的是在语言模型中集成外部服务或API的调用能力。
- 模型可以在生成文本的过程中调用外部函数或服务,获取额外的数据或执行特定的任务。
Function Calling的意义?
- 解决时效性问题
今天是哪年哪日?今天天气如何? - 拓展LLM能力边界
帮我算一下 e 8 / 12345 e^8/12345 e8/12345 等于多少?帮我搜索一下这篇论文?
5.1 Function Calling 与 RAG
工作原理
- Function Calling:
指的是在语言模型中集成外部功能或API的调用能力;
模型可以在生成文本的过程中调用外部函数或服务,获取额外的数据或执行特定的任务。 - RAG:
结合了信息检索和文本生成;
它首先从一个大型的文档数据库中检索与输入查询相关的文档,然后将这些文档的信息融入到语言模型的生成过程中。
应用场景
- Function Calling:
适用于需要模型执行特定操作或与外部系统交互的场景。
例如,模型可以调用天气API来回答关于当前天气的问题,或者调用翻译服务来提供翻译;
在动态数据查询、任务自动化、系统集成以及结构化数据获取等方面有广泛应用。 - RAG:
适用于那些需要外部信息来提供准确回答的场景;
如问答系统,它可以通过检索到的信息来丰富和支模型的回答;
在医疗、法律、研究等领域,使用RAG可以保证提供的答案与权威文献一致。
6 LMDeploy 量化部署实践
6.1 配置LMDeploy环境
6.1.1 环境搭建
创建一个名为lmdeploy的conda环境,python版本为3.10,创建成功后激活环境并安装0.5.3版本的lmdeploy及相关包。
conda create -n lmdeploy python=3.10 -y
conda activate lmdeploy
conda install pytorch==2.1.2 torchvision==0.16.2 torchaudio==2.1.2 pytorch-cuda=12.1 -c pytorch -c nvidia -y
pip install timm==1.0.8 openai==1.40.3 lmdeploy[all]==0.5.3pip install datasets==2.19.2
6.1.2 InternStudio 环境获取模型
InternStudio统一把模型放置在/root/models/目录。
运行以下命令,创建文件夹并设置开发机共享目录的软链接。
mkdir /root/models
ln -s /root/share/new_models/Shanghai_AI_Laboratory/internlm2_5-7b-chat /root/models
ln -s /root/share/new_models/Shanghai_AI_Laboratory/internlm2_5-1_8b-chat /root/models
ln -s /root/share/new_models/OpenGVLab/InternVL2-26B /root/models
本实战使用internlm2_5-7b-chat和InternVL2-26B作为演示。由于上述模型量化会消耗大量时间(约8h),量化请使用internlm2_5-1_8b-chat模型完成。
6.1.3 LMDeploy 验证启动模型文件
在量化工作正式开始前,我们还需要验证一下获取的模型文件能否正常工作,以免竹篮打水一场空。
让我们进入创建好的conda环境并启动InternLM2_5-1_8b-chat
conda activate lmdeploy
lmdeploy chat /root/models/internlm2_5-7b-chat
启动成功后,可以提问:

启动大模型后查看资源监控:

现在显存占用约23GB。
我们要运行参数量为7B的InternLM2.5,由InternLM2.5的码仓查询InternLM2.5-7b-chat的config.json文件可知,该模型的权重被存储为bfloat16格式:

对于一个7B(70亿)参数的模型,每个参数使用16位浮点数(等于 2个 Byte)表示,则模型的权重大小约为:
7×10^9 parameters×2 Bytes/parameter=14GB
为什么现在显存占用约23GB呢?
这是因为LMDeploy设置了kv cache量化占剩余显存的80%:

此时对于24GB的显卡,即30%A100,权重占用14GB显存,剩余显存24-14=10GB,因此kv cache占用10GB*0.8=8GB,加上原来的权重14GB,总共占用14+8=22GB。
实际加载模型后,其他项也会占用部分显存,因此剩余显存比理论偏低,实际占用会略高于22GB。
6.2 LMDeploy与InternLM2.5
前面我们直接在本地部署InternLM2.5。而在实际应用中,我们有时会将大模型封装为API接口服务,供客户端访问。
6.2.1 LMDeploy API部署InternLM2.5
启动API服务器
首先让我们进入创建好的conda环境,并通下命令启动API服务器,部署InternLM2.5模型:
conda activate lmdeploy
lmdeploy serve api_server \/root/models/internlm2_5-7b-chat \--model-format hf \--quant-policy 0 \--server-name 0.0.0.0 \--server-port 23333 \--tp 1
命令解释:
lmdeploy serve api_server:这个命令用于启动API服务器。/root/models/internlm2_5-7b-chat:这是模型的路径。--model-format hf:这个参数指定了模型的格式。hf代表“Hugging Face”格式。--quant-policy 0:这个参数指定了量化策略。--server-name 0.0.0.0:这个参数指定了服务器的名称。在这里,0.0.0.0是一个特殊的IP地址,它表示所有网络接口。--server-port 23333:这个参数指定了服务器的端口号。在这里,23333是服务器将监听的端口号。--tp 1:这个参数表示并行数量(GPU数量)。
这一步由于部署在远程服务器上,所以本地需要做一下ssh转发才能直接访问。在你本地打开一个cmd或powershell窗口,输入命令如下:
ssh -CNg -L 23333:127.0.0.1:23333 root@ssh.intern-ai.org.cn -p 你的ssh端口号
打开浏览器,访问http://127.0.0.1:23333看到如下界面即代表部署成功:

6.2.2 以命令行形式连接API服务器
关闭http://127.0.0.1:23333网页,但保持终端和本地窗口不动,新建一个终端。
conda activate lmdeploy
lmdeploy serve api_client http://localhost:23333
稍待片刻,等出现double enter to end input >>>的输入提示即启动成功,此时便可以随意与InternLM2.5对话,同样是两下回车确定,输入exit退出。
6.2.3 以Gradio网页形式连接API服务器
保持启动23333端口的服务,在新建终端中输入exit退出。
输入以下命令,使用Gradio作为前端,启动网页:
lmdeploy serve gradio http://localhost:23333 \--server-name 0.0.0.0 \--server-port 6006
启动后,关闭之前的cmd/powershell窗口,重开一个,再次做一下ssh转发(因为此时端口不同)。在你本地打开一个cmd或powershell窗口,输入命令如下。
ssh -CNg -L 6006:127.0.0.1:6006 root@ssh.intern-ai.org.cn -p <你的ssh端口号>
打开浏览器,访问地址http://127.0.0.1:6006,然后就可以与模型尽情对话了:

6.3 LMDeploy Lite
随着模型变得越来越大,我们需要一些大模型压缩技术来降低模型部署的成本,并提升模型的推理性能。LMDeploy 提供了权重量化和 k/v cache两种策略。
6.3.1 设置最大kv cache缓存大小
kv cache是一种缓存技术,通过存储键值对的形式来复用计算结果,以达到提高性能和降低内存消耗的目的。在大规模训练和推理中,kv cache可以显著减少重复计算量,从而提升模型的推理速度。理想情况下,kv cache全部存储于显存,以加快访存速度。
模型在运行时,占用的显存可大致分为三部分:模型参数本身占用的显存、kv cache占用的显存,以及中间运算结果占用的显存。LMDeploy的kv cache管理器可以通过设置--cache-max-entry-count参数,控制kv缓存占用剩余显存的最大比例。默认的比例为0.8。
6.3.2 设置在线 kv cache int4/int8 量化
自 v0.4.0 起,LMDeploy 支持在线 kv cache int4/int8 量化,量化方式为 per-head per-token 的非对称量化。此外,通过 LMDeploy 应用 kv 量化非常简单,只需要设定 quant_policy 和cache-max-entry-count参数。目前,LMDeploy 规定 quant_policy=4 表示 kv int4 量化,quant_policy=8 表示 kv int8 量化。
例如,输入以下指令,启动API服务器:
lmdeploy serve api_server \/root/models/internlm2_5-7b-chat \--model-format hf \--quant-policy 4 \--cache-max-entry-count 0.4\--server-name 0.0.0.0 \--server-port 23333 \--tp 1
相比使用BF16精度的kv cache,int4的Cache可以在相同4GB的显存下只需要4位来存储一个数值,而BF16需要16位。这意味着int4的Cache可以存储的元素数量是BF16的四倍。
6.3.3 W4A16 模型量化和部署
- W4:这通常表示权重量化为4位整数(int4)。这意味着模型中的权重参数将从它们原始的浮点表示(例如FP32、BF16或FP16,Internlm2.5精度为BF16)转换为4位的整数表示。这样做可以显著减少模型的大小。
- A16:这表示激活(或输入/输出)仍然保持在16位浮点数(例如FP16或BF16)。激活是在神经网络中传播的数据,通常在每层运算之后产生。
使用1.8B模型进行量化:
lmdeploy lite auto_awq \/root/models/internlm2_5-1_8b-chat \--calib-dataset 'ptb' \--calib-samples 128 \--calib-seqlen 2048 \--w-bits 4 \--w-group-size 128 \--batch-size 1 \--search-scale False \--work-dir /root/models/internlm2_5-1_8b-chat-w4a16-4bit
命令解释:
lmdeploy lite auto_awq:lite这是LMDeploy的命令,用于启动量化过程,而auto_awq代表自动权重量化(auto-weight-quantization)。/root/models/internlm2_5-7b-chat: 模型文件的路径。--calib-dataset 'ptb': 这个参数指定了一个校准数据集,这里使用的是’ptb’(Penn Treebank,一个常用的语言模型数据集)。--calib-samples 128: 这指定了用于校准的样本数量—128个样本--calib-seqlen 2048: 这指定了校准过程中使用的序列长度—2048- -
-w-bits 4: 这表示权重(weights)的位数将被量化为4位。 --work-dir /root/models/internlm2_5-7b-chat-w4a16-4bit: 这是工作目录的路径,用于存储量化后的模型和中间结果。
等终端输出如下时,说明正在推理中,稍待片刻:

报错解决:
- 如果此处出现报错:
TypeError: 'NoneType' object is not callable。原因datasets3.0 无法下载calibrate数据集,解决办法:pip install datasets==2.19.2
等待推理完成,便可以直接在你设置的目标文件夹看到对应的模型文件。
那么推理后的模型和原本的模型区别在哪里呢?最明显的两点是模型文件大小以及占据显存大小。
我们可以输入如下指令查看在当前目录中显示所有子目录的大小:
cd /root/models/
du -sh *
输出结果如下(其余文件夹都是以软链接的形式存在的,不占用空间,故显示为0):

那么原模型大小呢?输入以下指令查看。
cd /root/share/new_models/Shanghai_AI_Laboratory/
du -sh *

那么显存占用情况对比呢?
输入以下指令启动量化后的模型:
lmdeploy chat /root/models/internlm2_5-7b-chat --cache-max-entry-count 0.4
显存占用情况:
对于修改kv cache默认占用之前,即如1.3 LMDeploy验证启动模型文件所示直接启动模型的显存占用情况(23GB):
- 在 BF16 精度下,7B模型权重占用14GB:70×10^9 parameters×2 Bytes/parameter=14GB
- kv cache占用8GB:剩余显存24-14=10GB,kv cache默认占用80%,即10*0.8=8GB
- 其他项1GB
故23GB=权重占用14GB+kv cache占用8GB+其它项1GB
对于修改kv cache占用之后的显存占用情况(19GB):
- bfloat16是16位的浮点数格式,占用2字节(16位)的存储空间。int4是4位的整数格式,占用0.5字节(4位)的存储空间。因此,从bfloat16到int4的转换理论上可以将模型权重的大小减少到原来的1/4,即7B个int4参数仅占用3.5GB的显存。
- kv cache占用16.4GB:剩余显存24-3.5=20.5GB,kv cache默认占用80%,即20.5*0.8=16.4GB
- 其他项约为1GB
故20.9GB=权重占用3.5GB+kv cache占用16.4GB+其它项1GB
6.3.4 W4A16 量化+ KV cache+KV cache 量化
输入以下指令,让我们同时启用量化后的模型、设定kv cache占用和kv cache int4量化:
lmdeploy serve api_server \/root/models/internlm2_5-1_8b-chat-w4a16-4bit \--model-format awq \--quant-policy 4 \--cache-max-entry-count 0.4\--server-name 0.0.0.0 \--server-port 23333 \--tp 1
显存占用11.3GB:

7 LMDeploy之FastAPI与Function call
7.1 API开发
与之前一样,让我们进入创建好的conda环境并输入指令启动API服务器:
conda activate lmdeploy
lmdeploy serve api_server \/root/models/internlm2_5-1_8b-chat-w4a16-4bit \--model-format awq \--cache-max-entry-count 0.4 \--quant-policy 4 \--server-name 0.0.0.0 \--server-port 23333 \--tp 1
保持终端窗口不动,新建一个终端,新建文件:
touch /root/internlm2_5.py
写内容:
# 导入openai模块中的OpenAI类,这个类用于与OpenAI API进行交互
from openai import OpenAI# 创建一个OpenAI的客户端实例,需要传入API密钥和API的基础URL
client = OpenAI(api_key='YOUR_API_KEY', # 替换为你的OpenAI API密钥,由于我们使用的本地API,无需密钥,任意填写即可base_url="http://0.0.0.0:23333/v1" # 指定API的基础URL,这里使用了本地地址和端口
)# 调用client.models.list()方法获取所有可用的模型,并选择第一个模型的ID
# models.list()返回一个模型列表,每个模型都有一个id属性
model_name = client.models.list().data[0].id# 使用client.chat.completions.create()方法创建一个聊天补全请求
# 这个方法需要传入多个参数来指定请求的细节
response = client.chat.completions.create(model=model_name, # 指定要使用的模型IDmessages=[ # 定义消息列表,列表中的每个字典代表一个消息{"role": "system", "content": "你是一个友好的小助手,负责解决问题."}, # 系统消息,定义助手的行为{"role": "user", "content": "帮我讲述一个关于狐狸和西瓜的小故事"}, # 用户消息,询问时间管理的建议],temperature=0.8, # 控制生成文本的随机性,值越高生成的文本越随机top_p=0.8 # 控制生成文本的多样性,值越高生成的文本越多样
)# 打印出API的响应结果
print(response.choices[0].message.content)
执行代码:
conda activate lmdeploy
python /root/internlm2_5.py
终端会输出如下结果:

此时代表我们成功地使用本地API与大模型进行了一次对话,如果切回第一个终端窗口,会看到如下信息,这代表其成功的完成了一次用户问题GET与输出POST:

7.2 Function call
关于Function call,即函数调用功能,它允许开发者在调用模型时,详细说明函数的作用,并使模型能够智能地根据用户的提问来输入参数并执行函数。完成调用后,模型会将函数的输出结果作为回答用户问题的依据。
首先让我们进入创建好的conda环境并启动API服务器。
启动服务:
conda activate lmdeploy
lmdeploy serve api_server \/root/models/internlm2_5-7b-chat \--model-format hf \--quant-policy 0 \--server-name 0.0.0.0 \--server-port 23333 \--tp 1
让我们使用一个简单的例子作为演示。输入如下指令,新建internlm2_5_func.py,写入内容:
from openai import OpenAIdef add(a: int, b: int):return a + bdef mul(a: int, b: int):return a * btools = [{'type': 'function','function': {'name': 'add','description': 'Compute the sum of two numbers','parameters': {'type': 'object','properties': {'a': {'type': 'int','description': 'A number',},'b': {'type': 'int','description': 'A number',},},'required': ['a', 'b'],},}
}, {'type': 'function','function': {'name': 'mul','description': 'Calculate the product of two numbers','parameters': {'type': 'object','properties': {'a': {'type': 'int','description': 'A number',},'b': {'type': 'int','description': 'A number',},},'required': ['a', 'b'],},}
}]
messages = [{'role': 'user', 'content': 'Compute (3+5)*2'}]client = OpenAI(api_key='YOUR_API_KEY', base_url='http://0.0.0.0:23333/v1')
model_name = client.models.list().data[0].id
response = client.chat.completions.create(model=model_name,messages=messages,temperature=0.8,top_p=0.8,stream=False,tools=tools)
print(response)
func1_name = response.choices[0].message.tool_calls[0].function.name
func1_args = response.choices[0].message.tool_calls[0].function.arguments
func1_out = eval(f'{func1_name}(**{func1_args})')
print(func1_out)messages.append({'role': 'assistant','content': response.choices[0].message.content
})
messages.append({'role': 'environment','content': f'3+5={func1_out}','name': 'plugin'
})
response = client.chat.completions.create(model=model_name,messages=messages,temperature=0.8,top_p=0.8,stream=False,tools=tools)
print(response)
func2_name = response.choices[0].message.tool_calls[0].function.name
func2_args = response.choices[0].message.tool_calls[0].function.arguments
func2_out = eval(f'{func2_name}(**{func2_args})')
print(func2_out)
执行代码:
python /root/internlm2_5_func.py
输出结果:

我们可以看出InternLM2.5将输入'Compute (3+5)*2'根据提供的function拆分成了"加"和"乘"两步,第一步调用function add实现加,再于第二步调用function mul实现乘,再最终输出结果16:
相关文章:
大模型 LMDeploy 量化部署
1 模型部署 定义: 在软件工程中,部署通常指的是将开发完毕的软件投入使用的过程。在人工智能领域,模型部署是实现深度学习算法落地应用的关键步骤。简单来说,模型部署就是将训练好的深度学习模型在特定环境中运行的过程。 场景…...
算法设计5_分支限界法
分支限界法 分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树,裁剪那些不能得到最优解的子树以提高搜索效率。 步骤: ① 定义解空间(对解编码); ② 确定解空间的树结构; ③ 按BFS等方式搜索: a.每个活…...
2025年人工智能专业可以考哪些证书呢?
人工智能是目前全球热门的专业领域之一,随着人工智能应用范围的不断扩大,越来越多的人开始关注人工智能相关证书的获取。那么,人工智能专业可以考什么证书呢?本文将为大家介绍人工智能相关证书的种类。 人工智能机器视觉应用工程师…...
仿真技术助力高尔夫球打破传统设计局限,实现球杆强大的功能
Altair近日宣布与业内领先的高尔夫装备制造商 Cleveland Golf 开展合作,以设计新款 HiBore XL 球杆。借助 Altair 先进的仿真与设计技术,Cleveland Golf 不断刷新高尔夫装备的行业标准,并在球杆产品设计方面实现突破。 Cleveland Golf 借助 A…...
微前端架构学习笔记
前言 之前遇到过一个需求,有两个项目分别由两个不同的部门负责,不同技术栈,不同代码仓库: A 项目是官网,负责展示产品亮点等信息,有多个入口可以进入 B 项目中的不同页面。B 项目是业务线,负责…...
DApp开发:从合约到系统快速上线解决方案
在区块链技术迅猛发展的今天,去中心化应用(DApp)作为区块链的一项重要应用,已经吸引了众多开发者和企业的关注。与传统应用程序不同,DApp依托于区块链的去中心化特点,实现了透明、安全、不可篡改等优势&…...
react 中 useState 中的 set 方法异步解决
使用 useEffect 监听状态的改变。 一、异步特性 在批量处理状态更新时,用以提高性能。 二、异步解决 使用useEffect来处理更新后的状态,useEffect钩子在组件渲染后执行,并且会在依赖项(第二个参数)发生变化时重新执…...
UAC2.0 speaker——带反馈端点的 USB speaker(16bit 单声道)
UAC2.0 speaker 系列文章 UAC2.0 speaker——单声道 USB speaker(16bit) UAC2.0 speaker——类特殊请求 UAC2.0 speaker——音量控制 UAC2.0 speaker——多采样率支持 UAC2.0 speaker——24/32bit 支持 UAC2.0 speaker——speaker 数据传输 UAC2.0 speaker——同时支持 16bi…...
docker的简单使用
文章目录 docker简介docker架构镜像和容器镜像有关的常用命令容器相关常用命令 docker简介 Docker是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0协议开源。 Docker可以让开方子打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到…...
Selenium:强大的 Web 自动化测试工具
Selenium:强大的 Web 自动化测试工具 在当今的软件开发和测试领域,自动化工具的重要性日益凸显。Selenium 就是一款备受欢迎的 Web 自动化测试工具,它为开发者和测试人员提供了强大的功能和便利。本文将详细介绍 Selenium 是什么,…...
设计模式 在PLM系统的应用场景介绍
通义灵码 设计模式在 PLM(产品生命周期管理)系统中扮演着重要的角色,可以帮助开发人员更好地组织代码、提高系统的可维护性和扩展性。以下是一些常见的设计模式及其在 PLM 系统中的应用场景: 1. 单例模式(Singleton …...
C#请求https提示未能为 SSL/TLS 安全通道建立信任关系
System.Net.WebException: 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系 ,这个错误通常表明你的应用程序在尝试建立一个安全的 SSL/TLS 连接时遇到了问题。这通常是由于证书验证失败引起的。证书验证失败可能有几个原因: 证书不受信任&#…...
【人工智能】GaussDB数据库技术及应用
文章目录 前言一、数据库的基本概念及发展演进1、数据库概念DB2、数据库管理系统概念DBMS3、数据库与数据库管理系统的关系4、数据库的演进及发展5、数据模型的基本概念6、数据模型的要求和类型7、层次模型的基本概念8、网状模型的基本概念8、关系模型的基本概念9、非关系模型的…...
OpenAI12天 –第3天的实时更新,包括 ChatGPT、Sora、o1 等
OpenAI提前开启了假期,推出了为期 12 天的活动,名为“OpenAI 12 天”。在接下来的一周左右的每一天,OpenAI 都将发布现有产品的新更新以及新软件,包括备受期待的 Sora AI 视频生成器。 OpenAI 首席执行官 Sam Altman 表示&#x…...
删除Yocto中build-x9hp_ms_a12_vemmc_ap2/tmp/work/aarch64-sdrv-linux/package后再编译出错问题
前言: 在yocto编译中,一般会添加自己的package并编译打包到yocto里去。这个包里的内容有时候需要添加或者删除。但是我删除了文件,在编译完成烧录到板子上,里面还有自己删除的文件,于是就在yocto搜索哪个目录有该文件&…...
2024三掌柜赠书活动第三十五期:Redis 应用实例
目录 前言 Redis操作都会,却不知道怎么用? 关于《Redis 应用实例》 编辑推荐 内容简介 作者简介 图书目录 《Redis 应用实例》全书速览 拓展:Redis使用场景 实例1:缓存应用 场景描述 实现方法 具体代码示例 实例2&a…...
观察者模式的理解和实践
引言 在软件开发中,设计模式是开发者们为了解决常见的设计问题而总结出来的一系列最佳实践。观察者模式(Observer Pattern)是其中一种非常经典且使用率极高的设计模式。它主要用于定义对象之间的一对多关系,使得当一个对象的状态发…...
查看Windows系统上的Redis服务器是否设置了密码
查看 Redis 配置文件 1.找到 Redis 配置文件: 通常Redis配置文件名为 redis.windows.conf 或 redis.conf,它位于Redis安装目录中。 2.打开配置文件: 使用文本编辑器(如Notepad、VS Code等)打开该文件。 3.查找 re…...
认识Java中的异常(半成品)
1.异常的概念与体系结构 1.1在Java中,将程序执行过程中发生的不正常行为称为异常.比如 1.算数异常 public class Main1 {public static void main(String[] args){System.out.println(10/0);} } //异常信息为:Exception in thread "main" java.lang.ArithmeticExc…...
生成SSH秘钥文件
git生成文件命令 # 配置用户名和邮箱 git config --global user.name "你的GitHub用户名" git config --global user.email "你的GitHub邮箱"# 生成ssh-key ssh-keygen -t rsa -C “你的GitHub邮箱" # 验证 ssh -T gitgithub .com 第一步:…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
