| | --- |
| | base_model: |
| | - llm-jp/llm-jp-3-3.7b-instruct2 |
| | license: apache-2.0 |
| | datasets: |
| | - p1atdev/gsm8k-ja-slim |
| | - SyntheticVeryEasyMath5k |
| | - SyntheticWhichIsGreater5k |
| | language: |
| | - ja |
| | library_name: transformers |
| | tags: |
| | - grpo |
| | - trl |
| | --- |
| | |
| | additional instruction: |
| |
|
| | ``` |
| | 回答する際は、思考過程を<think></think>ブロック内に記述し、最終的な答えを数値のみで<answer></answer>ブロック内に記述してください。 |
| | ``` |
| |
|
| | ## Example |
| |
|
| | ```py |
| | import torch |
| | from transformers import AutoTokenizer, AutoModelForCausalLM |
| | |
| | tokenizer = AutoTokenizer.from_pretrained("p1atdev/llm-jp-3-3.7b-instruct2-R27") |
| | model = AutoModelForCausalLM.from_pretrained("p1atdev/llm-jp-3-3.7b-instruct2-R27", torch_dtype=torch.float16) |
| | model = model.eval().to("cuda") |
| | |
| | |
| | additional_instruction = "回答する際は、思考過程を<think></think>ブロック内に記述し、最終的な答えを数値のみで<answer></answer>ブロック内に記述してください。" |
| | question = "ナタリアは4月に48人の友人にクリップを販売し、その後5月にはその半分の数のクリップを販売しました。ナタリアは4月と5月の合計でいくつのクリップを販売しましたか?" |
| | |
| | inputs = tokenizer.apply_chat_template( |
| | [ |
| | { |
| | "role": "user", |
| | "content": question |
| | }, |
| | ], |
| | additional_instruction=additional_instruction, # pass the additional instruction |
| | tokenize=False, |
| | add_generation_prompt=True, # append "### 応答:" |
| | return_tensors="pt", |
| | ) |
| | inputs = tokenizer(inputs, return_tensors="pt").to(model.device) |
| | |
| | with torch.inference_mode(): |
| | outputs = model.generate( |
| | **inputs, |
| | do_sample=True, |
| | temperature=0.9, |
| | top_p=0.6, |
| | top_k=20, |
| | max_new_tokens=256, |
| | repetition_penalty=1.0, |
| | eos_token_id=tokenizer.eos_token_id, |
| | pad_token_id=tokenizer.pad_token_id, |
| | ) |
| | print(tokenizer.decode(outputs[0][len(inputs.input_ids[0]):])) |
| | ``` |
| |
|
| | the output: |
| |
|
| | ``` |
| | <think> |
| | 4月にナタリアは48人の友人にクリップを販売しました。 |
| | 5月にはその半分の数のクリップを販売したので、48 ÷ 2 = 24人の友人にクリップを販売したことになります。 |
| | したがって、4月と5月の合計でナタリアは48 + 24 = 72人の友人にクリップを販売したことになります。</think> |
| | <answer>72</answer></s> |
| | ``` |
| |
|
| |
|
| | ## Dataset |
| |
|
| | - 日本語訳した GSM8K ([p1atdev/gsm8k-ja-slim](https://huggingface.co/datasets/p1atdev/gsm8k-ja-slim)) |
| | - うち、苗字や人名に関する問題を除外 |
| | - SyntheticVeryEasyMath5k |
| | - 機械的に合成した、整数の四則演算問題 5,000問 |
| | - SyntheticWhichIsGreater5k |
| | - 機械的に合成した、二つの小数のどちらが大きいかを回答する問題 5,000問 |
| | |
| | 下の二つのデータは、[math_problem.py](https://huggingface.co/p1atdev/llm-jp-3-3.7b-instruct2-R27/blob/main/math_problem.py) の関数を使って以下のように合成しました。 |
| |
|
| | ```py |
| | def generate_int_problem( |
| | num_generation: int, |
| | max_int: int, |
| | min_int: int, |
| | max_terms: int, |
| | ): |
| | for i in range(num_generation): |
| | text, tex, result = create_integer_arithmetic_problem( |
| | max_val=max_int, |
| | min_val=min_int, |
| | max_terms=max_terms, |
| | ) |
| | formula = random.choice([text, tex]) |
| | templates = [ |
| | "{formula} = ?", |
| | "{formula} を計算してください。", |
| | "次の式を計算し、計算結果を解答してください。\n{formula}", |
| | "計算して\n{formula}", |
| | "次の式を計算してください。\n{formula}", |
| | "次の式の答えは何ですか?\n{formula}", |
| | "? に当てはまる数字を答えてください。\n{formula}", |
| | "{formula}\n計算して", |
| | "{formula}\n↑の答えを求めてください。", |
| | ] |
| | instruction = random.choice(templates).format(formula=formula) |
| | |
| | yield { |
| | "ground_truth": str(result), |
| | "instruction": instruction, |
| | "source": "synthetic_int_problem", |
| | "answer_dtype": "int", |
| | "skip_check": False, |
| | } |
| | |
| | def generate_wig_problem( |
| | num_generation: int, |
| | max_num: float, |
| | min_num: float, |
| | precision: int, |
| | ): |
| | for i in range(num_generation): |
| | num_1, num_2, greater = create_two_decimals( |
| | min_val=min_num, |
| | max_val=max_num, |
| | precision=precision, |
| | ) |
| | templates = [ |
| | "次の数字のうち、どちらが大きいですか?\n{num_1}\n{num_2}", |
| | "{num_1} と {num_2} のうちどちらが大きいですか?", |
| | "{num_1} と {num_2} はどっちが大きい?", |
| | "大きいほうを選んで: {num_1} {num_2}", |
| | "次の数値を比較し、大きい方を選んでください。\n{num_1} {num_2}", |
| | ] |
| | instruction = random.choice(templates).format(num_1=num_1, num_2=num_2) |
| | |
| | yield { |
| | "ground_truth": str(greater), |
| | "instruction": instruction, |
| | "source": "synthetic_which_is_greater", |
| | "answer_dtype": "float", |
| | "skip_check": False, |
| | } |
| | |
| | |
| | # generate dataset |
| | ds_easy_int = Dataset.from_generator( |
| | generate_int_problem, |
| | gen_kwargs={ |
| | "num_generation": 5000, |
| | "max_int": 10, |
| | "min_int": -10, |
| | "max_terms": 5, |
| | }, |
| | ) |
| | assert isinstance(ds_easy_int, Dataset) |
| | print("easy_int:", ds_easy_int) |
| | |
| | ds_wig = Dataset.from_generator( |
| | generate_wig_problem, |
| | gen_kwargs={ |
| | "num_generation": 5000, |
| | "max_num": 100.0, |
| | "min_num": -100.0, |
| | "precision": 3, |
| | }, |
| | ) |
| | assert isinstance(ds_wig, Dataset) |
| | print("wig:", ds_wig) |
| | |
| | # japanese gsm8k |
| | ds_gsm8k = load_dataset("p1atdev/gsm8k-ja-slim", split="train") |
| | assert isinstance(ds_gsm8k, Dataset) |
| | ds_gsm8k = ds_gsm8k.filter(filter_gsm8k_ja, batched=True) |
| | ds_gsm8k = ds_gsm8k.map( |
| | map_gsm8k_ja_instruction, remove_columns=ds_gsm8k.column_names |
| | ) |
| | print("gsm8k:", ds_gsm8k) |
| | |
| | # concat |
| | ds = concatenate_datasets( # from datasets import concatenate_datasets |
| | [ |
| | ds_gsm8k, |
| | ds_easy_int, |
| | ds_wig, |
| | ] |
| | ) |
| | print("total:", ds) |
| | ``` |
| |
|
| |
|