Views
No views yet
1# 必要なライブラリを読み込み
2from unsloth import FastLanguageModel
3from peft import PeftModel
4import torch
5import json
6from tqdm import tqdm
7import re
8
9# ベースとなるモデルと学習したLoRAのアダプタ(Hugging FaceのIDを指定)。
10model_id = "llm-jp/llm-jp-3-13b"
11adapter_id = "ToshiyukiNH/llm-jp-3-13b-it-gct4_lora"
12
13# Hugging Face Token を指定。
14HF_TOKEN = "your-token"
15
16# unslothのFastLanguageModelで元のモデルをロード。
17dtype = None # Noneにしておけば自動で設定
18load_in_4bit = True # 今回は13Bモデルを扱うためTrue
19
20model, tokenizer = FastLanguageModel.from_pretrained(
21 model_name=model_id,
22 dtype=dtype,
23 load_in_4bit=load_in_4bit,
24 trust_remote_code=True,
25)
26
27# 元のモデルにLoRAのアダプタを統合。
28model = PeftModel.from_pretrained(
29 model, adapter_id,
30 token = HF_TOKEN
31)
32
33# タスクとなるデータの読み込み。
34datasets = []
35with open("./elyza-tasks-100-TV_0.jsonl", "r") as f:
36 item = ""
37 for line in f:
38 line = line.strip()
39 item += line
40 if item.endswith("}"):
41 datasets.append(json.loads(item))
42 item = ""
43
44# prompting
45system_instruction = """
46あなたは思慮深くユーモアのある社会人です。以下の注意点をよく読み、ユーザーからの指示に対してステップバイステップで考え、そして端的に回答してください。
47
48### 注意点
49- ユーザーからの指示に正確に従ってください。
50- 200文字以内で回答してください。
51- 数字のみを用いて回答できる指示に対しては、数字のみを用いて回答してください。
52- 回答内の数字はすべて半角に変換してください。
53- 回答内の全角スペースおよび記号 "\u3000" は全て半角スペースに変換してください。
54- 回答を見直し、その回答が日本語としておかしい場合は一度だけ再考してください。
55
56"""
57
58prompt_template = """
59### 指示
60{instruction}
61
62### 回答
63"""
64
65# モデルを用いてタスクの推論。
66
67
68# 推論するためにモデルのモードを変更
69FastLanguageModel.for_inference(model)
70
71results = []
72for dt in tqdm(datasets):
73 input = dt["input"]
74
75 prompt = f"""### 指示\n{input}\n### 回答\n"""
76
77# inputs = tokenizer([prompt], return_tensors = "pt").to(model.device)
78 messages = [
79 system_instruction,
80 prompt_template.format(instruction=input)
81 ]
82 inputs = tokenizer(["".join(messages)], return_tensors = "pt").to(model.device)
83
84 outputs = model.generate(**inputs, max_new_tokens = 512, use_cache = True, do_sample=False, repetition_penalty=1.2)
85 prediction = tokenizer.decode(outputs[0], skip_special_tokens=True).split('\n### 回答')[-1]
86
87 results.append({"task_id": dt["task_id"], "input": input, "output": prediction})
88
89# 結果をjsonlで保存。
90
91# ここではadapter_idを元にファイル名を決定しているが、ファイル名は任意で問題なし。
92json_file_id = re.sub(".*/", "", adapter_id)
93with open(f"./{json_file_id}_output.jsonl", 'w', encoding='utf-8') as f:
94 for result in results:
95 json.dump(result, f, ensure_ascii=False)
96 f.write('\n')