Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TensorRT-LLM的支持在计划中吗 #132

Closed
HLSS-Hen opened this issue Jun 9, 2024 · 17 comments
Closed

TensorRT-LLM的支持在计划中吗 #132

HLSS-Hen opened this issue Jun 9, 2024 · 17 comments
Assignees

Comments

@HLSS-Hen
Copy link

HLSS-Hen commented Jun 9, 2024

从GLM到chatGLM3都提供了TensorRT-LLM的支持,请问这代模型是否会继续提供

@zRzRzRzRzRzRzR zRzRzRzRzRzRzR self-assigned this Jun 10, 2024
@zRzRzRzRzRzRzR
Copy link
Member

目前直接用GLM-3的转换GLM-4的就行了吧

@HLSS-Hen
Copy link
Author

@zRzRzRzRzRzRzR 谢谢,用上--chatglm_version chatglm3后,转换、构建成功。
现有的trtllm(r0.10.0),SamplingConfig.end_idint形,而GLM4 MODEL.chat()里面用的 eos_token_id 有三个: [tokenizer.eos_token_id, tokenizer.convert_tokens_to_ids("<|user|>"), tokenizer.convert_tokens_to_ids("<|observation|>")]
实测 glm-4-9b-chat 要用 <|user|>(151336) 才给到end_id才可以。或者把三个同时给 stop_words_list,最终多生成出一个 <|user|>(151336) 要截去。而在glm-4v-9b 并不需要,直接给eos_token_id(151329)就行。

@zRzRzRzRzRzRzR
Copy link
Member

不能直接一个字不改,,还是要参考我们的demo的,stop id 有三个哈

@HLSS-Hen
Copy link
Author

这里三个stop_id是为什么;对于TensorRT-LLM,在推理的时候,SamplingConfig 只接受一个 int 类型的 end_id,或者提供stop_words_list

在我的简单尝试中,在三个stop id选一个给到SamplingConfig.end_id的情况下,对比GLM-4和GLM-4V,前者要输入 <|user|>(15336)可以正常工作,而后者输入 <|endoftext|> (151329)可以正常工作。

即,如果只把 <|endoftext|> (151329) 给到 end_id,GLM-4无法正确停下,GLM-4V可以。

