WSL2でLLM-jp-3-*-instructをvLLMと共に試してみる
「オープンかつ日本語に強いGPT-3級大規模言語モデル「LLM-jp-3 172B」の事前学習に使用しているコーパスで学習した 1.8B、3.7B、13B の各モデルを公開」したらしいので試してみます。
それぞれのモデル毎に、ベースとinstruct の各モデルが公開されています。今回はinstructのモデル3つを試します。
使用するPCはドスパラさんの「GALLERIA UL9C-R49」。スペックは
・CPU: Intel® Core™ i9-13900HX Processor
・Mem: 64 GB
・GPU: NVIDIA® GeForce RTX™ 4090 Laptop GPU(16GB)・GPU: NVIDIA® GeForce RTX™ 4090 (24GB)
・OS: Ubuntu22.04 on WSL2(Windows 11)
です。
1. 準備
仮想環境
python3 -m venv vllm
cd $_
source bin/activate
つづいて、パッケージのインストール。
pip install -U vllm
vLLMのインストール時にtorchやら依存関係必要なものは勝手にインストールされます。
2. 流し込むコード
こちらを/path/to/query4vllm.pyとして保存します。
import sys
import argparse
from vllm import LLM, SamplingParams
from typing import List, Dict
import time
# argv
parser = argparse.ArgumentParser()
parser.add_argument("--model-path", type=str, default=None)
parser.add_argument("--no-chat", action='store_true')
parser.add_argument("--no-use-system-prompt", action='store_true')
parser.add_argument("--max-model-len", type=int, default=32768)
parser.add_argument("--tensor-parallel-size", type=int, default=1)
parser.add_argument("--gpu-memory-utilization", type=float, default=0.2)
parser.add_argument("--max-tokens", type=int, default=4096)
args = parser.parse_args(sys.argv[1:])
model_id = args.model_path
if model_id == None:
exit
is_chat = not args.no_chat
use_system_prompt = not args.no_use_system_prompt
max_new_tokens = args.max_tokens
tensor_parallel_size = args.tensor_parallel_size
max_model_len = args.max_model_len
gpu_memory_utilization = args.gpu_memory_utilization
# トークナイザーとモデルの準備
model = LLM(
model=model_id,
dtype="auto",
trust_remote_code=True,
tensor_parallel_size=tensor_parallel_size,
max_model_len=max_model_len,
#quantization="awq",
gpu_memory_utilization=gpu_memory_utilization
)
tokenizer = model.get_tokenizer()
DEFAULT_SYSTEM_PROMPT = "あなたは誠実で優秀な日本人のアシスタントです。"
def q(
user_query: str,
history: List[Dict[str, str]]=None
) -> List[Dict[str, str]]:
# generation params
generation_params = SamplingParams(
temperature=0.8,
top_p=0.95,
top_k=40,
max_tokens=max_new_tokens,
repetition_penalty=1.1
)
#
start = time.process_time()
# messages
messages = ""
if is_chat:
messages = []
if use_system_prompt:
messages = [
{"role": "system", "content": DEFAULT_SYSTEM_PROMPT},
]
user_messages = [
{"role": "user", "content": user_query}
]
else:
user_messages = user_query
if history:
user_messages = history + user_messages
messages += user_messages
# generation prompts
if is_chat:
prompt = tokenizer.apply_chat_template(
conversation=messages,
add_generation_prompt=True,
tokenize=False
)
else:
prompt = messages
input_ids = tokenizer.encode(
prompt,
add_special_tokens=True,
)
print("--- prompt")
print(prompt)
print("--- output")
# 推論
outputs = model.generate(
sampling_params=generation_params,
prompt_token_ids=[input_ids],
)
print(outputs)
output = outputs[0]
print(output.outputs[0].text)
if is_chat:
user_messages.append(
{"role": "assistant", "content": output.outputs[0].text}
)
else:
user_messages += output.outputs[0].text
end = time.process_time()
##
input_tokens = len(output.prompt_token_ids)
output_tokens = len(output.outputs[0].token_ids)
total_time = end - start
tps = output_tokens / total_time
print(f"prompt tokens = {input_tokens:.7g}")
print(f"output tokens = {output_tokens:.7g} ({tps:f} [tps])")
print(f" total time = {total_time:f} [s]")
return user_messages
3. 試してみる
(1) llm-jp/llm-jp-3-1.8b-instruct
1.8Bモデルに聞いてみます。
CUDA_VISIBLE_DEVICES=0 python -i /path/to/query4vllm.py \
--model-path llm-jp/llm-jp-3-1.8b-instruct \
--max-model-len 4096 \
--gpu-memory-utilization 0.99
pythonプロンプトが表示されたら、聞きましょう。
>>> history = q("ドラえもんとはなにか")
--- prompt
<s>以下は、タスクを説明する指示です。要求を適切に満たす応答を書きなさい。
### 指示:
ドラえもんとはなにか
### 応答:
--- output
Processed prompts: 100%|███████████████████| 1/1 [00:02<00:00, 2.47s/it, est. speed input: 14.99 toks/s, output: 149.07 toks/s]
prompt tokens = 37
output tokens = 368 (147.064601 [tps])
total time = 2.502302 [s]
ドラミちゃんが少女になっていますが、1.8Bでこの内容はいいんじゃないでしょうか。推論もちょー速いですし。
(2) llm-jp/llm-jp-3-3.7b-instruct
3.7Bモデルに聞いてみます。
CUDA_VISIBLE_DEVICES=0 python -i /path/to/query4vllm.py \
--model-path llm-jp/llm-jp-3-3.7b-instruct \
--max-model-len 4096 \
--gpu-memory-utilization 0.99
pythonプロンプトが表示されたら、聞きましょう。
>>> history = q("ドラえもんとはなにか")
--- prompt
<s>以下は、タスクを説明する指示です。要求を適切に満たす応答を書きなさい。
### 指示:
ドラえもんとはなにか
### 応答:
--- output
Processed prompts: 100%|█████████████████████| 1/1 [00:06<00:00, 6.47s/it, est. speed input: 5.72 toks/s, output: 91.26 toks/s]
prompt tokens = 37
output tokens = 590 (90.673710 [tps])
total time = 6.506847 [s]
ノビタオーラ号、宝島ですな。
(3) llm-jp/llm-jp-3-13b-instruct
config.json のパラメータ値を確認しつつ、起動します。
13Bモデルですと1x24GBでは足りませんので、tensor-parallel-sizeを2としてGPUを2枚使用します。
CUDA_VISIBLE_DEVICES=0,1 python -i /path/to/query4vllm.py \
--model-path llm-jp/llm-jp-3-13b-instruct \
--max-model-len 4096 \
--tensor-parallel-size 2 \
--gpu-memory-utilization 0.95
聞いてみましょう。
>>> history = q("ドラえもんとはなにか")
--- prompt
<s>以下は、タスクを説明する指示です。要求を適切に満たす応答を書きなさい。
### 指示:
ドラえもんとはなにか
### 応答:
--- output
Processed prompts: 100%|█████████████████████| 1/1 [00:18<00:00, 18.05s/it, est. speed input: 2.05 toks/s, output: 24.04 toks/s]
prompt tokens = 37
output tokens = 434 (23.939246 [tps])
total time = 18.129226 [s]
4. まとめ
1.8Bモデルもとてもいいかんじ。他のモデルもきちんとドラえもんのことを学習しているように見えます。すばらしい。