<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          多模態(tài)模型(VLM)部署方法拋磚引玉

          共 38283字,需瀏覽 77分鐘

           ·

          2024-07-10 22:00

          ↑ 點擊藍字 關(guān)注極市平臺
          作者丨oldpan
          來源丨oldpan博客
          編輯丨極市平臺

          極市導(dǎo)讀

           

          文章詳細討論了幾種多模態(tài)模型,如LLaVA、InternLM-XComposer2、QWen-VL等,并解釋了它們的架構(gòu)和訓(xùn)練流程。以及介紹了幾種多模態(tài)模型的部署框架,包括TensorRT-LLM、lmdeploy和vLLM,并討論了它們對VLM模型的支持程度。 >>加入極市CV技術(shù)交流群,走在計算機視覺的最前沿

          去年年初LLM剛起步的時候,大模型的部署方案還不是很成熟,如今僅僅過了一年多,LLM部署方案已經(jīng)遍地都是了。

          而多模態(tài)模型相比大語言模型來說,發(fā)展的還沒有很“特別”成熟,不過由于兩者結(jié)構(gòu)很相似,LLMs的經(jīng)驗還是可以很好地利用到VLMs中。

          本篇文章中提到的多模態(tài)指的是視覺多模態(tài),即VLM(Vision Language Models)。

          以下用一張圖展示下簡單多模態(tài)模型的運行流程:

          • Text Embeddings即文本輸入,就是常見LLM中的輸入;
          • 而Multomode projector則是多模態(tài)模型額外一個模態(tài)的輸入,這里指的是視覺輸入信息,當然是轉(zhuǎn)換維度之后的;

          將這個轉(zhuǎn)換維度之后的視覺特征和Text Embeddings執(zhí)行concat操作合并起來,輸入decoder中(例如llama)就完成推理流程了;

          Multomode projector負責(zé)將原始的圖像特征轉(zhuǎn)換下維度,輸出轉(zhuǎn)換后的圖像特征;所以有個中文叫投射層,這個名字有點抽象,理解就行,其實就是個mlp層,轉(zhuǎn)換下視覺特征的維度

          多模態(tài)運作流程 from https://huggingface.co/blog/zh/vlms

          引入VLM

          VLM就是視覺encoder加上語言decoder,這么說可能有點抽象,我們先簡單回顧下transformer的基本結(jié)構(gòu):

          from huggingface

          由編碼器和解碼器組成,最開始的transformer主要是處理機器翻譯任務(wù),結(jié)構(gòu)是encoder+decoder。除了這個結(jié)構(gòu),還有一些其他結(jié)構(gòu)適用于各種任務(wù),比如

          • Encoder-only models:適用于需要理解輸入的任務(wù),例如句子分類和命名實體識別。
          • Decoder-only models:適用于生成性任務(wù),如文本生成。
          • Encoder-decoder models or sequence-to-sequence models:適用于需要輸入的生成性任務(wù),例如翻譯或摘要。

          我們常見的llama屬于Decoder-only models,只有decoder層;bert屬于encoder-only;T5屬于encoder-decoder。llama不多說了,BERT 是一種僅包含編碼器的模型,它通過學(xué)習(xí)雙向的上下文來更好地理解語言的深層含義。

          BERT 通常用于理解任務(wù),如情感分析、命名實體識別、問題回答等。T5 模型包括編碼器和解碼器,適用于同時需要理解和生成語言的任務(wù)。T5 被設(shè)計來處理各種“文本到文本”的任務(wù),比如機器翻譯、文摘生成、文本分類等。這種結(jié)構(gòu)允許模型首先通過編碼器理解輸入文本,然后通過解碼器生成相應(yīng)的輸出文本?;A(chǔ)知識就過到這里,我們先說enc-dec結(jié)構(gòu)。

          Encoder-Decoder (Enc-Dec)

          注意,Enc-Dec模型需要區(qū)別于多模態(tài)模型,目前TensorRT-LLM官方支持的enc-dec模型如下:

          • T5[1]
          • T5v1.1[2] and Flan-T5[3]
          • mT5[4]
          • BART[5]
          • mBART[6]
          • FairSeq NMT[7]
          • ByT5[8]

          第一個就是T5也就是上述提到的編碼器+解碼器結(jié)構(gòu)。需要注意這些模型都是基于Transformer架構(gòu)的自然語言處理(NLP)模型,區(qū)別于多模態(tài)模型,這些模型主要是處理文本,算是單模態(tài)。

          VLM or multimodal

          而多模態(tài)除了本文,就帶上了圖像:

          VILA架構(gòu)和訓(xùn)練流程

          VILA[9]是nvidia推出的一個視覺語言模型,上圖很清楚地介紹了其推理和訓(xùn)練流程。我知道的一些多模態(tài)模型有(這些模型來自lmdeploy官方github介紹):

          • LLaVA(1.5,1.6) (7B-34B)
          • InternLM-XComposer2 (7B, 4khd-7B)
          • QWen-VL (7B)
          • DeepSeek-VL (7B)
          • InternVL-Chat (v1.1-v1.5)
          • MiniGeminiLlama (7B)
          • CogVLM-Chat (17B)
          • CogVLM2-Chat (19B)
          • MiniCPM-Llama3-V-2_5

          這里我只簡單介紹下llava,畢竟llava是較早的做多模態(tài)的模型,之后很多多模態(tài)的架構(gòu)和llava基本都差不多。剩下的多模態(tài)模型大家可以自行查閱,結(jié)構(gòu)基本都類似。

          LLAVA

          LLaVA\(2304\)[10]作為VLMs的代表性工作,號稱只需要幾個小時的訓(xùn)練,即可讓一個LLM轉(zhuǎn)變?yōu)閂LM:

          image

          訓(xùn)練方式比較簡單,主要操作是將視覺圖像視作一種“外語”(相比于之前純nlp,圖像可以當做額外輸入的外語),利用vision-encoder和projection[11]將“圖像翻譯成文本信號”,并微調(diào)LLM從而可以適應(yīng)圖像任務(wù),我們簡單看下其推理代碼:

          llava的整體運行過程

          其中processor就是圖像預(yù)處理,處理后得到的input為:inputs.pixel_values,其shape是torch.Size([1, 3, 336, 336])。然后進入generate階段:

          image

          第一步(stage-1)是執(zhí)行encoder部分:

          • input_ids(torch.Size([1, 17])) -> input_embeds(torch.Size([1, 17, 4096]))
          • pixel_values(torch.Size([1, 3, 336, 336]))經(jīng)過視覺模型 輸出視覺特征(torch.Size([1, 576, 1024]))
          • 視覺特征經(jīng)過投影層(mlp)輸出最終的圖像特征(torch.Size([1, 576, 4096]))

          第二步(stage-2)是執(zhí)行文字embed和圖像embed合并過程,也就是合并inputs_embeds + image_features,最終得到的inputs_embeds維度為torch.Size([1, 592, 4096]),具體在llava中是pre_prompt + image + post_prompt一起輸入進來,其中image的特征替換prompt中的標記,對應(yīng)的token id為32000。

          而這個_merge_input_ids_with_image_features函數(shù)的作用主要是將image_featuresinputs_embeds合并起來:在合并完兩者之后,其余部分就和普通的decoder基本一致了。整體運行流程如下:

          其他多模態(tài)模型拼輸入的方式和llava類似,比如InternVLChat[12],輸入的prompt是這樣的:

          image

          轉(zhuǎn)換為token_ids如下,其圖像特征占位,img_context_token_id是92546:

          image

          上述prompt中的<IMG_CONTEXT>之后會被實際的圖像特征填上,目前只是占個位子。運行過程中的維度變化:

          • pixel_values.shape   torch.Size([1, 3, 224, 224])  ->  vision model -> torch.Size([1, 64, 2048])
          • input_ids   torch.Size([1, 293])  -> language model embed -> torch.Size([1, 293, 2048])

          核心代碼如下,需要注意這里是先占位再填(input_embeds[selected]=...)的形式,不是llava中concat的形式,最終實現(xiàn)效果是一樣的。

          最終也是將合并后的embeds送入language-decoder中。

          包含cross-attention的多模態(tài)

          上述介紹的多模態(tài)模型都是文本輸入和圖像輸入轉(zhuǎn)換為embeds合并后,輸入language decoder中,這個decoder可以是常見的decoder-only models,比如llama。

          還有些特殊的多模態(tài)模型的decoder部分會有cross-attention結(jié)構(gòu),比如meta推出的nougat[13]。其視覺特征不會和input_ids合并,而是單獨輸入decoder,在decoder中和文本特征進行cross attention:

          這種結(jié)構(gòu)相對稍微復(fù)雜一些。

          部署方案

          部署方案的話,我們參考主流開源(TensorRT-LLM不完全開源)框架來窺探下。雖然一些大廠有自己的LLM部署方案,不過技術(shù)其實也多是“借鑒”,大同小異。這幾個LLM框架應(yīng)該是用的比較多的:

          • TensorRT-LLM
          • vLLM
          • lmdeploy

          目前這三個框架都支持VLM模型,只不過支持程度不同,我們先看trt-llm。

          TensorRT-LLM

          trt-llm中多模態(tài)部分在Multimodal示例中,如果是跑demo或者實際中使用trt-llm的python session跑的話,直接看官方的example即可:

          如果我們更進一步,想要部署在生產(chǎn)環(huán)境,也是可以搞的。如果我們想要使用triton inference server部署的話,TensorRT-LLM對多模態(tài)模型的支持限于將cv-encoder和decoder分離開,搞成兩個模型服務(wù)。

          即通過ensemble或者tensorrt_llm_bls(python backend)的方式串起來,整體運行流程和在普通模型中是一致的(先輸入image和text,然后兩者經(jīng)過tokenizer轉(zhuǎn)換為token id,最終拼接和encoder輸出特征圖一并傳入decoder中)。

          視覺端

          視覺端模型轉(zhuǎn)換和普通CV模型一致,可以通過onnx的方式或者直接通過trt-python-api搭建。

          以llava舉例子,在TensorRT-LLM中,首先把視覺模型(encoder)使用Wrapper類套一層,其中:

          • self.vision_tower是視覺模型,
          • multi_modal_projector是投影層,將特征維度轉(zhuǎn)換為和input_embeds相匹配的維度:

          轉(zhuǎn)換好之后,模型信息如下:

          [I] ==== TensorRT Engine ====  
              Name: Unnamed Network 0 | Explicit Batch Engine  
                
              ---- 1 Engine Input(s) ----  
              {input [dtype=float16, shape=(-1, 3, 336, 336)]}  
                
              ---- 1 Engine Output(s) ----  
              {output [dtype=float16, shape=(-1, 576, 4096)]}  
                
              ---- Memory ----  
              Device Memory: 56644608 bytes  
                
              ---- 1 Profile(s) (2 Tensor(s) Each) ----  
              - Profile: 0  
                  Tensor: input           (Input), Index: 0 | Shapes: min=(1, 3, 336, 336), opt=(2, 3, 336, 336), max=(4, 3, 336, 336)  
                  Tensor: output         (Output), Index: 1 | Shape: (-1, 576, 4096)  
                
              ---- 398 Layer(s) ----  

          語言端

          decoder端需要額外加入一個合并input_ids 和prompt_table_data的embedding層(這里稱為PromptTuningEmbedding),其余的和普通llama一致:

          通過設(shè)置 use_prompt_tuning來確定該decoder是否需要額外的 prompt_tuning 輸入:

          class LLaMAModel(Module):  
              def __init__(self,  
                           num_layers,  
                           num_heads,  
                           ...# 省略參數(shù)  
                           use_prompt_tuning: bool = False,   # !!!  
                           enable_pos_shift=False,  
                           dense_context_fmha=False,  
                           max_lora_rank=None):  
                  super().__init__()  
                  self.mapping = mapping  
                  self.use_prompt_tuning = use_prompt_tuning  
                  EmbeddingCls = PromptTuningEmbedding if use_prompt_tuning else Embedding  

          其中PromptTuningEmbedding的forward代碼如下,這個使用trt-python-api搭出來的layer主要作用就是將input_ids和視覺特征prompt_embedding_table進行embed并且concat,和上述一開始提到的concat流程大差不差:

          # PromptTuningEmbedding  
          def forward(self, tokens, prompt_embedding_table, tasks, task_vocab_size):  
              # do not use ">=" because internally the layer works with floating points  
              prompt_tokens_mask = tokens > (self.vocab_size - 1)  
            
              # clip tokens in the [0, vocab_size) range  
              normal_tokens = where(prompt_tokens_mask, self.vocab_size - 1, tokens)  
              normal_embeddings = embedding(normal_tokens, self.weight.value,  
                                            self.tp_size, self.tp_group,  
                                            self.sharding_dim, self.tp_rank)  
            
              # put virtual tokens in the [0, max_prompt_vocab_size) range  
              prompt_tokens = where(prompt_tokens_mask, tokens - self.vocab_size, 0)  
            
              # add offsets to match the concatenated embedding tables  
              tasks = tasks * task_vocab_size  
            
              # tasks: [batch_size, seq_len]  
              # prompt_tokens: [batch_size, seq_len]  
              prompt_tokens = prompt_tokens + tasks  
              prompt_embeddings = embedding(prompt_tokens, prompt_embedding_table)  
            
              # prompt_tokens_mask: [batch_size, seq_len] -> [batch_size, seq_len, 1]  
              # combine the correct sources of embedding: normal/prompt  
              return where(unsqueeze(prompt_tokens_mask, -1), prompt_embeddings,  
                           normal_embeddings)  

          服務(wù)整合

          服務(wù)整合其實很容易,只不過官方一開始并沒有給出示例,只有在最近才在tutorial中給出實際例子:

          • https://github.com/triton-inference-server/tutorials/blob/main/Popular\_Models\_Guide/Llava1.5/llava\_trtllm\_guide.md[14]

          其實我們可以很早發(fā)現(xiàn)tensorrt_llm/config.pbtxt中已經(jīng)包含了這兩個輸入:

          • prompt_embedding_table
          • prompt_vocab_size

          意味著在trt-llm的executor中包裝著decoder-engine,可以接受這兩個輸入。而trt-llm提供的executor,在triton-trt-llm-backend去通過調(diào)用這個API實現(xiàn)inflight batching:

          # inflight_batcher_llm/tensorrt_llm/config.pbtxt  
            {  
              name: "prompt_embedding_table"  
              data_type: TYPE_FP16  
              dims: [ -1, -1 ]  
              optional: true  
              allow_ragged_batch: true  
            },  
            {  
              name: "prompt_vocab_size"  
              data_type: TYPE_INT32  
              dims: [ 1 ]  
              reshape: { shape: [ ] }  
              optional: true  
            },  

          而之前介紹的llava的decoder結(jié)構(gòu),則可以看到有prompt_embedding_table和prompt_vocab_size這兩個輸入:

          [03/04/2024-03:23:39] [TRT-LLM] [I] Engine:name=Unnamed Network 0, refittable=False, num_layers=495, device_memory_size=1291851264, nb_profiles=1  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=input_ids, mode=TensorIOMode.INPUT, shape=(-1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=position_ids, mode=TensorIOMode.INPUT, shape=(-1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=prompt_embedding_table, mode=TensorIOMode.INPUT, shape=(-1, 4096), dtype=DataType.HALF, tformat=Row major linear FP16 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=tasks, mode=TensorIOMode.INPUT, shape=(-1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=prompt_vocab_size, mode=TensorIOMode.INPUT, shape=(1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=last_token_ids, mode=TensorIOMode.INPUT, shape=(-1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=kv_cache_block_offsets, mode=TensorIOMode.INPUT, shape=(-1, 2, -1), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=host_kv_cache_block_offsets, mode=TensorIOMode.INPUT, shape=(-1, 2, -1), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=host_kv_cache_pool_pointers, mode=TensorIOMode.INPUT, shape=(2,), dtype=DataType.INT64, tformat=Row major linear INT8 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=sequence_length, mode=TensorIOMode.INPUT, shape=(-1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=host_request_types, mode=TensorIOMode.INPUT, shape=(-1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=host_past_key_value_lengths, mode=TensorIOMode.INPUT, shape=(-1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=context_lengths, mode=TensorIOMode.INPUT, shape=(-1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=host_context_lengths, mode=TensorIOMode.INPUT, shape=(-1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=host_max_attention_window_sizes, mode=TensorIOMode.INPUT, shape=(32,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=host_sink_token_length, mode=TensorIOMode.INPUT, shape=(1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=cache_indirection, mode=TensorIOMode.INPUT, shape=(-1, 1, -1), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [03/04/2024-03:23:39] [TRT-LLM] [I] Tensor:name=logits, mode=TensorIOMode.OUTPUT, shape=(-1, 32064), dtype=DataType.FLOAT, tformat=Row major linear FP32 format (kLINEAR)  

          這是普通decoder-only server中的服務(wù)文件組織:

          而最終整體的目錄文件,我們再多一個encoder文件夾就行,具體我們可以在preprocessing中調(diào)用encoder,然后去處理prompt合并,最終通過prompt_embedding_table和prompt_vocab_size送入tensorrt_llm中即可。不過需要注意,trt-llm不支持cross attention這種多模態(tài)的inflight batching,因為在config.pbtxt沒有暴露出相關(guān)的接口,cross attention這種多模態(tài)不需要prompt_embedding_table和prompt_vocab_size,而是需要類似于encoder_output這種原始的圖像特征輸入,以下是官方nougat模型decoder部分轉(zhuǎn)為trt的結(jié)構(gòu):

          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=input_ids, mode=TensorIOMode.INPUT, shape=(-1, 1), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=position_ids, mode=TensorIOMode.INPUT, shape=(-1, 1), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=encoder_input_lengths, mode=TensorIOMode.INPUT, shape=(-1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=encoder_max_input_length, mode=TensorIOMode.INPUT, shape=(-1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=encoder_output, mode=TensorIOMode.INPUT, shape=(-1, -1, 1024), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=host_past_key_value_lengths, mode=TensorIOMode.INPUT, shape=(-1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=sequence_length, mode=TensorIOMode.INPUT, shape=(-1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=context_lengths, mode=TensorIOMode.INPUT, shape=(-1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=host_request_types, mode=TensorIOMode.INPUT, shape=(-1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=last_token_ids, mode=TensorIOMode.INPUT, shape=(-1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cache_indirection, mode=TensorIOMode.INPUT, shape=(-1, 1, -1), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=host_max_attention_window_sizes, mode=TensorIOMode.INPUT, shape=(10,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=host_sink_token_length, mode=TensorIOMode.INPUT, shape=(1,), dtype=DataType.INT32, tformat=Row major linear INT32 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=past_key_value_0, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_past_key_value_0, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=past_key_value_1, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_past_key_value_1, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=past_key_value_2, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_past_key_value_2, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=past_key_value_3, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_past_key_value_3, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=past_key_value_4, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_past_key_value_4, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=past_key_value_5, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_past_key_value_5, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=past_key_value_6, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_past_key_value_6, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=past_key_value_7, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_past_key_value_7, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=past_key_value_8, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_past_key_value_8, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=past_key_value_9, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_past_key_value_9, mode=TensorIOMode.INPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_kv_cache_gen, mode=TensorIOMode.INPUT, shape=(1,), dtype=DataType.BOOL, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=present_key_value_0, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_present_key_value_0, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=present_key_value_1, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_present_key_value_1, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=present_key_value_2, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_present_key_value_2, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=present_key_value_3, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_present_key_value_3, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=present_key_value_4, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_present_key_value_4, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=present_key_value_5, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_present_key_value_5, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=present_key_value_6, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_present_key_value_6, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=present_key_value_7, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_present_key_value_7, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=present_key_value_8, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_present_key_value_8, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=present_key_value_9, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=cross_present_key_value_9, mode=TensorIOMode.OUTPUT, shape=(-1, 2, 16, -1, 64), dtype=DataType.BF16, tformat=Row major linear INT8 format (kLINEAR)  
          [04/23/2024-03:56:36] [TRT-LLM] [I] Tensor:name=logits, mode=TensorIOMode.OUTPUT, shape=(-1, 50000), dtype=DataType.FLOAT, tformat=Row major linear FP32 format (kLINEAR)  

          lmdeploy

          lmdeploy對多模態(tài)的支持方式也在預(yù)料之中,decoder使用自家的turbomind或者pytorch engine去跑,然后cv-encoder端復(fù)用原始transformers庫中的代碼去跑,整理流程和trt-llm中的相似。

          vLLM

          vllm對多模態(tài)模型的支持尚可,官方展示的不是很多,但實際上支持了不少(https://github.com/vllm-project/vllm/issues/4194[15]);而且鑒于vllm的易接入性,自己增加模型還是比較簡單的:

          另外,vLLM近期也在修改相關(guān)VLM的架構(gòu),正在進行重構(gòu)[16],以及vllm對vlm的一些后續(xù)優(yōu)化:

          • Make VLMs work with chunked prefill
          • Unify tokenizer & multi-modal processor (so that we can leverage AutoProcessor from transformers)
          • Prefix caching for images
          • Streaming inputs of multi-modal data

          簡單測試了llava,測試性能在同樣fp16的情況下性能不如trt-llm,原因表現(xiàn)可以參考在llama上的對比。

          優(yōu)化點TODO

          優(yōu)化點其實有很多,不過占大頭的就是量化[17]

          量化

          因為多模態(tài)的decoder部分就是普通的decode模型,我們可以復(fù)用現(xiàn)有的成熟的量化技術(shù)量化decoder部分就可以拿到很大的收益。整個pipeline當中視覺encoder部分的耗時占比一般都很小5%左右,encoder部分可以按照我們平常的小模型的方式去優(yōu)化即可,量化也可以上。需要注意的就是量化方法,大模型量化方法很多,需要選對。

          The AWQ quantization algorithm is suitable for multi-modal applications since AWQ does not require backpropagation or reconstruction, while GPTQ does. Thus, it has better generalization ability to new modalities and does not overfit to a specific calibration set. We only quantized the language part of the model as it dominates the model size and inference latency. The visual part takes less than 4% of the latency. AWQ outperforms existing methods (RTN, GPTQ) under zero-shot and various few-shot settings, demonstrating the generality of different modalities and in-context learning workloads.

          Runtime

          還有cv-encoder需要和decoder最好放到一個runtime當中,要不然會有一些冗余的顯存拷貝,不過這部分對吞吐影響不大,主要是latency。trt-llm中對enc-dec結(jié)構(gòu)已經(jīng)做了這樣的優(yōu)化,在trt-llm-0607版本中將這倆放到了同一個runtime中,這里指的是Executor,可以看到多出了一個encoder的model path:

          可以看到triton-llm-backend中多了一個encoder_model_path的輸入,這里將encoder和decoder放到同一個runtime中了:

          還有一些其他的優(yōu)化空間,這里暫時不談了,后續(xù)有新的結(jié)論了再補充。

          這里的討論還不是很全很細,算是拋磚引玉,之后有更新也會再發(fā)篇文章單獨介紹。各位讀者如果有比較好的方法或者建議也歡迎留言,我們一起討論。

          參考

          • https://github.com/triton-inference-server/tutorials/pull/100[18]
          • https://huggingface.co/blog/vlms[19]
          • https://github.com/InternLM/lmdeploy/issues/1309[20]
          • https://developer.nvidia.com/blog/visual-language-intelligence-and-edge-ai-2-0/[21]
          參考資料
          [1]

          T5: https://huggingface.co/docs/transformers/main/en/model_doc/t5

          [2]

          T5v1.1: https://huggingface.co/docs/transformers/model_doc/t5v1.1

          [3]

          Flan-T5: https://huggingface.co/docs/transformers/model_doc/flan-t5

          [4]

          mT5: https://huggingface.co/docs/transformers/model_doc/mt5

          [5]

          BART: https://huggingface.co/docs/transformers/model_doc/bart

          [6]

          mBART: https://huggingface.co/docs/transformers/model_doc/mbart

          [7]

          FairSeq NMT: https://pytorch.org/hub/pytorch_fairseq_translation/

          [8]

          ByT5: https://huggingface.co/docs/transformers/main/en/model_doc/byt5

          [9]

          VILA: https://developer.nvidia.com/blog/visual-language-models-on-nvidia-hardware-with-vila/

          [10]

          LLaVA(2304): https://link.zhihu.com/?target=https%3A//arxiv.org/abs/2304.08485

          [11]

          projection: https://www.zhihu.com/search?q=projection&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22article%22%2C%22sourceId%22%3A%22702811733%22%7D

          [12]

          InternVLChat: https://huggingface.co/OpenGVLab/InternVL-Chat-V1-5

          [13]

          nougat: https://github.com/facebookresearch/nougat

          [14]

          https://github.com/triton-inference-server/tutorials/blob/main/Popular_Models_Guide/Llava1.5/llava_trtllm_guide.md: https://github.com/triton-inference-server/tutorials/blob/main/Popular_Models_Guide/Llava1.5/llava_trtllm_guide.md

          [15]

          https://github.com/vllm-project/vllm/issues/4194: https://github.com/vllm-project/vllm/issues/4194

          [16]

          重構(gòu): https://github.com/vllm-project/vllm/issues/4194

          [17]

          undefined: undefined

          [18]

          https://github.com/triton-inference-server/tutorials/pull/100: https://github.com/triton-inference-server/tutorials/pull/100

          [19]

          https://huggingface.co/blog/vlms: https://huggingface.co/blog/vlms

          [20]

          https://github.com/InternLM/lmdeploy/issues/1309: https://github.com/InternLM/lmdeploy/issues/1309

          [21]

          https://developer.nvidia.com/blog/visual-language-intelligence-and-edge-ai-2-0/: https://developer.nvidia.com/blog/visual-language-intelligence-and-edge-ai-2-0/

          公眾號后臺回復(fù)“數(shù)據(jù)集”獲取100+深度學(xué)習(xí)各方向資源整理

          極市干貨

          技術(shù)專欄:多模態(tài)大模型超詳細解讀專欄搞懂Tranformer系列ICCV2023論文解讀極市直播
          極視角動態(tài)歡迎高校師生申報極視角2023年教育部產(chǎn)學(xué)合作協(xié)同育人項目新視野+智慧腦,「無人機+AI」成為道路智能巡檢好幫手!
          技術(shù)綜述:四萬字詳解Neural ODE:用神經(jīng)網(wǎng)絡(luò)去刻畫非離散的狀態(tài)變化transformer的細節(jié)到底是怎么樣的?Transformer 連環(huán)18問!

          點擊閱讀原文進入CV社區(qū)

          收獲更多技術(shù)干貨

          瀏覽 130
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄色视频在线观看免费 | 国产乱伦A片 | 成人午夜啪免费视频在线观看软件 | 影音先锋一区二区三区 | 久热网 |