File size: 6,191 Bytes
fb34003
 
 
 
 
 
 
 
 
 
 
f4b9fb8
fb34003
 
 
 
 
 
 
 
 
 
 
f4b9fb8
 
 
 
 
 
 
 
 
 
 
 
 
 
c2fd441
 
f4b9fb8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c2fd441
 
 
f4b9fb8
 
 
 
 
 
 
9a26811
f4b9fb8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d83dbe4
f4b9fb8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d83dbe4
f4b9fb8
d83dbe4
f4b9fb8
 
d83dbe4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f4b9fb8
 
 
 
 
 
 
 
 
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
---
base_model: llm-jp/llm-jp-3-13b
tags:
- text-generation-inference
- transformers
- unsloth
- llama
- trl
license: apache-2.0
language:
- en
library_name: peft
---

# Uploaded  model

- **Developed by:** libkazz
- **License:** apache-2.0
- **Finetuned from model :** llm-jp/llm-jp-3-13b

This llama model was trained 2x faster with [Unsloth](https://github.com/unslothai/unsloth) and Huggingface's TRL library.

[<img src="https://raw.githubusercontent.com/unslothai/unsloth/main/images/unsloth%20made%20with%20love.png" width="200"/>](https://github.com/unslothai/unsloth)

### Training Details
指示チューニングデータとして下記のものを利用しました。
* ichikara-instruction-003-001-1.json
* ichikara-instruction-003-002-1.json 
* ichikara-instruction-003-003-1.json

以下について, 指示に対して複数の回答を持つデータは回答を1件のみ抽出して指示データをして利用しました。
* ichikara-instruction-003-001-5.1.json 
* ichikara-instruction-003-001-5.2.json 
* ichikara-instruction-003-001-2.1.json 
* ichikara-instruction-003-001-2.2.json 

回答を1件のみ抽出するために gpt-4o-mini で下記 script を利用しました。
<details>
  <summary>script</summary>

```python
# gpt-4o-mini を使って最も適切そうな回答を選定
def select_best_response(file_path, output_dir):
    with open(file_path, "r", encoding="utf-8") as file:
        data = json.load(file)

    grouped_data = {}
    
    # データをデータ番号ごとに分類
    for item in data:
        data_number = item["ID"].split("-")[4]
        grouped_data.setdefault(data_number, []).append(item)
    
    filtered_data = []
    for data_number, responses in grouped_data.items():
        print(f"\n#### {data_number} ####")

        # 指示と回答リストを生成
        instructions = [r["text"] for r in responses]
        outputs = [r["output"] for r in responses]
        
        # GPT-4o-miniに最適な回答を選定させる
        prompt = (
            "以下の指示に対して最も適切な回答を選定してください。\n\n"
            f"### 指示 ###\n```\n{instructions[0]}\n```\n\n"
            "### 候補 ###\n" + "\n\n".join([f"{i+1}: \n```\n{output}\n```" for i, output in enumerate(outputs)]) +
            "\n\n### 回答 ###\n番号(1 or 2)のみを回答してください。1つだけ選択してください。\n"
        )

        try:
            response = openai.chat.completions.create(
                model="gpt-4o-mini",
                messages=[
                    {"role": "system", "content": "あなたはIQ140の論理的思考力の高い文章評価の専門家です。"},
                    {"role": "user", "content": prompt}
                ]
            )
            content = response.choices[0].message.content
            print(content)
            best_choice = int(content.strip()) - 1
        except ValueError as e:
            print(f"ValueError: 無効な応答がありました。データ番号: {data_number}")
            print(f"応答内容: {response.choices[0].message['content']}")
            best_choice = 1
        except Exception as e:
            print(f"予期しないエラーが発生しました。データ番号: {data_number}")
            print(e)
            best_choice = 1

        filtered_data.append(responses[best_choice])
    
    output_file_name = os.path.basename(file_path)
    output_file_path = os.path.join(output_dir, output_file_name)
    with open(output_file_path, "w", encoding="utf-8") as output_file:
        json.dump(filtered_data, output_file, ensure_ascii=False, indent=2)
```

  
</details>

### ライセンス
* ichikara-instruction データセットのライセンスは cc-by-nc-sa になっております。

### SFTの概要
* 4bit量子化
* LoRAによるSFT
* learning_rate = 2e-4
* num_train_epochs = 2

## Bias, Risks, and Limitations
RLHF,DPOを実施していないため不適切な表現が出力される可能性があります。

# elyza-tasks-100-TV_0.jsonl の出力方法

elyza-tasks-100-TV_0.jsonl に記載されている指示に対する返答のサンプル出力コードは次のようになります。

```python
import torch
from transformers import (
    AutoTokenizer,
    AutoModelForCausalLM,
    BitsAndBytesConfig,
)
from peft import LoraConfig, PeftModel
from datasets import load_dataset

BASE_MODEL = "llm-jp/llm-jp-3-13b"
PEFT_MODEL = "libkazz/llm-jp-3-13b-it_lora"

tokenizer = AutoTokenizer.from_pretrained(PEFT_MODEL)
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_compute_dtype=torch.float16,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_use_double_quant=False,
)

base_model = AutoModelForCausalLM.from_pretrained(
            BASE_MODEL,
            device_map="auto",
            quantization_config=bnb_config,
            torch_dtype="auto",
            trust_remote_code=True,
        )

model = PeftModel.from_pretrained(base_model, PEFT_MODEL)

# elyza-tasks-100-TV_0.jsonl データの読み込み
from datasets import load_dataset
from tqdm import tqdm

datasets = load_dataset("json", data_files="./elyza-tasks-100-TV_0.jsonl", split="train")

results = []
for dt in tqdm(datasets):
  input = dt["input"]
  prompt = f"次の指示に忠実に回答を作成しなさい。\n\n### 指示:\n{input}\n\n### 回答:\n"

  model_input = tokenizer([prompt], return_tensors = "pt").to(model.device)

  if "token_type_ids" in model_input:
      del model_input["token_type_ids"]
  
  outputs = model.generate(
      **model_input,
      max_new_tokens = 512,
      pad_token_id=tokenizer.pad_token_id,
      eos_token_id=tokenizer.eos_token_id,
      use_cache = True,
      do_sample=False,
      repetition_penalty=1.2
    )
  
  prediction = tokenizer.decode(outputs[0], skip_special_tokens=True).split('\n### 回答')[-1]
  results.append({"task_id": dt["task_id"], "input": input, "output": prediction})

# ファイルに保存する
import json
with open("output.jsonl", "wt", encoding='utf-8') as f:
    for result in results:
        json.dump(result, f, ensure_ascii=False)
        f.write('\n')
```