commit f9331c90682a14f10e7527edd5fe22ae48629370 Author: ModelHub XC Date: Fri Sep 4 23:16:17 2026 +0800 初始化项目,由ModelHub XC社区提供模型 Model: saad1926q/qwen3-1.7b-15puzzle-sft-depth-8-15 Source: Original Platform diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..52373fe --- /dev/null +++ b/.gitattributes @@ -0,0 +1,36 @@ +*.7z filter=lfs diff=lfs merge=lfs -text +*.arrow filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.ckpt filter=lfs diff=lfs merge=lfs -text +*.ftz filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.h5 filter=lfs diff=lfs merge=lfs -text +*.joblib filter=lfs diff=lfs merge=lfs -text +*.lfs.* filter=lfs diff=lfs merge=lfs -text +*.mlmodel filter=lfs diff=lfs merge=lfs -text +*.model filter=lfs diff=lfs merge=lfs -text +*.msgpack filter=lfs diff=lfs merge=lfs -text +*.npy filter=lfs diff=lfs merge=lfs -text +*.npz filter=lfs diff=lfs merge=lfs -text +*.onnx filter=lfs diff=lfs merge=lfs -text +*.ot filter=lfs diff=lfs merge=lfs -text +*.parquet filter=lfs diff=lfs merge=lfs -text +*.pb filter=lfs diff=lfs merge=lfs -text +*.pickle filter=lfs diff=lfs merge=lfs -text +*.pkl filter=lfs diff=lfs merge=lfs -text +*.pt filter=lfs diff=lfs merge=lfs -text +*.pth filter=lfs diff=lfs merge=lfs -text +*.rar filter=lfs diff=lfs merge=lfs -text +*.safetensors filter=lfs diff=lfs merge=lfs -text +saved_model/**/* filter=lfs diff=lfs merge=lfs -text +*.tar.* filter=lfs diff=lfs merge=lfs -text +*.tar filter=lfs diff=lfs merge=lfs -text +*.tflite filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.wasm filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text +*tfevents* filter=lfs diff=lfs merge=lfs -text +tokenizer.json filter=lfs diff=lfs merge=lfs -text diff --git a/README.md b/README.md new file mode 100644 index 0000000..d529119 --- /dev/null +++ b/README.md @@ -0,0 +1,170 @@ +--- +license: apache-2.0 +base_model: PrimeIntellect/Qwen3-1.7B +tags: + - qwen3 + - 15-puzzle + - sft + - reasoning + - puzzle-solving +datasets: + - saad1926q/15-puzzle +--- + +# Qwen3 1.7B 15-Puzzle SFT + +This is a supervised fine-tuned checkpoint of `PrimeIntellect/Qwen3-1.7B` for 15-puzzle move prediction and reasoning-format alignment. + +The model was fine-tuned on solved 15-puzzle trajectories from [`saad1926q/15-puzzle`](https://huggingface.co/datasets/saad1926q/15-puzzle), using depth 8–15 puzzles. + +Each training example contains: + +- A board state +- A solver-verified optimal move sequence +- Short per-move rationales + +## Training Data + +**Dataset split** + +- **Dataset:** `saad1926q/15-puzzle` +- **Config/subset:** `sft` +- **Split:** `sft` +- **Rows:** 600 +- **Scramble depths:** 8–15 +- **Base trajectories:** Solver-verified optimal paths +- **Rationale source:** DeepSeek-generated rationales with tile-move convention + +### Move Convention + +Moves describe the **numbered tile** moving into the blank, **not** the blank moving. + +For example, if the board is: + +```text +13 _ 14 15 +``` + +then + +```xml +left +``` + +means tile **14** moves left into the blank, producing: + +```text +13 14 _ 15 +``` + +## Intended Use + +This checkpoint is primarily intended as an SFT initialization for later RL training on the 15-puzzle. + +The goal of SFT is to teach: + +- Task format +- The `...` and `...` response structure +- Legal move semantics +- Basic trajectory-following behavior + +It should **not** be treated as a fully capable 15-puzzle solver, especially on deeper scrambles. + +## Response Format + +The model is trained to respond with: + +```xml + +short rationale + +left +``` + +Allowed moves are: + +- `up` +- `down` +- `left` +- `right` + +## Training + +**Base model** + +- `PrimeIntellect/Qwen3-1.7B` + +**Fine-tuning framework** + +- PrimeIntellect Prime-RL SFT + +**Training setup** + +- Full-parameter SFT +- 600 examples +- 40 training steps +- 3 epochs +- Sequence length: 3072 +- Learning rate: `1e-5` +- Final loss: approximately **0.47** + +## Loading + +```python +from transformers import AutoModelForCausalLM, AutoTokenizer + +model_id = "saad1926q/qwen3-1.7b-15puzzle-sft-depth-8-15" + +tokenizer = AutoTokenizer.from_pretrained(model_id) +model = AutoModelForCausalLM.from_pretrained( + model_id, + device_map="auto", +) +``` + +## Example Prompt + +```text +You are Player 0 in 15-puzzle. + +A 4x4 sliding puzzle board is given. The blank tile is shown as _. + +Your goal is to reach the solved board: + +1 2 3 4 +5 6 7 8 +9 10 11 12 +13 14 15 _ + +At each turn, choose one legal move. + +Moves describe the numbered tile moving into the blank, not the blank moving. + +Allowed moves are: +up, down, left, right. + +Wrap your move in .... + +Current board: + +1 2 3 4 +5 6 7 8 +9 10 11 _ +13 14 15 12 +``` + +Expected style: + +```xml + +Move tile 12 up into the blank to place it in its correct final position. + +up +``` + +## Limitations + +- This is an SFT checkpoint, not an RL-trained solver. +- The model may still make illegal or suboptimal moves. +- The training set is small and focused on scramble depths 8–15. +- The rationales are intended to teach format and move semantics, not guarantee perfect search behavior. \ No newline at end of file diff --git a/STABLE b/STABLE new file mode 100644 index 0000000..e69de29 diff --git a/chat_template.jinja b/chat_template.jinja new file mode 100644 index 0000000..be5ffea --- /dev/null +++ b/chat_template.jinja @@ -0,0 +1,130 @@ +{% macro render_extra_keys(json_dict, handled_keys) %} + {%- if json_dict is mapping %} + {%- for json_key in json_dict if json_key not in handled_keys %} + {%- if json_dict[json_key] is mapping or (json_dict[json_key] is sequence and json_dict[json_key] is not string) %} + {{- '\n<' ~ json_key ~ '>' ~ (json_dict[json_key] | tojson | safe) ~ '' }} + {%- else %} + {{-'\n<' ~ json_key ~ '>' ~ (json_dict[json_key] | string) ~ '' }} + {%- endif %} + {%- endfor %} + {%- endif %} +{% endmacro %} + +{%- if messages[0]["role"] == "system" %} + {%- set system_message = messages[0]["content"] %} + {%- set loop_messages = messages[1:] %} +{%- else %} + {%- set loop_messages = messages %} +{%- endif %} + +{%- if not tools is defined %} + {%- set tools = [] %} +{%- endif %} + +{%- if system_message is defined %} + {{- "<|im_start|>system\n" + system_message }} +{%- else %} + {%- if tools is iterable and tools | length > 0 %} + {{- "<|im_start|>system\nYou are Qwen, a helpful AI assistant that can interact with a computer to solve tasks." }} + {%- endif %} +{%- endif %} +{%- if tools is iterable and tools | length > 0 %} + {{- "\n\n# Tools\n\nYou have access to the following functions:\n\n" }} + {{- "" }} + {%- for tool in tools %} + {%- if tool.function is defined %} + {%- set tool = tool.function %} + {%- endif %} + {{- "\n\n" ~ tool.name ~ "" }} + {%- if tool.description is defined %} + {{- '\n' ~ (tool.description | trim) ~ '' }} + {%- endif %} + {{- '\n' }} + {%- if tool.parameters is defined and tool.parameters is mapping and tool.parameters.properties is defined and tool.parameters.properties is mapping %} + {%- for param_name, param_fields in tool.parameters.properties|items %} + {{- '\n' }} + {{- '\n' ~ param_name ~ '' }} + {%- if param_fields.type is defined %} + {{- '\n' ~ (param_fields.type | string) ~ '' }} + {%- endif %} + {%- if param_fields.description is defined %} + {{- '\n' ~ (param_fields.description | trim) ~ '' }} + {%- endif %} + {%- set handled_keys = ['name', 'type', 'description'] %} + {{- render_extra_keys(param_fields, handled_keys) }} + {{- '\n' }} + {%- endfor %} + {%- endif %} + {% set handled_keys = ['type', 'properties'] %} + {{- render_extra_keys(tool.parameters, handled_keys) }} + {{- '\n' }} + {%- set handled_keys = ['type', 'name', 'description', 'parameters'] %} + {{- render_extra_keys(tool, handled_keys) }} + {{- '\n' }} + {%- endfor %} + {{- "\n" }} + {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n\n\n\nvalue_1\n\n\nThis is the value for the second parameter\nthat can span\nmultiple lines\n\n\n\n\n\nReminder:\n- Function calls MUST follow the specified format: an inner block must be nested within XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n' }} +{%- endif %} +{%- if system_message is defined %} + {{- '<|im_end|>\n' }} +{%- else %} + {%- if tools is iterable and tools | length > 0 %} + {{- '<|im_end|>\n' }} + {%- endif %} +{%- endif %} +{%- for message in loop_messages %} + {%- if message.role == "assistant" and message.tool_calls is defined and message.tool_calls is iterable and message.tool_calls | length > 0 %} + {{- '<|im_start|>' + message.role }} + {%- if message.content is defined and message.content is string and message.content | trim | length > 0 %} + {{- '\n' + message.content | trim + '\n' }} + {%- endif %} + {%- for tool_call in message.tool_calls %} + {%- if tool_call.function is defined %} + {%- set tool_call = tool_call.function %} + {%- endif %} + {{- '\n\n\n' }} + {%- if tool_call.arguments is defined %} + {%- for args_name, args_value in tool_call.arguments|items %} + {{- '\n' }} + {%- set args_value = args_value | tojson | safe if args_value is mapping or (args_value is sequence and args_value is not string) else args_value | string %} + {{- args_value }} + {{- '\n\n' }} + {%- endfor %} + {%- endif %} + {{- '\n' }} + {%- endfor %} + {{- '<|im_end|>\n' }} + {%- elif message.role == "user" or message.role == "system" or message.role == "assistant" %} + {{- '<|im_start|>' + message.role }} + {%- if message.role == "assistant" and message.reasoning_content is defined %} + {%- if message.reasoning_content -%} + {{ '\n' + message.reasoning_content.strip() + '' }} + {%- else -%} + {{ '\n' }} + {%- endif -%} + {%- if message.content.strip() -%} + {{ '\n' + message.content.strip() }} + {%- endif -%} + {%- else %} + {{- '\n' + message.content }} + {%- endif %} + {{- '<|im_end|>' + '\n' }} + {%- elif message.role == "tool" %} + {%- if loop.previtem and loop.previtem.role != "tool" %} + {{- '<|im_start|>user\n' }} + {%- endif %} + {{- '\n' }} + {{- message.content }} + {{- '\n\n' }} + {%- if not loop.last and loop.nextitem.role != "tool" %} + {{- '<|im_end|>\n' }} + {%- elif loop.last %} + {{- '<|im_end|>\n' }} + {%- endif %} + {%- else %} + {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>\n' }} + {%- endif %} +{%- endfor %} +{%- if add_generation_prompt %} + {{- '<|im_start|>assistant\n' }} +{%- endif %} \ No newline at end of file diff --git a/config.json b/config.json new file mode 100644 index 0000000..793f3cd --- /dev/null +++ b/config.json @@ -0,0 +1,65 @@ +{ + "architectures": [ + "Qwen3ForCausalLM" + ], + "attention_bias": false, + "attention_dropout": 0.0, + "bos_token_id": 151643, + "dtype": "bfloat16", + "eos_token_id": 151645, + "fp8": false, + "head_dim": 128, + "hidden_act": "silu", + "hidden_size": 2048, + "initializer_range": 0.02, + "intermediate_size": 6144, + "layer_types": [ + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention" + ], + "max_position_embeddings": 40960, + "max_window_layers": 28, + "model_type": "qwen3", + "num_attention_heads": 16, + "num_hidden_layers": 28, + "num_key_value_heads": 8, + "pad_token_id": 151645, + "rms_norm_eps": 1e-06, + "rope_parameters": { + "rope_theta": 1000000, + "rope_type": "default" + }, + "sliding_window": null, + "tie_word_embeddings": true, + "transformers_version": "5.6.2", + "use_cache": false, + "use_grouped_mm": true, + "use_sliding_window": false, + "vocab_size": 151936 +} diff --git a/generation_config.json b/generation_config.json new file mode 100644 index 0000000..76ef482 --- /dev/null +++ b/generation_config.json @@ -0,0 +1,10 @@ +{ + "_from_model_config": true, + "bos_token_id": 151643, + "eos_token_id": 151645, + "output_attentions": false, + "output_hidden_states": false, + "pad_token_id": 151645, + "transformers_version": "5.6.2", + "use_cache": true +} diff --git a/model.safetensors b/model.safetensors new file mode 100644 index 0000000..7c15ec9 --- /dev/null +++ b/model.safetensors @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:25c47f7804e46200485128cdd45a7e501b34bb00099fb438dbd98bc77e596b23 +size 3441185608 diff --git a/tokenizer.json b/tokenizer.json new file mode 100644 index 0000000..c7afbed --- /dev/null +++ b/tokenizer.json @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be75606093db2094d7cd20f3c2f385c212750648bd6ea4fb2bf507a6a4c55506 +size 11422650 diff --git a/tokenizer_config.json b/tokenizer_config.json new file mode 100644 index 0000000..5e1a57d --- /dev/null +++ b/tokenizer_config.json @@ -0,0 +1,30 @@ +{ + "add_prefix_space": false, + "backend": "tokenizers", + "bos_token": null, + "clean_up_tokenization_spaces": false, + "eos_token": "<|im_end|>", + "errors": "replace", + "extra_special_tokens": [ + "<|im_start|>", + "<|im_end|>", + "<|object_ref_start|>", + "<|object_ref_end|>", + "<|box_start|>", + "<|box_end|>", + "<|quad_start|>", + "<|quad_end|>", + "<|vision_start|>", + "<|vision_end|>", + "<|vision_pad|>", + "<|image_pad|>", + "<|video_pad|>" + ], + "is_local": false, + "local_files_only": false, + "model_max_length": 131072, + "pad_token": "<|im_end|>", + "split_special_tokens": false, + "tokenizer_class": "Qwen2Tokenizer", + "unk_token": null +}