この記事は、Docker Captain Harsh Manvar と共同で執筆しています。
Hugging Face は、機械学習(ML)の分野で強力な存在となっています。 事前学習済みモデルの大規模なコレクションとユーザーフレンドリーなインターフェースは、AI/MLの展開とスペースへのアプローチ方法を完全に変えました。 Docker モデルと Hugging Face モデルの統合について詳しく知りたい場合は、「Hugging Face の Docker Spaces を使用した機械学習アプリの構築」という記事に包括的なガイドがあります。
言語生成の驚異である大規模言語モデル(LLM)は、驚異的な発明です。 この記事では、Hugging Face がホストする Llama モデルを Docker のコンテキストで使用する方法を見て、自然言語処理 (NLP) の愛好家や研究者に新たな機会を提供します。

顔のハグとLLMの紹介
Hugging Face(HF)は、 MLモデルのトレーニング、微調整、デプロイのための包括的なプラットフォームを提供します。 また、LLMは、テキストの生成、補完、分類などのタスクを実行できる最先端のモデルを提供します。
Docker を ML に活用する
堅牢な Docker コンテナ化技術により、プログラムのパッケージ化、配布、運用が容易になります。 MLモデルをDockerコンテナで囲むことで、さまざまなコンテキストで一貫して動作することを保証します。 再現性が保証され、長年の「私のマシンで動作する」という問題が解決されます。
フォーマットの種類
Hugging Faceのほとんどのモデルでは、2つのオプションが利用可能です。
AIモデルの量子化で使用される量子化手法の例としては、GGMLモデルやGPTQモデルなどがあります。 これは、トレーニング中またはトレーニング後の量子化を意味します。 GGML モデルと GPTQ モデル (よく知られた 2 つの量子化モデル) は、モデルの重みを低い精度に減らすことで、モデルのサイズと計算の必要性を最小限に抑えます。
HF モデルは GPU に負荷がかかり、GPU は CPU よりも大幅に高速に推論を実行します。 一般的に、モデルは巨大であり、多くのVRAMも必要です。 この記事では、CPUでうまく動作し、GPUが優れていない場合はおそらく高速であるGGMLモデルを利用します。
このデモではトランスフォーマーとトランスフォーマーも使用するので、まずそれらを理解しましょう。
- トランスフォーマー: トランスフォーマーの API とツールのおかげで、最新の事前トレーニング済みモデルを簡単にダウンロードしてトレーニングできます。 事前トレーニング済みモデルを使用することで、モデルをゼロからトレーニングするために必要な時間とリソース、および計算コストと二酸化炭素排出量を削減できます。
- ctransformers: GGML ライブラリを使用して C/C++ で開発されたトランスフォーマー モデルの Python バインディング。
Llama モデルへのアクセスを要求する
Meta Llamaモデルを利用し、サインアップし、アクセスをリクエストします。
Hugging Faceトークンの作成
今後使用するアクセストークンを作成するには、Hugging Faceプロファイル設定に移動し、左側のサイドバーから [アクセストークン ]を選択します(図1)。 作成したアクセストークンの値を保存します。
![- F1 Hugging Face アクセストークン Hugging Faceのプロフィール設定のスクリーンショット。[アクセス トークン] を選択します。](https://www.docker.com/ja-jp/app/uploads/2023/12/F1-Hugging-Face-Access-Token-1110x587.png)
Docker環境のセットアップ
LLMの領域を探る前に、まずDocker環境を構成する必要があります。 オペレーティングシステムに基づいて、 Dockerの公式Webサイトの 指示に従って、最初にDockerをインストールします。 インストール後、次のコマンドを実行してセットアップを確認します。
1 | docker --version |
クイックデモ
次のコマンドは、Hugging Face harsh-manvar-llama-2-7b-chat-test:latest
イメージを使用してコンテナーを実行し、コンテナーからホスト コンピューターにポート 7860
を公開します。 また、環境変数 HUGGING_FACE_HUB_TOKEN
を指定した値に設定します。
1 2 3 4 | docker run -it -p 7860:7860 --platform=linux/amd64 \ -e HUGGING_FACE_HUB_TOKEN="YOUR_VALUE_HERE" \ registry.hf.space/harsh-manvar-llama-2-7b-chat-test:latest python app.py |
- このフラグは
-it
、コンテナをインタラクティブモードで実行し、ターミナルをアタッチするようにDockerに指示します。 これにより、コンテナとそのプロセスを操作できるようになります。 - このフラグは
-p
、コンテナからホストマシンにポート7860を公開するようにDockerに指示します。 これは、ポート 7860 のホスト マシンからコンテナーの Web サーバーにアクセスできることを意味します。 - このフラグは
--platform=linux/amd64
、AMD64アーキテクチャのLinuxマシンでコンテナを実行するようにDockerに指示します。 - このフラグは
-e HUGGING_FACE_HUB_TOKEN="YOUR_VALUE_HERE"
、環境変数HUGGING_FACE_HUB_TOKEN
を指定した値に設定するように Docker に指示します。 これは、コンテナからHugging Faceモデルにアクセスするために必要です。
スクリプトは app.py
、コンテナーで実行する Python スクリプトです。 これにより、コンテナが起動し、ターミナルが開きます。 その後、ターミナルでコンテナとそのプロセスを操作できます。 コンテナーを終了するには、 Ctrl+C キーを押します。
ランディングページへのアクセス
コンテナの Web サーバにアクセスするには、Web ブラウザ http://localhost:7860
を開き、 に移動します。 Hugging Faceモデルのランディングページが表示されます(図2)。
ブラウザを開き、http://localhost:7860 に移動します。

はじめ
プロジェクトのクローン作成
開始するには、Hugging Faceの既存の スペース/リポジトリを複製またはダウンロードします。
ファイル: 必要条件.txt
requirements.txt
ファイルは、プロジェクトを実行するために必要な Python パッケージとモジュールを一覧表示するテキスト ファイルです。これは、プロジェクトの依存関係を管理し、プロジェクトで作業するすべての開発者が必要なパッケージの同じバージョンを使用していることを確認するために使用されます。
Hugging Face llama-2-13b-chat
モデルを実行するには、次のPythonパッケージが必要です。 このモデルはサイズが大きいため、ダウンロードとインストールに時間がかかる場合があります。 また、モデルを実行するために Python プロセスに割り当てられるメモリを増やす必要がある場合もあります。
1 2 3 4 5 6 7 | gradio==3.37.0 protobuf==3.20.3 scipy==1.11.1 torch==2.0.1 sentencepiece==0.1.99 transformers==4.31.0 ctransformers==0.2.27 |
ファイル: ドッカーファイル
1 2 3 4 5 6 7 8 | FROM python:3.9 RUN useradd -m -u 1000 user WORKDIR /code COPY ./requirements.txt /code/requirements.txt RUN pip install --upgrade pip RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt USER user COPY --link --chown=1000 ./ /code |
次のセクションでは、Dockerfile の詳細について説明します。 最初の行は、公式の Python 3.9 イメージをイメージのベース イメージとして使用するように Docker に指示します。
1 | FROM python:3.9 |
次の行は、ユーザー ID が 1000 の user という名前の新しいユーザーを作成します。 このフラグは -m
、ユーザーのホームディレクトリを作成するようにDockerに指示します。
1 | RUN useradd -m -u 1000 user |
次に、この行はコンテナの作業ディレクトリを /code
に設定します。
1 | WORKDIR /code |
要件ファイルを現在のディレクトリ /code
からコンテナーにコピーします。 また、この行は、コンテナー内の pip パッケージ マネージャーをアップグレードします。
1 | RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt |
この行は、コンテナーの既定のユーザーを user に設定します。
1 | USER user |
次の行は、現在のディレクトリ /code
の内容をコンテナ内にコピーします。 このフラグは --link
、ファイルをコピーする代わりにハードリンクを作成するようにDockerに指示するため、パフォーマンスが向上し、イメージのサイズが小さくなります。 このフラグは --chown=1000
、コピーされたファイルの所有権をユーザーユーザーに変更するようにDockerに指示します。
1 | COPY --link --chown=1000 ./ /code |
Dockerイメージをビルドしたら、コマンドを使用して実行できます docker run
。 これにより、Python 3.9 イメージを実行する新しいコンテナーが root 以外のユーザーで起動します。 その後、ターミナルを使用してコンテナーを操作できます。
ファイル: app.py
Python コードは、Gradio を使用して、トランスフォーマーを使用してトレーニングされたテキスト生成モデルのデモを作成する方法を示しています。 このコードを使用すると、ユーザーはテキストプロンプトを入力し、テキストの続きを生成できます。
Gradioは、インタラクティブな機械学習デモを簡単に作成して共有できるPythonライブラリです。 デモを作成およびデプロイするためのシンプルで直感的なインターフェイスを提供し、トランスフォーマーを含む幅広い機械学習フレームワークとライブラリをサポートします。
このPythonスクリプトは、テキストチャットボットのGradioデモです。 事前トレーニング済みのテキスト生成モデルを使用して、ユーザー入力に対する応答を生成します。 ファイルを分解し、各セクションを見ていきます。
次の行は、 Iterator
モジュールから型をインポートします typing
。 この型は、反復処理できる値のシーケンスを表すために使用されます。 次の行では、 gradio
ライブラリもインポートされます。
1 2 | from typing import Iterator import gradio as gr |
次の行は logging
、自然言語処理用の一般的な機械学習ライブラリであるライブラリから transformers
モジュールをインポートします。
1 2 | from transformers.utils import logging from model import get_input_token_length, run |
次に、この行は get_input_token_length()
model モジュールから and run()
関数をインポートします。 これらの関数は、テキストの入力トークンの長さを計算し、事前トレーニング済みのテキスト生成モデルを使用してテキストを生成するためにそれぞれ使用されます。 次の 2 行では、情報レベルのメッセージを出力し、transformers ロガーを使用するように logging モジュールを設定します。
1 2 3 4 | from model import get_input_token_length, run logging.set_verbosity_info() logger = logging.get_logger( "transformers" ) |
次の行は、コード全体で使用されるいくつかの定数を定義しています。 また、行は Gradio デモで表示されるテキストを定義します。
1 2 3 4 5 6 7 8 | DEFAULT_SYSTEM_PROMPT = """""" MAX_MAX_NEW_TOKENS = 2048 DEFAULT_MAX_NEW_TOKENS = 1024 MAX_INPUT_TOKEN_LENGTH = 4000 DESCRIPTION = """""" LICENSE = """""" |
この行は、コードが開始中であることを示す情報レベルのメッセージをログに記録します。 この関数は、テキストボックスをクリアし、入力メッセージを状態変数に saved_input
保存します。
1 2 3 | logger.info( "Starting" ) def clear_and_save_textbox(message: str ) - > tuple [ str , str ]: return '', message |
以下の関数は、入力したメッセージをチャットボットに表示し、チャット履歴にメッセージを追加します。
1 2 3 4 5 | def display_input(message: str , history: list [ tuple [ str , str ]]) - > list [ tuple [ str , str ]]: history.append((message, '')) logger.info( "display_input=%s" ,message) return history |
この関数は、チャット履歴から以前の応答を削除し、更新されたチャット履歴と以前の応答を返します。
1 2 3 4 5 6 7 | def delete_prev_fn( history: list [ tuple [ str , str ]]) - > tuple [ list [ tuple [ str , str ]], str ]: try : message, _ = history.pop() except IndexError: message = '' return history, message or '' |
次の関数は、事前トレーニング済みのテキスト生成モデルと指定されたパラメーターを使用してテキストを生成します。 これは、各タプルが入力メッセージと生成された応答を含むタプルのリストを生成するイテレータを返します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | def generate( message: str , history_with_input: list [ tuple [ str , str ]], system_prompt: str , max_new_tokens: int , temperature: float , top_p: float , top_k: int , ) - > Iterator[ list [ tuple [ str , str ]]]: #logger.info("message=%s",message) if max_new_tokens > MAX_MAX_NEW_TOKENS: raise ValueError history = history_with_input[: - 1 ] generator = run(message, history, system_prompt, max_new_tokens, temperature, top_p, top_k) try : first_response = next (generator) yield history + [(message, first_response)] except StopIteration: yield history + [(message, '')] for response in generator: yield history + [(message, response)] |
次の関数は、指定されたメッセージに対する応答を生成し、空の文字列と生成された応答を返します。
1 2 3 4 5 | def process_example(message: str ) - > tuple [ str , list [ tuple [ str , str ]]]: generator = generate(message, [], DEFAULT_SYSTEM_PROMPT, 1024 , 1 , 0.95 , 50 ) for x in generator: pass return '', x |
完全なPythonコードは次のとおりです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | from typing import Iterator import gradio as gr from transformers.utils import logging from model import get_input_token_length, run logging.set_verbosity_info() logger = logging.get_logger( "transformers" ) DEFAULT_SYSTEM_PROMPT = """""" MAX_MAX_NEW_TOKENS = 2048 DEFAULT_MAX_NEW_TOKENS = 1024 MAX_INPUT_TOKEN_LENGTH = 4000 DESCRIPTION = """""" LICENSE = """""" logger.info( "Starting" ) def clear_and_save_textbox(message: str ) - > tuple [ str , str ]: return '', message def display_input(message: str , history: list [ tuple [ str , str ]]) - > list [ tuple [ str , str ]]: history.append((message, '')) logger.info( "display_input=%s" ,message) return history def delete_prev_fn( history: list [ tuple [ str , str ]]) - > tuple [ list [ tuple [ str , str ]], str ]: try : message, _ = history.pop() except IndexError: message = '' return history, message or '' def generate( message: str , history_with_input: list [ tuple [ str , str ]], system_prompt: str , max_new_tokens: int , temperature: float , top_p: float , top_k: int , ) - > Iterator[ list [ tuple [ str , str ]]]: #logger.info("message=%s",message) if max_new_tokens > MAX_MAX_NEW_TOKENS: raise ValueError history = history_with_input[: - 1 ] generator = run(message, history, system_prompt, max_new_tokens, temperature, top_p, top_k) try : first_response = next (generator) yield history + [(message, first_response)] except StopIteration: yield history + [(message, '')] for response in generator: yield history + [(message, response)] def process_example(message: str ) - > tuple [ str , list [ tuple [ str , str ]]]: generator = generate(message, [], DEFAULT_SYSTEM_PROMPT, 1024 , 1 , 0.95 , 50 ) for x in generator: pass return '', x def check_input_token_length(message: str , chat_history: list [ tuple [ str , str ]], system_prompt: str ) - > None : #logger.info("check_input_token_length=%s",message) input_token_length = get_input_token_length(message, chat_history, system_prompt) #logger.info("input_token_length",input_token_length) #logger.info("MAX_INPUT_TOKEN_LENGTH",MAX_INPUT_TOKEN_LENGTH) if input_token_length > MAX_INPUT_TOKEN_LENGTH: logger.info( "Inside IF condition" ) raise gr.Error(f 'The accumulated input is too long ({input_token_length} > {MAX_INPUT_TOKEN_LENGTH}). Clear your chat history and try again.' ) #logger.info("End of check_input_token_length function") with gr.Blocks(css = 'style.css' ) as demo: gr.Markdown(DESCRIPTION) gr.DuplicateButton(value = 'Duplicate Space for private use' , elem_id = 'duplicate-button' ) with gr.Group(): chatbot = gr.Chatbot(label = 'Chatbot' ) with gr.Row(): textbox = gr.Textbox( container = False , show_label = False , placeholder = 'Type a message...' , scale = 10 , ) submit_button = gr.Button( 'Submit' , variant = 'primary' , scale = 1 , min_width = 0 ) with gr.Row(): retry_button = gr.Button( 'Retry' , variant = 'secondary' ) undo_button = gr.Button( 'Undo' , variant = 'secondary' ) clear_button = gr.Button( 'Clear' , variant = 'secondary' ) saved_input = gr.State() with gr.Accordion(label = 'Advanced options' , open = False ): system_prompt = gr.Textbox(label = 'System prompt' , value = DEFAULT_SYSTEM_PROMPT, lines = 6 ) max_new_tokens = gr.Slider( label = 'Max new tokens' , minimum = 1 , maximum = MAX_MAX_NEW_TOKENS, step = 1 , value = DEFAULT_MAX_NEW_TOKENS, ) temperature = gr.Slider( label = 'Temperature' , minimum = 0.1 , maximum = 4.0 , step = 0.1 , value = 1.0 , ) top_p = gr.Slider( label = 'Top-p (nucleus sampling)' , minimum = 0.05 , maximum = 1.0 , step = 0.05 , value = 0.95 , ) top_k = gr.Slider( label = 'Top-k' , minimum = 1 , maximum = 1000 , step = 1 , value = 50 , ) gr.Markdown(LICENSE) textbox.submit( fn = clear_and_save_textbox, inputs = textbox, outputs = [textbox, saved_input], api_name = False , queue = False , ).then( fn = display_input, inputs = [saved_input, chatbot], outputs = chatbot, api_name = False , queue = False , ).then( fn = check_input_token_length, inputs = [saved_input, chatbot, system_prompt], api_name = False , queue = False , ).success( fn = generate, inputs = [ saved_input, chatbot, system_prompt, max_new_tokens, temperature, top_p, top_k, ], outputs = chatbot, api_name = False , ) button_event_preprocess = submit_button.click( fn = clear_and_save_textbox, inputs = textbox, outputs = [textbox, saved_input], api_name = False , queue = False , ).then( fn = display_input, inputs = [saved_input, chatbot], outputs = chatbot, api_name = False , queue = False , ).then( fn = check_input_token_length, inputs = [saved_input, chatbot, system_prompt], api_name = False , queue = False , ).success( fn = generate, inputs = [ saved_input, chatbot, system_prompt, max_new_tokens, temperature, top_p, top_k, ], outputs = chatbot, api_name = False , ) retry_button.click( fn = delete_prev_fn, inputs = chatbot, outputs = [chatbot, saved_input], api_name = False , queue = False , ).then( fn = display_input, inputs = [saved_input, chatbot], outputs = chatbot, api_name = False , queue = False , ).then( fn = generate, inputs = [ saved_input, chatbot, system_prompt, max_new_tokens, temperature, top_p, top_k, ], outputs = chatbot, api_name = False , ) undo_button.click( fn = delete_prev_fn, inputs = chatbot, outputs = [chatbot, saved_input], api_name = False , queue = False , ).then( fn = lambda x: x, inputs = [saved_input], outputs = textbox, api_name = False , queue = False , ) clear_button.click( fn = lambda : ([], ''), outputs = [chatbot, saved_input], queue = False , api_name = False , ) demo.queue(max_size = 20 ).launch(share = False , server_name = "0.0.0.0" ) |
とgenerate
関数はcheck_input_token_length
、コードの主要部分を構成します。この generate
関数は、メッセージ、以前のメッセージの履歴、および次のようなさまざまな生成パラメーターを指定して応答を生成する役割を担います。
max_new_tokens
: これは、応答生成モデルが生成できるトークンの最大数を示す整数です。temperature
: この浮動小数点値は、生成される出力のランダム性を調整します。 結果は、高い値 (1.0 など) ではよりランダムになり、低いレベル (0.2 など) では予測しやすくなります。top_p
: 核サンプリングは、0 から 1 の範囲のこの浮動小数点値によって決定されます。 これにより、トークンの累積確率のカットオフポイントが確立されます。top_k
: 次に考慮されるトークンの数は、この整数で表されます。 数値が大きいほど、出力が集中します。
UI コンポーネントと API サーバーの実行は、 によって app.py
処理されます。 基本的には、 app.py
アプリケーションやその他の構成を初期化する場所です。
ファイル: Model.py
Python スクリプトは、LLM を使用してユーザー入力に対する応答を生成するチャット ボットです。 このスクリプトでは、次の手順を使用して応答を生成します。
- ユーザ入力、チャット履歴、およびシステム プロンプトを組み合わせて、LLM のプロンプトを作成します。
- プロンプトの入力トークンの長さを計算します。
- LLM と次のパラメーターを使用して応答を生成します。
max_new_tokens
: 生成する新しいトークンの最大数。temperature
: 応答を生成するときに使用する温度。 温度が高いほど、より創造的で多様な応答が得られますが、一貫性の低い応答になる可能性もありますtop_p
: このパラメータは、応答の生成に使用される核サンプリングアルゴリズムを制御します。 値が大きいtop_p
ほど、より焦点を絞った有益な回答が得られ、値が小さいほど、より創造的で多様な回答が得られます。top_k
: このパラメーターは、応答を生成するときに考慮する最も確率の高いトークンの数を制御します。 値が大きいtop_k
ほど、より予測可能で一貫性のある応答が得られ、値が小さいほど、より創造的で多様な応答が得られます。
この TextIteratorStreamer
クラスの主な機能は、印刷可能なテキストをキューに格納することです。 このキューは、ダウンストリーム アプリケーションで反復子として使用して、生成されたテキストに非ブロッキングな方法でアクセスできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | from threading import Thread from typing import Iterator #import torch from transformers.utils import logging from ctransformers import AutoModelForCausalLM from transformers import TextIteratorStreamer, AutoTokenizer logging.set_verbosity_info() logger = logging.get_logger( "transformers" ) config = { "max_new_tokens" : 256 , "repetition_penalty" : 1.1 , "temperature" : 0.1 , "stream" : True } model_id = "TheBloke/Llama-2-7B-Chat-GGML" device = "cpu" model = AutoModelForCausalLM.from_pretrained(model_id, model_type = "llama" , lib = "avx2" , hf = True ) tokenizer = AutoTokenizer.from_pretrained( "meta-llama/Llama-2-7b-chat-hf" ) def get_prompt(message: str , chat_history: list [ tuple [ str , str ]], system_prompt: str ) - > str : #logger.info("get_prompt chat_history=%s",chat_history) #logger.info("get_prompt system_prompt=%s",system_prompt) texts = [f '<s>[INST] <<SYS>>\n{system_prompt}\n<</SYS>>\n\n' ] #logger.info("texts=%s",texts) do_strip = False for user_input, response in chat_history: user_input = user_input.strip() if do_strip else user_input do_strip = True texts.append(f '{user_input} [/INST] {response.strip()} </s><s>[INST] ' ) message = message.strip() if do_strip else message #logger.info("get_prompt message=%s",message) texts.append(f '{message} [/INST]' ) #logger.info("get_prompt final texts=%s",texts) return ''.join(texts) def get_input_token_length(message: str , chat_history: list [ tuple [ str , str ]], system_prompt: str ) - > int : #logger.info("get_input_token_length=%s",message) prompt = get_prompt(message, chat_history, system_prompt) #logger.info("prompt=%s",prompt) input_ids = tokenizer([prompt], return_tensors = 'np' , add_special_tokens = False )[ 'input_ids' ] #logger.info("input_ids=%s",input_ids) return input_ids.shape[ - 1 ] def run(message: str , chat_history: list [ tuple [ str , str ]], system_prompt: str , max_new_tokens: int = 1024 , temperature: float = 0.8 , top_p: float = 0.95 , top_k: int = 50 ) - > Iterator[ str ]: prompt = get_prompt(message, chat_history, system_prompt) inputs = tokenizer([prompt], return_tensors = 'pt' , add_special_tokens = False ).to(device) streamer = TextIteratorStreamer(tokenizer, timeout = 15. , skip_prompt = True , skip_special_tokens = True ) generate_kwargs = dict ( inputs, streamer = streamer, max_new_tokens = max_new_tokens, do_sample = True , top_p = top_p, top_k = top_k, temperature = temperature, num_beams = 1 , ) t = Thread(target = model.generate, kwargs = generate_kwargs) t.start() outputs = [] for text in streamer: outputs.append(text) yield "".join(outputs) |
トランスフォーマーを使用したテキスト生成に必要なモジュールとライブラリをインポートするには、次のコードを使用できます。
1 | from transformers import AutoTokenizer, AutoModelForCausalLM |
これにより、トランスフォーマーを使用したテキストのトークン化と生成に必要なモジュールがインポートされます。
インポートするモデルを定義するには、以下を使用できます。
1 | model_id = "TheBloke/Llama-2-7B-Chat-GGML" |
この手順では、モデル ID を Meta 7B チャット LLama モデルの縮小バージョンとして TheBloke/Llama-2-7B-Chat-GGML
定義します。
必要なモジュールとライブラリをインポートし、インポートするモデルを定義したら、次のコードを使用してトークナイザーとモデルを読み込むことができます。
1 2 | tokenizer = AutoTokenizer.from_pretrained(model_id) model = AutoModelForCausalLM.from_pretrained(model_id) |
これにより、Hugging Face Hub からトークナイザーとモデルが読み込まれます。トークナイザーの仕事は、モデルの入力を準備することです。 各モデルのトークナイザーは、ライブラリで入手できます。 インポートするモデルを定義します。ここでも、 TheBloke/Llama-2-7B-Chat-GGML
.
、max_new_tokens
およびstream
configで変数temperature
repetition_penalty
と値を設定する必要があります。
max_new_tokens
: プロンプトで指定されたトークン数を無視して、可能なほとんどのトークン。temperature
: 後続のトークンの確率を変更するために使用された金額。repetition_penalty
: 繰り返しペナルティパラメータ。 1.0 は罰がないことを示します。川
: 応答テキストをストリーミング方式で生成するか、1 つのバッチで生成するか。
また、スペースを作成し、そのスペースにファイルをコミットして、Hugging Faceでアプリケーションをホストし、直接テストすることもできます。
イメージのビルド
次のコマンドは、プラットフォーム上にモデルの Docker イメージ llama-2-13b-chat
をビルドします linux/amd64
。 画像には という名前 local-llm:v1
が付けられます。
1 | docker buildx build --platform=linux/amd64 -t local-llm:v1 . |
コンテナの実行
次のコマンドは、Dockerイメージを実行する local-llm:v1
新しいコンテナを起動し、ホストマシン上のポート 7860
を公開します。 環境変数は -e HUGGING_FACE_HUB_TOKEN="YOUR_VALUE_HERE"
、Hugging Face Hubからモデルをダウンロードする llama-2-13b-chat
ために必要なHugging Face Hubトークンを設定します。
1 | docker run -it -p 7860:7860 --platform=linux/amd64 -e HUGGING_FACE_HUB_TOKEN="YOUR_VALUE_HERE" local-llm:v1 python app.py |
次に、ブラウザを開いて http://localhost:7860 に移動し、ローカルのLLM Dockerコンテナの出力を確認します(図3)。

また、Docker Desktop からコンテナーを表示することもできます (図 4)。

結論
Docker を使用して LLM GGML モデルをローカルにデプロイすることは、自然言語処理を使用するための便利で効果的な方法です。 モデルをドッキングすると、異なる環境間での移動が容易になり、一貫性のある実行が保証されます。 ブラウザーでモデルをテストすると、ユーザー フレンドリーなインターフェイスが提供され、そのパフォーマンスをすばやく評価できます。
このセットアップにより、インフラストラクチャとデータをより詳細に制御でき、さまざまなアプリケーション用の高度な言語モデルを簡単にデプロイできます。 これは、大規模言語モデルの展開における重要な一歩です。
さらに詳しく
- 「 Build Machine Learning Apps with Hugging Face の Docker Spaces」をお読みください。
- Docker デスクトップの最新リリースを入手します。
- 次のものに投票してください! 公開ロードマップをご覧ください。
- 質問がありますか? Docker コミュニティがお手伝いします。
- ドッカーは初めてですか? 始めましょう。