コンテンツにスキップ

LoRAアダプターで実行

LoRAアダプターを使用してファインチューニングされたモデルを生成して実行する

Section titled “LoRAアダプターを使用してファインチューニングされたモデルを生成して実行する”

ONNX Runtimeで実行するのに適した形式でモデルとアダプターを生成する方法を学びます。

LoRAはLow Rank Adaptationの略です。これは、グラフ内の一部のレイヤーを凍結し、アダプターと呼ばれるアーティファクトで可変レイヤーの重みの値を提供する、一般的なファインチューニングの方法です。

Multi LoRAは、ランタイムに複数のアダプターを使用して、同じモデルの異なるファインチューニングを実行します。アダプターは、シナリオごと、テナント/顧客ごと、またはユーザーごとである可能性があり、つまり、アダプターは少数から数百または数千まで存在する可能性があります。

Oliveは、ONNX形式でモデルとアダプターを生成します。これらのモデルとアダプターは、ONNX Runtimeで実行できます。

  1. Oliveをインストールする

    これにより、mainからOliveがインストールされます。リリースされたらバージョン0.8.0に置き換えてください。

    Terminal window
    pip install git+https://github.com/microsoft/olive
  2. ONNX Runtime generate()をインストールする

    pip install onnxruntime-genai
  3. その他の依存関係をインストールする

    Terminal window
    pip install optimum peft
  4. torchとtransformersをダウングレードする

    TODO: torch 2.5.0にはエクスポートのバグがあり、transformers>=4.45.0とは互換性がありません。

    Terminal window
    pip uninstall torch
    pip install torch==2.4
    pip uninstall transformers
    pip install transformers==4.44
  5. モデルを選択する

    HuggingFaceのモデル、または独自のモデルを使用できます。モデルはPyTorchモデルである必要があります。

  6. モデルをファインチューニングするか、既存のアダプターを使用するかを決定する

    HuggingFaceには多くの既存のアダプターがあります。複数の異なるアダプターを使用している場合、これらはすべて元のモデルの同じファインチューニングされたレイヤーを使用する必要があります。

ONNX形式でモデルとアダプターを生成する

Section titled “ONNX形式でモデルとアダプターを生成する”
  1. ファインチューニングする場合、Oliveを実行してモデルをファインチューニングします

    注意:この操作には、CUDAがインストールされたNVIDIA GPUを搭載したシステムが必要です。

    olive fine-tuneコマンドを使用します:https://microsoft.github.io/Olive/how-to/cli/cli-finetune.html

    コマンドの使用例は次のとおりです。

    Terminal window
    olive finetune --method qlora -m meta-llama/Meta-Llama-3-8B -d nampdn-ai/tiny-codes --train_split "train[:4096]" --eval_split "train[4096:4224]" --text_template "### Language: {programming_language} \n### Question: {prompt} \n### Answer: {response}" --per_device_train_batch_size 16 --per_device_eval_batch_size 16 --max_steps 150 --logging_steps 50 -o adapters\tiny-codes
  2. オプションで、モデルを量子化します

    olive quantizeコマンドを使用します:https://microsoft.github.io/Olive/how-to/cli/cli-quantize.html

  3. 量子化されたモデルを使用してONNXモデルとアダプターを生成します

    このステップではolive auto-optコマンドを使用します:https://microsoft.github.io/Olive/how-to/cli/cli-auto-opt.html

    --adapter pathは、HuggingFaceアダプター参照、または上記でファインチューニングしたアダプターへのパスのいずれかです。

    --provider引数は、ONNX Runtime実行プロバイダーです。

    Terminal window
    olive auto-opt -m <モデルフォルダーへのパス> --adapter_path <アダプターへのパス> -o <出力モデルフォルダー> --device cpu\|gpu --provider <プロバイダー>
  4. アダプターを.onnx_adapter形式に変換します

    生成した各アダプターに対してこのステップを1回実行します。

    Terminal window
    olive convert-adapters --adapter_path <ファインチューニングされたアダプターへのパス> --output_path <.onnx_adapterの場所へのパス> --dtype float32

この例はPythonで示されていますが、C/C++ API、C# API、およびJava API(近日公開予定!)も使用できます。

import onnxruntime_genai as og
import numpy as np
import argparse
parser = argparse.ArgumentParser(description='ONNX LoRAアダプターをロードして切り替えるアプリケーション')
parser.add_argument('-m', '--model', type=str, help='ONNXベースモデル')
parser.add_argument('-a', '--adapters', nargs='+', type=str, help='.onnx_adapters形式のアダプターのリスト')
parser.add_argument('-t', '--template', type=str, help='プロンプトのフォーマットに使用するテンプレート')
parser.add_argument('-s', '--system', type=str, help='モデルに渡すシステムプロンプト')
parser.add_argument('-p', '--prompt', type=str, help='モデルに渡すユーザープロンプト')
args = parser.parse_args()
model = og.Model(args.model)
if args.adapters:
adapters = og.Adapters(model)
for adapter in args.adapters:
adapters.load(adapter, adapter)
tokenizer = og.Tokenizer(model)
tokenizer_stream = tokenizer.create_stream()
prompt = args.template.format(system=args.system, input=args.prompt)
params = og.GeneratorParams(model)
params.set_search_options(max_length=2048, past_present_share_buffer=False)
# この入力はtransformersバージョン > 4.45用に生成されます
#params.set_model_input("onnx::Neg_67", np.array(0, dtype=np.int64))
params.input_ids = tokenizer.encode(prompt)
generator = og.Generator(model, params)
if args.adapters:
for adapter in args.adapters:
print(f"[{adapter}]: {prompt}")
generator.set_active_adapter(adapters, adapter)
while not generator.is_done():
generator.compute_logits()
generator.generate_next_token()
new_token = generator.get_next_tokens()[0]
print(tokenizer_stream.decode(new_token), end='', flush=True)
else:
print(f"[Base]: {prompt}")
while not generator.is_done():
generator.compute_logits()
generator.generate_next_token()
Terminal window
python app.py -m <モデルフォルダー> -a <.onnx_adapterファイル> -t <プロンプトテンプレート> -s <システムプロンプト> -p <プロンプト>