LLM-text_generation_interfence

本文介绍了Huggingface中的text-generation-interference项目,涉及不同模型的加载方式(如ChatGLM和RWKV),以及项目架构中Launcher、Router和Server的角色。重点讨论了如何通过Launcher启动服务,Router的路由功能,以及Serve端的接口和缓存优化技术,如Flash-Attention和bitsandbytes库的应用。

今天来看看,Huggingface 中的一个项目 text-generation-interfence 。

它的特点在 github 中的很显眼的位置,就不在这里赘述了。其中如果有一些不太清楚的名词,可以查看 最后一部分——扩展资料,或许有你想要的东西。

前置知识——模型加载

不同的 transformer 训练不同的 model,同理,不同的 model 需要被不同的 transformer 加载:

例如 ChatGLM 和 RWKV,通过代码看,ChatGLM 是通过常规的 transformer 来加载模型的。

RWKV 是基于 transformer 的变种,是将 transformer 中的 self-attention 替换为 Position Encoding 和 TimeMix

self-attention 的含义,可以查看 LLM 100 关键词; Position Encoding 和  TimeMix 的含义,可以查看这个  链接

总体来说,不同的模型,由不同的 transformer 加载。

################# CHATGLM 加载模型的方法 ##################
>>> from transformers import AutoTokenizer, AutoModel
>>> tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True)
>>> model = AutoModel.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True).half().cuda()
>>> model = model.eval()
>>> response, history = model.chat(tokenizer, "你好", history=[])
>>> print(response)
你好 !我是人工智能助手 ChatGLM-6B,很高兴见到你,欢迎问我任何问题。
>>> response, history = model.chat(tokenizer, "晚上睡不着应该怎么办", history=history)
>>> print(response)

################# RWKV 加载模型的方法  ##################
from rwkv.model import RWKV                         # pip install rwkv
model = RWKV(model='/fsx/BlinkDL/HF-MODEL/rwkv-4-pile-1b5/RWKV-4-Pile-1B5-20220903-8040', strategy='cuda fp16')

out, state = model.forward([187, 510, 1563, 310, 247], None)   # use 20B_tokenizer.json
print(out.detach().cpu().numpy())                   # get logits
out, state = model.forward([187, 510], None)
out, state = model.forward([1563], state)           # RNN has state (use deepcopy if you want to clone it)
out, state = model.forward([310, 247], state)
print(out.detach().cpu().numpy())  

项目架构

整个项目由三部分组成:

  • launcher
  • router
  • serve

Launcher、Router和Server(Python gRPC服务)都是服务的组成部分,它们各自承担不同的职责,共同提供一个完整的文本生成推理服务。以下是它们之间的关系:

  • Launcher:这是服务的启动器,它负责启动和运行服务。它可能会启动 Router,并设置好所有的路由规则。然后,它会监听指定的地址和端口,等待并处理来自客户端的连接。当接收到一个连接时,它会将连接转发给Router 进行处理。
  • Router:这是服务的中间件,它的主要职责是路由和调度请求。当客户端发送一个请求时,Router 会接收这个请求,然后根据请求的内容和当前的系统状态,决定将请求路由到哪个处理器进行处理。这个处理器可能是Server 中的一个 gRPC 方法。Router 的目的是有效地管理和调度系统资源,提高系统的并发处理能力和响应速度。
  • Server(Python gRPC服务):这是服务的核心部分,它实现了文本生成推理的主要逻辑。它提供了一些 gRPC 方法,如 Info、Health、ServiceDiscovery、ClearCache、FilterBatch、Prefill 和 Decode,这些方法用于处理客户端的请求,执行文本生成的推理任务,并返回结果。这个服务可能运行在一个单独的服务器上,独立于Launcher 和 Router。

launcher 启动器

顾名思义,launcher 启动器,就是负责启动的程序,主要做以下工作:(在 launcher/src/main.rs 中)

  1. 通过 serve 的命令下载模型,代码中执行的函数为: download_convert_model(&args, running.clone())?;
  2. 启动 serve ,代码中执行的函数为: spawn_shards(...)
  3. 启动 router,代码中执行的函数为:spawn_webserver(args, shutdown.clone(), &shutdown_receiver)?;

所以,router 和 serve 负责主要的逻辑处理与模型调用。在项目中有一个架构图,可以更加直观的认识到它们之间的关系,其架构如下图所示:

router 路由

可以看到 router 这个 webserver 负责接收请求,然后放在 buffer 中,等收集到一定量的数据后,一个 batch 一个 batch 的以 rpc 的方式发送给 serve 的去处理。

对外暴露的 url 很少同时也很精简,只有四个:

  1. /generate : 一次性生成所有回答的 token
  2. /generate_stream :流式的生成所回答的 token (就类似于 chatgpt 一样,一个字一个字的显现)
  3. /metrics : 获取该服务的 metrics 信息。
  4. /info :获取模型的相关信息

serve