在给了 end_id=151329 情况下:

  • 给到 stop_words_list=tensorrt_llm.runtime.to_word_list_format([["<|endoftext|>"],["<|user|>"],["<|observation|>"]],tokenizer) 无法正确停止
 array([[[151329], [     1]],
        [[151336], [     1]],
        [[151338], [     1]]], dtype=int32)
  • 给到 stop_words_list=[[151329],[151336],[151338]] 可以停止,但是会多一个 <|user|>(15336)` token被输出,需要手动截去。

@zRzRzRzRzRzRzR
Copy link
Member

如果只能写一个,都用<|user|>
这个问题我已经放到排期了,之后会处理,感谢你的耐心尝试

@diaoyechao
Copy link

@zRzRzRzRzRzRzR 谢谢,用上--chatglm_version chatglm3后,转换、构建成功。 现有的trtllm(r0.10.0),SamplingConfig.end_idint形,而GLM4 MODEL.chat()里面用的 eos_token_id 有三个: [tokenizer.eos_token_id, tokenizer.convert_tokens_to_ids("<|user|>"), tokenizer.convert_tokens_to_ids("<|observation|>")]。 实测 glm-4-9b-chat 要用 <|user|>(151336) 才给到end_id才可以。或者把三个同时给 stop_words_list,最终多生成出一个 <|user|>(151336) 要截去。而在glm-4v-9b 并不需要,直接给eos_token_id(151329)就行。

glm-4v-9b可以转换吗?

@HLSS-Hen
Copy link
Author

@zRzRzRzRzRzRzR 谢谢,用上--chatglm_version chatglm3后,转换、构建成功。 现有的trtllm(r0.10.0),SamplingConfig.end_idint形,而GLM4 MODEL.chat()里面用的 eos_token_id 有三个: [tokenizer.eos_token_id, tokenizer.convert_tokens_to_ids("<|user|>"), tokenizer.convert_tokens_to_ids("<|observation|>")]。 实测 glm-4-9b-chat 要用 <|user|>(151336) 才给到end_id才可以。或者把三个同时给 stop_words_list,最终多生成出一个 <|user|>(151336) 要截去。而在glm-4v-9b 并不需要,直接给eos_token_id(151329)就行。

glm-4v-9b可以转换吗?

可以,但是tensorrt-llm不支持多模态。

@diaoyechao
Copy link

@zRzRzRzRzRzRzR 谢谢,用上--chatglm_version chatglm3后,转换、构建成功。 现有的trtllm(r0.10.0),SamplingConfig.end_idint形,而GLM4 MODEL.chat()里面用的 eos_token_id 有三个: [tokenizer.eos_token_id, tokenizer.convert_tokens_to_ids("<|user|>"), tokenizer.convert_tokens_to_ids("<|observation|>")]。 实测 glm-4-9b-chat 要用 <|user|>(151336) 才给到end_id才可以。或者把三个同时给 stop_words_list,最终多生成出一个 <|user|>(151336) 要截去。而在glm-4v-9b 并不需要,直接给eos_token_id(151329)就行。

glm-4v-9b可以转换吗?

可以,但是tensorrt-llm不支持多模态。

没太明白,glm-4v-9b不就是多模态的模型吗?

@HLSS-Hen
Copy link
Author

@zRzRzRzRzRzRzR 谢谢,用上--chatglm_version chatglm3后,转换、构建成功。 现有的trtllm(r0.10.0),SamplingConfig.end_idint形,而GLM4 MODEL.chat()里面用的 eos_token_id 有三个: [tokenizer.eos_token_id, tokenizer.convert_tokens_to_ids("<|user|>"), tokenizer.convert_tokens_to_ids("<|observation|>")]。 实测 glm-4-9b-chat 要用 <|user|>(151336) 才给到end_id才可以。或者把三个同时给 stop_words_list,最终多生成出一个 <|user|>(151336) 要截去。而在glm-4v-9b 并不需要,直接给eos_token_id(151329)就行。

glm-4v-9b可以转换吗?

可以,但是tensorrt-llm不支持多模态。

没太明白,glm-4v-9b不就是多模态的模型吗?

glm-4v-9b模型多一个输入images:torch.Tensor,如果不为空则通过视觉骨干(EVA2CLIPModel)将其编码后嵌入,这部分是tensorrt-llm不支持的。

    def forward(
            self,
            input_ids: torch.LongTensor = None,
            images: torch.Tensor = None,
            position_ids: Optional[torch.Tensor] = None,
            attention_mask: Optional[torch.BoolTensor] = None,
            full_attention_mask: Optional[torch.BoolTensor] = None,
            past_key_values: Optional[Tuple[Tuple[torch.Tensor, torch.Tensor], ...]] = None,
            inputs_embeds: Optional[torch.Tensor] = None,
            use_cache: Optional[bool] = None,
            output_hidden_states: Optional[bool] = None,
            return_dict: Optional[bool] = None,
    ) -> Union[Tuple, BaseModelOutputWithPast]:
        """take care of image_encode, position_ids and (attention_mask = None is fine)"""

        # generate mode with past_key_values. the image features are already mapped
        if past_key_values is None:
            # not allow for inputs_embeds, because we want to process image feature
            assert input_ids is not None and inputs_embeds is None, f"{input_ids} {inputs_embeds}"
            if not is_empty(images):  # multi-modality
                image_size: int = self.config.vision_config['image_size']
                patch_size: int = self.config.vision_config['patch_size']
                num_patches = (image_size // patch_size // 2) ** 2
                assert len(input_ids) == len(images), f"{len(input_ids)} {len(images)}"
                inputs_embeds = self.embedding(input_ids)

                images = images.to(dtype=inputs_embeds.dtype)
                images_features = self.vision(images)

                if position_ids is None:
                    position_ids = self.get_position_ids(input_ids, device=inputs_embeds.device)
                new_input_embeds, new_position_ids = [], []

                for i in range(len(input_ids)):
                    input_id = input_ids[i].tolist()
                    boi_token_pos, eoi_token_pos = input_id.index(self.config.boi_token_id), input_id.index(
                        self.config.eoi_token_id)
                    assert eoi_token_pos - boi_token_pos == 2
                    new_input_embeds.append(torch.cat(
                        (inputs_embeds[i, :boi_token_pos], images_features[i].to(inputs_embeds.device),
                         inputs_embeds[i, eoi_token_pos + 1:])))
                    new_position_ids.append(torch.cat(
                        (position_ids[i, :boi_token_pos + 1], position_ids[i, boi_token_pos + 1].repeat(num_patches),
                         position_ids[i, eoi_token_pos:])
                    ))
                inputs_embeds = torch.stack(new_input_embeds, dim=0)
                position_ids = torch.stack(new_position_ids, dim=0)

@diaoyechao
Copy link

@zRzRzRzRzRzRzR 谢谢,用上--chatglm_version chatglm3后,转换、构建成功。 现有的trtllm(r0.10.0),SamplingConfig.end_idint形,而GLM4 MODEL.chat()里面用的 eos_token_id 有三个: [tokenizer.eos_token_id, tokenizer.convert_tokens_to_ids("<|user|>"), tokenizer.convert_tokens_to_ids("<|observation|>")]。 实测 glm-4-9b-chat 要用 <|user|>(151336) 才给到end_id才可以。或者把三个同时给 stop_words_list,最终多生成出一个 <|user|>(151336) 要截去。而在glm-4v-9b 并不需要,直接给eos_token_id(151329)就行。

glm-4v-9b可以转换吗?

可以,但是tensorrt-llm不支持多模态。

没太明白,glm-4v-9b不就是多模态的模型吗?

glm-4v-9b模型多一个输入images:torch.Tensor,如果不为空则通过视觉骨干(EVA2CLIPModel)将其编码后嵌入,这部分是tensorrt-llm不支持的。

    def forward(
            self,
            input_ids: torch.LongTensor = None,
            images: torch.Tensor = None,
            position_ids: Optional[torch.Tensor] = None,
            attention_mask: Optional[torch.BoolTensor] = None,
            full_attention_mask: Optional[torch.BoolTensor] = None,
            past_key_values: Optional[Tuple[Tuple[torch.Tensor, torch.Tensor], ...]] = None,
            inputs_embeds: Optional[torch.Tensor] = None,
            use_cache: Optional[bool] = None,
            output_hidden_states: Optional[bool] = None,
            return_dict: Optional[bool] = None,
    ) -> Union[Tuple, BaseModelOutputWithPast]:
        """take care of image_encode, position_ids and (attention_mask = None is fine)"""

        # generate mode with past_key_values. the image features are already mapped
        if past_key_values is None:
            # not allow for inputs_embeds, because we want to process image feature
            assert input_ids is not None and inputs_embeds is None, f"{input_ids} {inputs_embeds}"
            if not is_empty(images):  # multi-modality
                image_size: int = self.config.vision_config['image_size']
                patch_size: int = self.config.vision_config['patch_size']
                num_patches = (image_size // patch_size // 2) ** 2
                assert len(input_ids) == len(images), f"{len(input_ids)} {len(images)}"
                inputs_embeds = self.embedding(input_ids)

                images = images.to(dtype=inputs_embeds.dtype)
                images_features = self.vision(images)

                if position_ids is None:
                    position_ids = self.get_position_ids(input_ids, device=inputs_embeds.device)
                new_input_embeds, new_position_ids = [], []

                for i in range(len(input_ids)):
                    input_id = input_ids[i].tolist()
                    boi_token_pos, eoi_token_pos = input_id.index(self.config.boi_token_id), input_id.index(
                        self.config.eoi_token_id)
                    assert eoi_token_pos - boi_token_pos == 2
                    new_input_embeds.append(torch.cat(
                        (inputs_embeds[i, :boi_token_pos], images_features[i].to(inputs_embeds.device),
                         inputs_embeds[i, eoi_token_pos + 1:])))
                    new_position_ids.append(torch.cat(
                        (position_ids[i, :boi_token_pos + 1], position_ids[i, boi_token_pos + 1].repeat(num_patches),
                         position_ids[i, eoi_token_pos:])
                    ))
                inputs_embeds = torch.stack(new_input_embeds, dim=0)
                position_ids = torch.stack(new_position_ids, dim=0)

意思是只转换了LLM的部分?那转换后还能正常使用吗?

@HLSS-Hen
Copy link
Author

@zRzRzRzRzRzRzR 谢谢,用上--chatglm_version chatglm3后,转换、构建成功。 现有的trtllm(r0.10.0),SamplingConfig.end_idint形,而GLM4 MODEL.chat()里面用的 eos_token_id 有三个: [tokenizer.eos_token_id, tokenizer.convert_tokens_to_ids("<|user|>"), tokenizer.convert_tokens_to_ids("<|observation|>")]。 实测 glm-4-9b-chat 要用 <|user|>(151336) 才给到end_id才可以。或者把三个同时给 stop_words_list,最终多生成出一个 <|user|>(151336) 要截去。而在glm-4v-9b 并不需要,直接给eos_token_id(151329)就行。

glm-4v-9b可以转换吗?

可以,但是tensorrt-llm不支持多模态。

没太明白,glm-4v-9b不就是多模态的模型吗?

glm-4v-9b模型多一个输入images:torch.Tensor,如果不为空则通过视觉骨干(EVA2CLIPModel)将其编码后嵌入,这部分是tensorrt-llm不支持的。

    def forward(
            self,
            input_ids: torch.LongTensor = None,
            images: torch.Tensor = None,
            position_ids: Optional[torch.Tensor] = None,
            attention_mask: Optional[torch.BoolTensor] = None,
            full_attention_mask: Optional[torch.BoolTensor] = None,
            past_key_values: Optional[Tuple[Tuple[torch.Tensor, torch.Tensor], ...]] = None,
            inputs_embeds: Optional[torch.Tensor] = None,
            use_cache: Optional[bool] = None,
            output_hidden_states: Optional[bool] = None,
            return_dict: Optional[bool] = None,
    ) -> Union[Tuple, BaseModelOutputWithPast]:
        """take care of image_encode, position_ids and (attention_mask = None is fine)"""

        # generate mode with past_key_values. the image features are already mapped
        if past_key_values is None:
            # not allow for inputs_embeds, because we want to process image feature
            assert input_ids is not None and inputs_embeds is None, f"{input_ids} {inputs_embeds}"
            if not is_empty(images):  # multi-modality
                image_size: int = self.config.vision_config['image_size']
                patch_size: int = self.config.vision_config['patch_size']
                num_patches = (image_size // patch_size // 2) ** 2
                assert len(input_ids) == len(images), f"{len(input_ids)} {len(images)}"
                inputs_embeds = self.embedding(input_ids)

                images = images.to(dtype=inputs_embeds.dtype)
                images_features = self.vision(images)

                if position_ids is None:
                    position_ids = self.get_position_ids(input_ids, device=inputs_embeds.device)
                new_input_embeds, new_position_ids = [], []

                for i in range(len(input_ids)):
                    input_id = input_ids[i].tolist()
                    boi_token_pos, eoi_token_pos = input_id.index(self.config.boi_token_id), input_id.index(
                        self.config.eoi_token_id)
                    assert eoi_token_pos - boi_token_pos == 2
                    new_input_embeds.append(torch.cat(
                        (inputs_embeds[i, :boi_token_pos], images_features[i].to(inputs_embeds.device),
                         inputs_embeds[i, eoi_token_pos + 1:])))
                    new_position_ids.append(torch.cat(
                        (position_ids[i, :boi_token_pos + 1], position_ids[i, boi_token_pos + 1].repeat(num_patches),
                         position_ids[i, eoi_token_pos:])
                    ))
                inputs_embeds = torch.stack(new_input_embeds, dim=0)
                position_ids = torch.stack(new_position_ids, dim=0)

意思是只转换了LLM的部分?那转换后还能正常使用吗?

无法接受图片输入,其他应该正常。

@zRzRzRzRzRzRzR
Copy link
Member

trt-llm只支持我们的chat模型,视觉模型还没有支持

@zRzRzRzRzRzRzR zRzRzRzRzRzRzR closed this as not planned Won't fix, can't repro, duplicate, stale Jun 17, 2024
@15929482853
Copy link

@HLSS-Hen 你好,请问你有没有尝试glm4用trt-llm进行awq量化,我这边量化之后推理结果为乱码

@HLSS-Hen
Copy link
Author

@15929482853 我这里实测没有太大问题,你可能没有正确使用tokenizer或者提供了错误的采样参数。

一些细节:
tensorrt-llm: v0.10.0
5800x3d, 128GB RAM, 3090

mamba create -n temp python=3.10
mamba activate temp
cd TENSORT_LLM_PATH
pip install -r examples/chatglm/requirements.txt
examples/quantization/install_requirements.sh
pip install "cython<3.0.0" wheel && pip install pyyaml==5.4.1 --no-build-isolation
pip install -r requirements.txt

魔改下部分package代码:

  • site-packages/modelopt/torch/export/model_config_export.py > export_tensorrt_llm_checkpoint
    model=model -> model=model.cpu() 24G显存是真的会爆的

  • site-packages/tensorrt_llm/models/chatglm/model.py > ChatGLMForCausalLM > check_config
    config.set_if_not_exist('chatglm_version', 'chatglm3') -> config.chatglm_version = "chatglm3" 强制套用chatglm3相关代码

然后执行量化和构建

python examples/quantization/quantize.py --model_dir /WORKSPACE/hf_ckpt/glm-4-9b-chat/ --dtype float16 --qformat int4_awq --output_dir /WORKSPACE/trt_ckpt/glm-4-9b-chat-awq --batch_size 8
trtllm-build --checkpoint_dir /WORKSPACE/trt_ckpt/glm-4-9b-chat-awq/ --gemm_plugin float16 --output_dir /WORKSPACE/trt_engines/glm-4-9b-chat-awq

简单测试:

from transformers import AutoTokenizer
import torch

tokenizer = AutoTokenizer.from_pretrained("/WORKSPACE/hf_ckpt/glm-4-9b-chat", trust_remote_code=True)

import tensorrt_llm
runner = tensorrt_llm.runtime.ModelRunnerCpp.from_dir("/WORKSPACE/trt_engines/glm-4-9b-chat-awq/")

history = [
        {'role': 'system', 'content': '一些提示词。。。'}, 
        # 可选,few shots
]

conversation = history.copy()
conversation.append({"role": "user", "content": "用户输入"})


inputs = tokenizer.apply_chat_template(conversation,
                                       add_generation_prompt=True,
                                       tokenize=True,
                                       return_tensors="pt",
                                       return_dict=True
                                       )

inputs = inputs.to("cuda")

with torch.no_grad():
    outputs = runner.generate([inputs["input_ids"][0]],
                    max_new_tokens=128,
                    end_id=151336, # 参考上面的讨论
                    pad_id=151329,
                    temperature=0,
                    top_p=0,
                    num_beams=1,
                    output_sequence_lengths=True,
                    return_dict=True,
                    exclude_input_in_output=True
                    )

print(tokenizer.decode(outputs["output_ids"][0,0][inputs["input_ids"].shape[1]:outputs["sequence_lengths"][0]]))

@15929482853
Copy link

@15929482853 我这里实测没有太大问题,你可能没有正确使用tokenizer或者提供了错误的采样参数。

一些细节: tensorrt-llm: v0.10.0 5800x3d, 128GB RAM, 3090

mamba create -n temp python=3.10
mamba activate temp
cd TENSORT_LLM_PATH
pip install -r examples/chatglm/requirements.txt
examples/quantization/install_requirements.sh
pip install "cython<3.0.0" wheel && pip install pyyaml==5.4.1 --no-build-isolation
pip install -r requirements.txt

魔改下部分package代码:

  • site-packages/modelopt/torch/export/model_config_export.py > export_tensorrt_llm_checkpoint
    model=model -> model=model.cpu() 24G显存是真的会爆的
  • site-packages/tensorrt_llm/models/chatglm/model.py > ChatGLMForCausalLM > check_config
    config.set_if_not_exist('chatglm_version', 'chatglm3') -> config.chatglm_version = "chatglm3" 强制套用chatglm3相关代码

然后执行量化和构建

python examples/quantization/quantize.py --model_dir /WORKSPACE/hf_ckpt/glm-4-9b-chat/ --dtype float16 --qformat int4_awq --output_dir /WORKSPACE/trt_ckpt/glm-4-9b-chat-awq --batch_size 8
trtllm-build --checkpoint_dir /WORKSPACE/trt_ckpt/glm-4-9b-chat-awq/ --gemm_plugin float16 --output_dir /WORKSPACE/trt_engines/glm-4-9b-chat-awq

简单测试:

from transformers import AutoTokenizer
import torch

tokenizer = AutoTokenizer.from_pretrained("/WORKSPACE/hf_ckpt/glm-4-9b-chat", trust_remote_code=True)

import tensorrt_llm
runner = tensorrt_llm.runtime.ModelRunnerCpp.from_dir("/WORKSPACE/trt_engines/glm-4-9b-chat-awq/")

history = [
        {'role': 'system', 'content': '一些提示词。。。'}, 
        # 可选,few shots
]

conversation = history.copy()
conversation.append({"role": "user", "content": "用户输入"})


inputs = tokenizer.apply_chat_template(conversation,
                                       add_generation_prompt=True,
                                       tokenize=True,
                                       return_tensors="pt",
                                       return_dict=True
                                       )

inputs = inputs.to("cuda")

with torch.no_grad():
    outputs = runner.generate([inputs["input_ids"][0]],
                    max_new_tokens=128,
                    end_id=151336, # 参考上面的讨论
                    pad_id=151329,
                    temperature=0,
                    top_p=0,
                    num_beams=1,
                    output_sequence_lengths=True,
                    return_dict=True,
                    exclude_input_in_output=True
                    )

print(tokenizer.decode(outputs["output_ids"][0,0][inputs["input_ids"].shape[1]:outputs["sequence_lengths"][0]]))

看了一下,我们的流程是一样的,我这块没什么问题。
唯一的不同是我是用的trt-llm版本是0.9.0,不知道这个有没有影响,我准备使用和你一样的环境再尝试一下,感谢回复!

@scdotbox
Copy link

如果把 glm-4v-9b 拆成 2个部分,一个是前面的 vit,获得 image embedding,然后把 images:torch.Tensor 合并到 input_ids 模块,可以复用 chat 模型吗?这样是不是可以直接使用 trtllm 的 glm4 ?

@HLSS-Hen
Copy link
Author

@scdotbox 不可行,图像的嵌入,不是嵌入为inputs_ids,而是1602 x 4096的特征,同时需要特殊的位置编码。
虽然官方Torch源码里面可以通过传入 position_idsinputs_embeds或者传入past_key_values,实现将图像嵌入操作分离。但是tensorrt_llm那里不支持,可以等tensorrt_llm那里支持。
trt-llm v0.10.0已经引入 CogVLM ;CogGLM2也在issue被请求加入,GLM-4V或许要在CogVLM2之后。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants