Divij commited on
Commit
8827fd2
·
verified ·
1 Parent(s): 409b314

Upload SFT checkpoint (with-thoughts, max_seq_len=6144)

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ base_model: meta-llama/Llama-3.2-3B-Instruct
3
+ library_name: transformers
4
+ license: llama3.2
5
+ pipeline_tag: text-generation
6
+ tags:
7
+ - sft
8
+ - scientific-reasoning
9
+ - instruction-tuning
10
+ - open-instruct
11
+ ---
12
+
13
+ # Divij/Llama-3.2-3B-Instruct-sft-with-thoughts
14
+
15
+ Supervised fine-tune of [`meta-llama/Llama-3.2-3B-Instruct`](https://huggingface.co/meta-llama/Llama-3.2-3B-Instruct) on a scientific-methodology
16
+ instruction dataset, where each assistant response interleaves `<Thought_i>` reasoning with `<Step_i>` actions.
17
+
18
+ The project goal is to compare whether including explicit `<Thought_i>` reasoning
19
+ traces alongside each `<Step_i>` action during SFT produces stronger scientific-methodology
20
+ generators than training on step-only plans.
21
+
22
+ ## Variant
23
+
24
+ This checkpoint is the **with-thoughts** variant:
25
+ The assistant target alternates `<Thought_i>` / `<Step_i>` pairs, so the model learns to produce explicit reasoning before each action. Trained with `max_seq_length=6144` to fit the longer sequences.
26
+
27
+ ## Training data
28
+
29
+ - Source: `sft_with_thoughts.jsonl` from the `verl_scientific_discovery`
30
+ repeated-sampling pipeline.
31
+ - 4,990 `messages`-format examples (`system` + `user` + `assistant`).
32
+ - Each assistant response is a step-by-step research methodology for a given
33
+ `Research Goal` + `Constraints` prompt.
34
+
35
+ ## Training setup
36
+
37
+ - **Framework:** [open-instruct](https://github.com/allenai/open-instruct) `finetune.py` (accelerate + FSDP2).
38
+ - **Hardware:** 2× NVIDIA H100 NVL (96 GB).
39
+ - **Precision:** bf16 mixed precision.
40
+ - **Attention:** FlashAttention-2.
41
+ - **Memory:** gradient checkpointing enabled.
42
+
43
+ ### Hyperparameters
44
+
45
+ | | |
46
+ |---|---|
47
+ | `max_seq_length` | **6144** |
48
+ | `num_train_epochs` | 3 |
49
+ | `per_device_train_batch_size` | 1 |
50
+ | `gradient_accumulation_steps` | 8 |
51
+ | Effective batch size | 16 (1 × 2 GPU × 8 accum) |
52
+ | `learning_rate` | 2e-5 |
53
+ | `lr_scheduler_type` | linear |
54
+ | `warmup_ratio` | 0.03 |
55
+ | `weight_decay` | 0.0 |
56
+ | `seed` | 42 |
57
+ | Optimizer | fused AdamW |
58
+ | Total optimization steps | 936 |
59
+ | **Final training loss** | **0.839** |
60
+
61
+ The chat template is inherited from the base model
62
+ (`meta-llama/Llama-3.2-3B-Instruct`). Labels are masked on the `system` and
63
+ `user` turns so only the assistant response contributes to the loss
64
+ (open-instruct's `sft_tulu_tokenize_and_truncate_v1` transform).
65
+
66
+ ## Usage
67
+
68
+ ```python
69
+ from transformers import AutoModelForCausalLM, AutoTokenizer
70
+ import torch
71
+
72
+ repo = "Divij/Llama-3.2-3B-Instruct-sft-with-thoughts"
73
+ tokenizer = AutoTokenizer.from_pretrained(repo)
74
+ model = AutoModelForCausalLM.from_pretrained(
75
+ repo,
76
+ torch_dtype=torch.bfloat16,
77
+ device_map="auto",
78
+ )
79
+
80
+ messages = [
81
+ {"role": "system", "content": "You are an expert research scientist. Produce reasoning/action pairs: <Thought_i> followed by <Step_i>."},
82
+ {"role": "user", "content": (
83
+ "You are given a scientific research problem.\n\n"
84
+ "Research Goal:\n<your research goal here>\n\n"
85
+ "Constraints:\n1) <constraint 1>\n2) <constraint 2>"
86
+ )},
87
+ ]
88
+
89
+ inputs = tokenizer.apply_chat_template(
90
+ messages,
91
+ add_generation_prompt=True,
92
+ return_tensors="pt",
93
+ ).to(model.device)
94
+
95
+ output = model.generate(
96
+ inputs,
97
+ max_new_tokens=1024,
98
+ do_sample=True,
99
+ temperature=0.7,
100
+ top_p=0.9,
101
+ )
102
+ print(tokenizer.decode(output[0][inputs.shape[-1]:], skip_special_tokens=True))
103
+ ```
104
+
105
+ ## Notes
106
+
107
+ - **Context length.** Use `max_seq_length` ≥ **6144** at inference time to match
108
+ the training regime; generations longer than this were not seen during training.
109
+ - **Intended use.** Research artifact for generating structured scientific research
110
+ plans. Not aligned for general-purpose chat or safety-critical use.
111
+ - **Compared to sibling.** A matching **without-thoughts** checkpoint at
112
+ [`Divij/Llama-3.2-3B-Instruct-sft-without-thoughts`](https://huggingface.co/Divij/Llama-3.2-3B-Instruct-sft-without-thoughts) is trained on
113
+ the same data but with the opposite treatment of reasoning traces.
chat_template.jinja ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {{- bos_token }}
2
+ {%- if custom_tools is defined %}
3
+ {%- set tools = custom_tools %}
4
+ {%- endif %}
5
+ {%- if not tools_in_user_message is defined %}
6
+ {%- set tools_in_user_message = true %}
7
+ {%- endif %}
8
+ {%- if not date_string is defined %}
9
+ {%- if strftime_now is defined %}
10
+ {%- set date_string = strftime_now("%d %b %Y") %}
11
+ {%- else %}
12
+ {%- set date_string = "26 Jul 2024" %}
13
+ {%- endif %}
14
+ {%- endif %}
15
+ {%- if not tools is defined %}
16
+ {%- set tools = none %}
17
+ {%- endif %}
18
+
19
+ {#- This block extracts the system message, so we can slot it into the right place. #}
20
+ {%- if messages[0]['role'] == 'system' %}
21
+ {%- set system_message = messages[0]['content']|trim %}
22
+ {%- set messages = messages[1:] %}
23
+ {%- else %}
24
+ {%- set system_message = "" %}
25
+ {%- endif %}
26
+
27
+ {#- System message #}
28
+ {{- "<|start_header_id|>system<|end_header_id|>\n\n" }}
29
+ {%- if tools is not none %}
30
+ {{- "Environment: ipython\n" }}
31
+ {%- endif %}
32
+ {{- "Cutting Knowledge Date: December 2023\n" }}
33
+ {{- "Today Date: " + date_string + "\n\n" }}
34
+ {%- if tools is not none and not tools_in_user_message %}
35
+ {{- "You have access to the following functions. To call a function, please respond with JSON for a function call." }}
36
+ {{- 'Respond in the format {"name": function name, "parameters": dictionary of argument name and its value}.' }}
37
+ {{- "Do not use variables.\n\n" }}
38
+ {%- for t in tools %}
39
+ {{- t | tojson(indent=4) }}
40
+ {{- "\n\n" }}
41
+ {%- endfor %}
42
+ {%- endif %}
43
+ {{- system_message }}
44
+ {{- "<|eot_id|>" }}
45
+
46
+ {#- Custom tools are passed in a user message with some extra guidance #}
47
+ {%- if tools_in_user_message and not tools is none %}
48
+ {#- Extract the first user message so we can plug it in here #}
49
+ {%- if messages | length != 0 %}
50
+ {%- set first_user_message = messages[0]['content']|trim %}
51
+ {%- set messages = messages[1:] %}
52
+ {%- else %}
53
+ {{- raise_exception("Cannot put tools in the first user message when there's no first user message!") }}
54
+ {%- endif %}
55
+ {{- '<|start_header_id|>user<|end_header_id|>\n\n' -}}
56
+ {{- "Given the following functions, please respond with a JSON for a function call " }}
57
+ {{- "with its proper arguments that best answers the given prompt.\n\n" }}
58
+ {{- 'Respond in the format {"name": function name, "parameters": dictionary of argument name and its value}.' }}
59
+ {{- "Do not use variables.\n\n" }}
60
+ {%- for t in tools %}
61
+ {{- t | tojson(indent=4) }}
62
+ {{- "\n\n" }}
63
+ {%- endfor %}
64
+ {{- first_user_message + "<|eot_id|>"}}
65
+ {%- endif %}
66
+
67
+ {%- for message in messages %}
68
+ {%- if not (message.role == 'ipython' or message.role == 'tool' or 'tool_calls' in message) %}
69
+ {{- '<|start_header_id|>' + message['role'] + '<|end_header_id|>\n\n'+ message['content'] | trim + '<|eot_id|>' }}
70
+ {%- elif 'tool_calls' in message %}
71
+ {%- if not message.tool_calls|length == 1 %}
72
+ {{- raise_exception("This model only supports single tool-calls at once!") }}
73
+ {%- endif %}
74
+ {%- set tool_call = message.tool_calls[0].function %}
75
+ {{- '<|start_header_id|>assistant<|end_header_id|>\n\n' -}}
76
+ {{- '{"name": "' + tool_call.name + '", ' }}
77
+ {{- '"parameters": ' }}
78
+ {{- tool_call.arguments | tojson }}
79
+ {{- "}" }}
80
+ {{- "<|eot_id|>" }}
81
+ {%- elif message.role == "tool" or message.role == "ipython" %}
82
+ {{- "<|start_header_id|>ipython<|end_header_id|>\n\n" }}
83
+ {%- if message.content is mapping or message.content is iterable %}
84
+ {{- message.content | tojson }}
85
+ {%- else %}
86
+ {{- message.content }}
87
+ {%- endif %}
88
+ {{- "<|eot_id|>" }}
89
+ {%- endif %}
90
+ {%- endfor %}
91
+ {%- if add_generation_prompt %}
92
+ {{- '<|start_header_id|>assistant<|end_header_id|>\n\n' }}
93
+ {%- endif %}
config.json ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "LlamaForCausalLM"
4
+ ],
5
+ "attention_bias": false,
6
+ "attention_dropout": 0.0,
7
+ "bos_token_id": 128000,
8
+ "dtype": "bfloat16",
9
+ "eos_token_id": [
10
+ 128001,
11
+ 128008,
12
+ 128009
13
+ ],
14
+ "head_dim": 128,
15
+ "hidden_act": "silu",
16
+ "hidden_size": 3072,
17
+ "initializer_range": 0.02,
18
+ "intermediate_size": 8192,
19
+ "max_position_embeddings": 131072,
20
+ "mlp_bias": false,
21
+ "model_type": "llama",
22
+ "num_attention_heads": 24,
23
+ "num_hidden_layers": 28,
24
+ "num_key_value_heads": 8,
25
+ "pad_token_id": null,
26
+ "pretraining_tp": 1,
27
+ "rms_norm_eps": 1e-05,
28
+ "rope_parameters": {
29
+ "factor": 32.0,
30
+ "high_freq_factor": 4.0,
31
+ "low_freq_factor": 1.0,
32
+ "original_max_position_embeddings": 8192,
33
+ "rope_theta": 500000.0,
34
+ "rope_type": "llama3"
35
+ },
36
+ "tie_word_embeddings": true,
37
+ "transformers_version": "5.5.3",
38
+ "use_cache": true,
39
+ "vocab_size": 128264
40
+ }
generation_config.json ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ {
2
+ "bos_token_id": 128000,
3
+ "eos_token_id": 128009,
4
+ "transformers_version": "5.5.3"
5
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f5da0f216b246eef847dedf88c3fafc55cb047f7d8f4118f9281a043c93a3f93
3
+ size 7213632392
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9400df98529060210393c40f08cb127f7c0df584338b3fbfdba8cf82a33c1ade
3
+ size 17210102
tokenizer_config.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "backend": "tokenizers",
3
+ "bos_token": "<|begin_of_text|>",
4
+ "clean_up_tokenization_spaces": true,
5
+ "eos_token": "<|eot_id|>",
6
+ "is_local": false,
7
+ "model_input_names": [
8
+ "input_ids",
9
+ "attention_mask"
10
+ ],
11
+ "model_max_length": 131072,
12
+ "pad_token": "<pad>",
13
+ "tokenizer_class": "TokenizersBackend"
14
+ }