• <xmp id="om0om">
  • <table id="om0om"><noscript id="om0om"></noscript></table>
  • 對話式人工智能

    聚焦:NAVER Place 利用 NVIDIA TensorRT-LLM 優化 SLM 基礎的垂直服務

    NAVER 是一家韓國熱門搜索引擎公司,提供 Naver Place ,這是一項基于地理的服務,可提供有關韓國數百萬家企業和興趣點的詳細信息。用戶可以搜索不同的地點、發表評論,以及實時進行預訂或下單。

    NAVER Place 垂直服務基于小語言模型 (SLMs) 來提高可用性,并專門針對 Place、Map 和 Travel。本文分享了 NVIDIA 和 NAVER 如何使用 NVIDIA TensorRT-LLM 優化 SLM 推理性能,從而在 NVIDIA Triton Inference Server 上實現基于 SLM 的垂直服務。如需詳細了解 NAVER 如何使用 AI,請參閱 NAVER Place AI 開發團隊簡介

    適用于 NAVER Place 評測的小語言模型

    大語言模型(LLMs) 相比,小語言模型(SLMs)是能夠以更少的參數理解自然語言的 AI 模型。眾所周知,當 SLMs 針對特定域任務進行適當微調時,它們可以在內存和計算能力較低的情況下正常工作。

    NAVER Place 使用定制的小語言模型(SLMs)與其內部數據集結合使用,以提供摘要(根據 NAVER Place 用戶留下的評論創建)或微評論,解釋每個地點的特點。

    Screenshot of NAVER Place service app showing review summary and microreview examples.
    圖 1.查看 NAVER Place 服務應用中的摘要和微評論示例。圖片來源:NAVER

    使用 SLM Transformer 解碼器將參觀與景點匹配

    NAVER Place 從其注冊地點收集收據和付款記錄,以顯示 NAVER Map 上每個地點的訪問和評論。為此,NAVER Place 提供了一個將參觀與興趣點 (POIs) 相匹配的系統。系統還會從博客文章中發現新的 POIs,或檢查重復的 POIs,以確保數據完整性并提高服務質量。

    Screenshots of the NAVER Place POI matching service UI.
    圖 2. NAVER Place POI 匹配服務 UI 由 SLM Transformer 解碼器啟用。圖片來源:NAVER

    采用 NVIDIA TensorRT-LLM 實現卓越的推理性能

    NVIDIA TensorRT-LLM 可加速并優化 NVIDIA GPU 上 LLM 的推理性能。它支持動態批處理以最大限度地提高吞吐量,并使用自回歸模型的內存優化方法 (例如分頁 KV 緩存和分塊上下文) 來提高內存效率。

    NAVER Place 采用了 TensorRT-LLM,因為它在吞吐量、到達第一個令牌的時間 (TTFT) 和每個輸出令牌的時間 (TPOT) 方面優于其他 LLM 推理解決方案。TensorRT-LLM 在各種輸入長度和輸出令牌場景中始終如一地提供卓越性能。

    圖 3 比較了使用 Qwen 模型 測量的熱門替代開源 LLM 推理庫和 TensorRT-LLM 在 NVIDIA A100 和 NVIDIA H100 GPU 上各種輸入和輸出令牌長度的吞吐量。

    Four charts showing QPS Comparison of TensorRT-LLM and a popular alternative library across different operation modes.
    圖 3、TensorRT-LLM 與不同操作模式下熱門替代庫的 QPS 比較。圖片來源:NAVER

    TensorRT-LLM 在所有解碼 – 預填充輕、預填充重、解碼重和解碼 – 預填充重操作模式下的表現均優于替代庫。其中,使用 SLM 的解碼重操作模式提供了最強的性能。此外,由于 TensorRT-LLM 提供針對最新 GPU 優化的內核,因此它在 NVIDIA Hopper 架構 上實現了特別高的性能。

    要了解如何使用 TensorRT-LLM 評估性能,請參閱 NVIDIA/TensorRT-LLM GitHub repo 中提供的 性能概述 。如需詳細了解構建 TensorRT-LLM 引擎的基本調優技術,請參閱 調優 TensorRT-LLM 性能的最佳實踐

    推理優化:在吞吐量和延遲之間做出權衡

    本節將探討在批量大小和內存優化技術 (例如分頁 KV 緩存和動態批處理) 方面平衡 LLM 推理吞吐量和延遲的策略。

    批量大小

    LLM 推理服務器將請求批量處理,以更大限度地提高吞吐量。但是,這會導致高延遲。這種權衡意味著,雖然較大的批量大小可以提供更高的吞吐量,但也可能會增加響應時間,因此必須在效率和用戶體驗之間保持謹慎的平衡 (圖 4)。通過根據您的目標 TTFT 和 TPOT 調整批量大小,您可以優化系統的性能,以更好地滿足您的特定服務要求。

    Four graphs showing throughput and time per output token according to batch size.
    圖 4、每個輸出令牌的吞吐量和時間 (根據批量大小而定)。圖片來源:NAVER

    Paged KV 緩存和 in-flight batching

    TensorRT-LLM 包括默認啟用的 分頁 KV 緩存 選項,可提高內存效率并增加批量大小上限,以適應需要低延遲和高吞吐量的任務。此默認設置可確保模型能夠平滑擴展,以處理延遲敏感的實時請求和需要更高吞吐量的批量處理場景,從而提供更靈活、更可靠的解決方案。

    TensorRT-LLM 也默認啟用 In-flight batching ,這可以提高吞吐量。對于大多數任務,NAVER 團隊默認使用這兩個選項。

    一個例外是,服務需要在較小的模型和較舊的 GPU 上實現極低的延遲。NAVER Place 在特定情況下需要極低的延遲,當關閉兩個選項時,性能表現更好。例如,POI 匹配是指實時處理請求,需要極低延遲的情況。由于模型相對較小,只有 1.3 億個,并且 NVIDIA T4 GPU 架構相對較舊,因此該服務需要將批量大小設為 1 以實現最低延遲,并關閉批處理選項。

    此外,使用小模型大小為 1.3 億,批量大小為 1,與計算開銷相比,分頁開銷更高,從而導致延遲增加和 QPS 降低。為了解決這個問題,團隊采用了連續的 KV 緩存,而不是分頁 KV 緩存,因為在給定條件下,內存開銷不太重要。這種選擇使我們能夠滿足 POI 匹配等用例的嚴格實時要求。

    精度 分頁 KV 緩存 緩存塊 輸入/輸出 最大 batch_size QPS 延遲 (以秒為單位)
    FP16 打開 7110 500/5 1 6.49 0.154
    FP16 關閉 7110 500/5 1 8.39 0.119
    表 1、當在特定情況下禁用分頁 KV 緩存時,當使用較小的模型和批量大小利用較舊的 GPU 架構時,QPS 和延遲會更好

    雖然 POI 匹配對實時服務的延遲要求極低,但它也需要高吞吐量才能進行背景匹配。因此,我們目前對每種版本使用不同的構建選項。

    "build_config": {
            "max_input_len": 512,
            "max_output_len": 32,
            "max_batch_size": 1,
            "max_beam_width": 1,
            "max_num_tokens": 4096,
            ...
            "plugin_config": {
                ...
                "paged_kv_cache": false,
                ...
            }
        }
    "build_config": {
           "max_input_len": 512,
           "max_output_len": 32,
           "max_batch_size": 8,
           "max_beam_width": 1,
           "max_num_tokens": 4096,
           ...
           "plugin_config": {
               ...
     
     
               "paged_kv_cache": true,
               ...
           }
       }

    推理優化:下游緩存

    本節將探討利用緩存技術來簡化下游推理任務的優化策略。我們研究了前綴和響應緩存如何幫助減少冗余計算并提高整體效率。

    前綴緩存

    由于下游任務生成的提示詞具有通用前綴,因此計算每個請求的整個預填充會浪費資源。為了避免這種情況,TensorRT-LLM 提供了前綴緩存,這可以顯著減少內存使用量和計算負載。有關更多詳細信息,請參閱 如何在 NVIDIA/TensorRT-LLM GitHub repo 中啟用 KV 緩存重用

    這種方法可以顯著增強 TTFT,并且對于具有長輸入長度、共享系統提示和短輸出長度的任務很有幫助。它特別適用于微評論,因為生成一個微評論平均需要 40 個多步驟推理,并且每個步驟共享前綴。

    但是,對于涉及高度多樣化系統提示的任務,前綴緩存可能無法高效運行,同時降低緩存性能并增加管理開銷,因為緩存基于最近使用最少(LRU)策略。

    響應緩存

    響應緩存是 NVIDIA Triton Inference Server 的一項功能,有助于避免低效的冗余推理。Triton 會使用推理請求哈希來訪問響應緩存,其中包括模型名稱、模型版本和模型輸入。響應緩存非常有效,但有意要求重新引用的情況除外,例如多項采樣解碼。在實時提供的 POI 匹配中,每秒發生 4 到 5 次緩存命中,這意味著計算負載減少了 17%。有關更多詳細信息,請參閱 Triton Response Cache 文檔

    Chart of response cache hits for the POI matching service.
    圖 5、POI 匹配服務的響應緩存命中。圖片來源:NAVER

    使用 Triton 服務 TensorRT-LLM

    使用 TensorRT-LLM 構建的 SLM 引擎可在 Triton Inference Server 上提供。Triton 提供了諸如 ensemble models Business Logic Scripting (BLS) 等功能,用于組成標記化、后處理或多步驟推理等工作流。例如,NAVER Place 選擇使用 BLS,是因為它為特定用例提供了所需的靈活性。本節將介紹 NAVER Place 如何最大限度地提高 Triton BLS 的優勢和可用性。

    通過定義明確的請求/響應模式提高可用性

    Triton 模型以 pb_tensor 格式交換數據。為提高通信效率和優化 LLM 推理而選擇的 BLS 結構包含預處理和后處理代碼,這需要將數據類型從 pb_tensor 轉換為 NumPy 數組,然后再轉換回 pb_tensor

    此過程存在兩個困難。首先,如果每個模型的 IO 數據未經過驗證,則調試很困難,因為在運行時發現了任何無效的數據格式或缺少必填字段。其次,由于將預處理和后處理合并到 BLS 中,代碼變得更加復雜,如果模型之間存在調用依賴項,則擴展和維護變得更加困難。

    這些挑戰強調了需要一個定義明確的請求/響應模式,以減少運行時錯誤并簡化代碼管理,尤其是在必須將多個模型鏈接在一起的情況下。此外,在整個工作流中保持一致的數據格式可顯著緩解調試困難,并確保更流暢的集成。例如,POI 匹配會經歷復雜的工作流,如圖 6 所示。

    Diagram of POI matching inference pipeline in BLS.
    圖 6、BLS 中的 POI 匹配推理工作流。圖片來源:NAVER

    為了克服這些困難,NAVER Place 團隊提出了以下方法。

    標準化 IO 模式管理

    基于 NVIDIA 的 Python 數據類,我們使用 Pydantic 定義了 IO 模式,這使得數據驗證變得更容易。這有助于確保所有 Triton 模型的請求和響應之間的結構一致性,并增強數據驗證。通過在此階段采用定義明確的模式,開發者可以盡早檢測到數據問題,并在整個推理工作流中維護一致的數據結構,最終減少調試用度并提高整體可靠性。

    例如,我們定義了一個名為 BlsRequest 的類,用于管理 Triton 請求的輸入數據格式并執行數據驗證,如以下代碼示例所示:

    # NOTE: Because Triton uses pb_tensor and Numpy objects,
    # it is required to declaratively manage the fields that are not defined as Python default types.
    # For this, we added tTe json_schema_extra field of Pydantic to explicitly manage data types.
    class BlsRequest(TritonFieldModel):
          name: Optional[str] = Field(None, json_schema_extra={'data_type': "TYPE_STRING"})
          subname: Optional[str] = Field(None, json_schema_extra={'data_type': "TYPE_STRING"})
          biznum: Optional[str] = Field(None, json_schema_extra={'data_type': "TYPE_STRING"})
          address: Optional[List[str]] = Field(None, json_schema_extra={'data_type': "TYPE_STRING"})
          tel: Optional[List[str]] = Field(None, json_schema_extra={'data_type': "TYPE_STRING"})
          @root_validator(pre=True)
          def check_all_fields_empty(cls, values):
              if not any(bool(v) for v in values.values()):
                  raise ValidationError("All fields cannot be empty", model=cls.__name__)

    按模型實現 IO 類型轉換的模塊化

    我們為每個模型封裝了 IO 數據轉換過程,并為 pb_tensor 和 Pydantic 之間的轉換創建了一個通用函數,使其適合基礎 Triton Python 模型。這有助于以一致的方式調用模型,而無需擔心內部數據轉換過程。

    以下代碼示例是一個函數,該函數接收 Pydantic Request 對象,將其轉換為 Triton pb_tensor,然后將模型推理的結果作為 Pydantic Response 對象返回:

    def _infer_model(self, request_model, response_model_cls, model_name, request_model, **infer_kwargs):
         # Converts Pydantic Request to Triton pb_tensors.
         pb_tensors = self.convert_pydantic_to_pb_tensors(request_model, batch_inference)
         # Runs model inference.
         infer_request = pb_utils.InferenceRequest(
             model_name=model_name,
             inputs=pb_tensors,
             requested_output_names=response_model_cls.get_field_names(),
             **infer_kwargs,
         )
         infer_response = infer_request.exec()
         # Converts Triton Response(pb_tensors) to Pydantic Response.
         return self.convert_pb_tensors_to_pydantic(response, response_model_cls)

    以下代碼示例使用 _infer_model 調用模型。只需聲明 GeneratorRequestGeneratorResponse 類,而忽略了復雜的數據轉換或模型調用過程。

    def infer_generator(self, request, text_input, max_tokens):
          response_model_cls = schema.GeneratorResponse
          request_model = schema.GeneratorRequest(text_input=text_input, max_tokens=max_tokens)
           return self._infer_model(
              request=request,
              model_name="generator_bls",
              request_model=request_model,
              response_model_cls=response_model_cls,
          )

    模塊化 BLS 業務邏輯并增強可測試性

    NAVER 團隊通過以下方式模塊化了業務邏輯,并在 BLS 中預處理和后處理代碼,以實現低耦合。這有助于降低代碼的復雜性,并提高可測試性和可維護性。

    • 模塊化預處理和后處理,并引入單元測試 將模型訓練、預處理和后處理代碼的業務邏輯模塊化,使其可重復使用。 將測試代碼設計為在 Python 運行時中獨立運行,即使沒有 Triton 運行時,也能驗證每個模型的預處理和后處理。
    • 重新定義 BLS 的角色 BLS 僅負責模型調用和端到端測試。這可以確保系統保持可擴展性,即使添加了新要求,也能最大限度地減少對 BLS 代碼的影響。
    • CI 簡介 為業務邏輯以及預處理和后處理代碼創建了 CI 測試管道。這有助于快速驗證模型訓練過程中所做的更改,確保它們不會影響服務。將這些測試集成到 CI 管道中可實現更早的問題檢測和快速解決,在不中斷服務流程的情況下確保穩定的更新。

    使用這種方法,我們有效地實現了增強數據驗證、代碼可維護性和開發生產力的目標,從而提高了基于 Triton 的 LLM 服務開發的生產力。

    總結

    NAVER Place 已成功使用 NVIDIA TensorRT-LLM 優化 LLM 引擎,并提高了 NVIDIA Triton Inference Server 的可用性。通過這種優化,該團隊還最大限度地提高了 GPU 利用率,進一步提高了整體系統效率。整個流程有助于優化多個基于 SLM 的垂直服務,使 NAVER Place 更加用戶友好。基于這些經驗,我們將繼續開發其他垂直模型,并將其應用于我們的服務。

    開始使用 NVIDIA TensorRT-LLM NVIDIA Triton Inference Server

    ?

    ?

    0

    標簽

    人人超碰97caoporen国产