在图中,也可以看到,在每个卡上都启动了一个 serve,被叫做 shard,这也是 launcher 的作用之一,通过参数来决定 serve 启动的情况。

在 serve 端的代码,有两个命令行启动脚本(serve/text_generation_server/cli.py):

# 下载模型权重的方法
@app.command()
def download_weights(
...
)
...

# 启动 serve 服务的方法
@app.command()
def serve(
...
)
...

其实内部逻辑也很简单,稍微处理一下数据后,直接调用 model 的接口来处理。

Server 对外暴露了一下接口:(这里说的对外,指的是 router )

  1. Info : 返回 model 信息
  2. Health : 检查 serve 的健康状况
  3. ServiceDiscovery : 服务发现,实现也很简单,将所有的 serve 的地址发送出去
  4. ClearCache : 清除 cache 中的数据 (cache 的功能再看)
  5. FilterBatch
  6. Prefill
  7. Decode
cache 中的存储单位是 batch (在 router 中提过,router 就是一个 batch 一个 batch 来传的。)

内部接口的含义

再然后,就剩下最重要的三个功能:FilterBatch、Prefill、Decode

FilterBatch 流程如下:(使用场景还不太清楚)

先从 cache 中以 batch_id 获取特定的 batch 再从 batch 中过滤出我们想要留下的 request_ids(这里的 request_id 指的是 客户端发送的请求 id ) 过滤后,再将 batch 放回 cache 中。

Prefill 的主要功能是:

  1. 从 router 接收 batch ,然后根据模型给的 from_pb 方法整理一下 batch 中的信息 并且 通过 tokenizer 来将相应的词转化成词向量。(from_pb 方法之后在说)
  2. 将 整理后的 batch 信息,通过 model 的 generate_token 方法,生成新的 token (也就是预测的词),同时也会返回 next_batch。(generate_token 方法之后在说)
  3. 将 next_batch 存放到 cache 中。
  4. 返回消息。

Decode 的功能也很简单,主要功能是:

  1. 通过 request 传入的 batch.id 从 cache 中获取 batch
  2. 将这些 batch 通过 model 的 generate_token 方法,生成新的 token,同时会返回 next_batch。
  3. 将 next_batch 存放到 cache 中。
  4. 返回消息。

主要是第一步,从 缓存中获取 batch,这样有两个好处:第一,request 不需要传输历史的 信息,上下文都在 cache 中;第二,cache 中缓存的是 词向量 的信息,所以,在每次预测词的时候,只需要将传入的 信息 通过词嵌入 转化成 词向量,其他的信息就不需要再做转化了,减少了大量的计算工作。

扩展资料

flash-attation

Flash-Attention 也是 Huggingface 中比较出名的一个项目,它是一种优化技术,使用了一种特殊的计算方法,可以在不影响模型精度的情况下,显著提高计算速度。这使得模型可以更快地处理大量数据。

优化的过程如下:

在传统的 Transformer 模型中,注意力机制需要计算一个大小为 (n^2) 的矩阵,其中 n 是序列的长度。这个过程在计算上是非常昂贵的,特别是对于长序列。Flash-Attention 通过使用一种叫做 "softmax decomposition" 的技术,将这个复杂的计算过程分解为几个更简单的步骤。这种方法可以显著提高计算速度,而不会影响模型的精度。

soft decomposition 在 100 words 中介绍一下吧,在这个引用一下。

不仅如此,在传统的 Transformer 模型中,注意力机制需要存储一个大小为 (n^2) 的矩阵,这在内存上是非常昂贵的,特别是对于长序列。Flash-Attention 还使用了 “checkpointing” 来减少内存的使用。

同理, checkpointing 在 100 words 中也介绍一下,在这里引用。

bitsandbytes

"bitsandbytes" 是一个库,它提供了一些用于 PyTorch 的 8 位 CUDA 函数。这个库的主要目标是提供一种高效的方式来处理和存储大型模型的权重,特别是在进行大规模训练或推理时。

"bitsandbytes" 的一个关键特性是它支持 4 位和 8 位的量化。量化 是一种减少模型大小和计算需求的技术,它通过将模型的权重从 32 位浮点数(通常用于训练神经网络的数据类型)减少到更小的位数(如 8 位或 4 位)来实现。这种方法可以显著减少模型的内存占用,从而使模型能够在更小的硬件上运行,或者处理更大的数据集。

"bitsandbytes" 库的另一个重要特性是它支持在 GPU 上进行计算,这使得它可以充分利用 GPU 的并行计算能力,从而提高计算速度。

总的来说,"bitsandbytes" 是一个强大的工具,它可以帮助研究人员和开发人员更有效地处理和存储大型模型的权重,从而使这些模型能够在更小的硬件上运行,或者处理更大的数据集。

Safetensors

"Safetensors" 是一个用于保存和加载张量的库,它支持最常见的框架(包括 PyTorchTensorFlow、JAX、PaddlePaddle 和 NumPy)。这个库的主要目标是提供一种安全和高效的方式来处理张量,特别是在进行模型保存和加载时。

"Safetensors" 的一个重要特性是它可以安全地加载文件。这是因为它不使用 Python 的 pickle 库,pickle 库在处理文件时存在安全风险,可能会执行恶意代码。相反,"Safetensors" 使用了一种安全的方法来处理文件,从而避免了这种风险。

此外,"Safetensors" 还支持懒加载(lazy loading),这意味着它可以在需要时才加载部分张量,而不是一次性加载整个张量。这种特性可以提高处理大型模型的效率,特别是在分布式环境中。

import torch
from safetensors.torch import load_file, save_file

weights = {"embeddings": torch.zeros((10, 100))}
save_file(weights, "model.safetensors")
weights2 = load_file("model.safetensors")

原文地址:

LLM-text_generation_interfence - 知乎

<think>好的,我现在需要解决用户遇到的TensorRTLLM运行时出现的未识别参数错误。用户运行run.py时使用了--model llm参数,但系统提示无法识别这个参数。首先,我应该考虑可能的原因,然后逐步排查问题。 首先,用户提到错误是“unrecognized arguments: --model llm”,这说明脚本run.py没有定义这个参数。可能的情况有几个: 1. **参数名称错误**:用户可能拼错了参数名。例如,正确的参数可能是--model_name或者--model_type,而不是--model。需要检查脚本的文档或代码中的参数定义。 2. **脚本版本问题**:用户可能使用的TensorRTLLM版本较旧,不支持--model参数。查看官方文档或更新日志,确认该参数是否在最新版本中添加。 3. **代码位置错误**:参数可能需要在特定位置或子命令下使用。例如,有些脚本需要先指定子命令,如run.py train --model llm,而不是直接放在主命令后面。 接下来,我需要用户提供更多信息来确认问题,比如run.py的帮助信息,或者代码中参数解析的部分。但根据现有的引用,用户之前遇到的类似问题如引用[1]中的“--local_rank=0”未识别,可能涉及多GPU训练时的参数设置,需要正确初始化进程组。引用[3]提到安装依赖的问题,可能环境配置不正确也会导致参数解析失败。 可能的解决方案步骤: 1. **检查参数名称**:运行python run.py --help查看可用的参数列表,确认是否存在--model参数,或者是否有拼写错误。 2. **查看脚本文档**:参考TensorRTLLM的官方文档或示例,确认参数的正确用法。例如,可能需要指定模型路径而非名称,或者使用其他参数如--engine_dir。 3. **更新代码库**:如果使用的是旧版本,尝试git pull或安装最新版本,确保支持所需的参数。 4. **检查参数位置**:确认参数是否需要在子命令之后。例如,是否有像run.py generate --model llm这样的结构。 5. **环境配置**:确保所有依赖已正确安装,特别是argparse或相关参数解析库的版本是否兼容。 如果用户确认参数正确但依然报错,可能需要检查run.py的源码,查看argparse的配置。例如,是否存在add_argument('--model')的定义,或者是否有条件判断导致参数未被正确解析。 总结来说,先通过--help确认参数是否存在,再检查版本和文档,最后查看代码中的参数定义,逐步排除可能的原因。</think>针对TensorRTLLM运行时报错`unrecognized arguments --model llm`的问题,以下是分步解决方案: ### 1. 确认参数名称与脚本兼容性 - **检查参数名称**:运行以下命令查看`run.py`支持的参数列表: ```bash python run.py --help ``` 确认输出中是否包含`--model`参数。若不存在,可能是参数名称拼写错误或脚本版本不支持。例如,正确参数可能是`--model_name`或`--model_path`[^1]。 ### 2. 验证脚本版本与文档一致性 - **查看官方文档**:访问TensorRTLLM的GitHub仓库或文档,确认`--model`是否为最新版本支持的参数。若文档中未提及,可能需要改用其他参数,例如: ```bash python run.py --engine_dir ./llm-engine --tokenizer ./tokenizer ``` 其中`--engine_dir`指定模型引擎路径[^3]。 ### 3. 检查参数作用域与子命令 - **确认参数位置**:某些脚本需要先指定子命令(如`generate`、`serve`),例如: ```bash python run.py generate --model llm ``` 若未指定子命令直接添加参数,可能导致解析失败[^2]。 ### 4. 升级代码库与依赖 - **更新代码仓库**: ```bash git pull origin main pip install -r requirements.txt --upgrade ``` 确保依赖版本与脚本兼容,避免因库版本过旧导致的参数解析问题。 ### 5. 检查代码中的参数解析逻辑 - **直接查看`run.py`源码**:搜索`argparse`相关的代码段,例如: ```python parser = argparse.ArgumentParser() parser.add_argument('--model', type=str, help='Model name') # 确认是否存在此行 ``` 若未定义`--model`参数,需修改代码或改用其他参数。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值