diff --git a/.gitattributes b/.gitattributes index a6344aac8c09253b3b630fb776ae94478aa0275b..a6edf747f20dcecfc5015924ddeaf9b8b843fe68 100644 --- a/.gitattributes +++ b/.gitattributes @@ -33,3 +33,5 @@ saved_model/**/* 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 +unmerged/tokenizer.json filter=lfs diff=lfs merge=lfs -text diff --git a/COMPLETE.json b/COMPLETE.json new file mode 100644 index 0000000000000000000000000000000000000000..2d4deed450491b0badfb73f212511d81baed3de3 --- /dev/null +++ b/COMPLETE.json @@ -0,0 +1,6 @@ +{ + "model": "Valen-4B", + "validated": true, + "files": 21, + "source_checkpoint_sha256": "b4193b4e907f44b913fd54a8d6b998e7050a1528306269a000f1e5e8bd8dffc7" +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..f938136e3adacfd92be087f6e113b5d6d97f678f --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 Alibaba Cloud + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/MODEL_USAGE.md b/MODEL_USAGE.md new file mode 100644 index 0000000000000000000000000000000000000000..f629d9c1519c5eeea68c7c50fbf3569101db6186 --- /dev/null +++ b/MODEL_USAGE.md @@ -0,0 +1,49 @@ +# Valen-4B + +完整合并的 Qwen3.5 + 两层 Mixer,提供 Choice、Noul、Score 决策和 share_state 多题推理。 +Complete Qwen3.5 backbone with merged LoRA, trained visual merger, and the FP32 Mixer head. + +训练版本:1195k + JevBench 30k,两阶段 SFT,最终 step 325。 +全体基座参数、训练参数、分词器及输入编译代码均在本目录。 + +## 加载 / Load + +验证环境:Python 3.10、PyTorch 2.6.0、Transformers 5.4.0、torchvision 0.21.0、Pillow、av 16.1.0。 +使用 Flash Attention 2 时,另需与 PyTorch/CUDA 匹配的 flash-attn。 + +```python +import torch +from transformers import AutoModel + +model = AutoModel.from_pretrained( + "./Valen-4B", + trust_remote_code=True, + dtype=torch.bfloat16, + attn_implementation="sdpa", # 或 flash_attention_2 / or flash_attention_2 +).to("cuda").eval() +# 和导出一致性验证保持相同的 FP32 精度。 / Match export verification precision. +torch.set_float32_matmul_precision("highest") +torch.backends.cudnn.allow_tf32 = False + +response = model.predict({ + "state": "There is one cat in the room.", + "questions": { + "animal": {"type": "choice", "instructions": "Which animal is present?", + "criteria": {"cat": "A cat", "dog": "A dog"}}, + "is_cat": {"type": "noul", "instructions": "There is a cat in the room."}, + "count": {"type": "score", "instructions": "How many cats are present?", + "criteria": ["No cats", "Exactly one cat", "Two or more cats"]}, + }, +}) +print(response["answers"]) +``` + +图像/视频使用 Valen 的 messages、image_url、video_url 输入格式,媒体路径由 `media_root` 解析。 +默认 `execution="shared_state"`;`model.predict(..., execution="question")` 可使用独立问题路径。 +视频沿用训练配置,采样 16 帧。所有 Mixer 参数保持 FP32,基座权重为 BF16。 + +`validation.json` 记录合并前后概率差异、重新加载一致性、文本/图像/视频及三类题型检查。 +`export_manifest.json` 记录来源 checkpoint、基座版本及文件 SHA-256。 +LoRA 以 FP32 累加后保存为 BF16;融合矩阵的舍入顺序与独立 LoRA 分支不同。 +验证样本中最大概率绝对差:0.01969546;预测标签变化:0 / 20。 +该检查只验证导出样本,不能代替完整 benchmark;之前 checkpoint 的成绩属于未融合版本。 diff --git a/README.md b/README.md index 154df8298fab5ecf322016157858e08cd1bccbe1..359f89d8a67a52bf3aabb61f9844bf887852cf90 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,106 @@ --- license: apache-2.0 +base_model: Qwen/Qwen3.5-4B +library_name: transformers +tags: +- valen +- decision-making +- shared-state +- qwen3.5 +- custom-code --- + +# Valen-4B + +Valen-4B combines Qwen3.5-4B with a two-layer MLP-Mixer decision head. It predicts probability distributions for Choice, Noul (yes/no), and Score questions. A shared state can contain text, images, or video and serve multiple questions. + +Valen-4B 基于 Qwen3.5-4B 和两层 MLP-Mixer 决策头,支持图文、文本、视频,以及共享 state 的多题推理。 + +## Training / 训练 + +- Two-stage SFT: decision-head warmup followed by joint LoRA, Mixer, and visual-merger fine-tuning. +- Training data: the previous 1,195,000 records plus JevBench train_v2 30,000 records, totaling 1,225,000 records. This count refers to records; shared-state records may contain multiple questions. +- Warmup: 122,500 records, 67 optimizer steps. Joint SFT: one epoch over all 1,225,000 records, 325 optimizer steps, on 32 H200 GPUs. +- Final checkpoint: joint SFT step 325. This release uses SFT training. +- Backbone: BF16. Mixer: FP32. Videos use 16 sampled frames. + +## Files / 权重格式 + +- Root directory: complete backbone with merged LoRA, trained visual merger, FP32 Mixer, tokenizer, processor, and standalone loading code. +- `unmerged/`: separate PEFT LoRA, Mixer, and trained visual-merger weights, with its own configuration and loading code. Requires the pinned original Qwen3.5-4B base. +- `MODEL_USAGE.md`: inference examples and environment details. +- `validation.json`, `fresh_process_validation.json`: export checks covering text, images, video, Choice/Noul/Score, question/shared_state, and isolated Python loading. +- `export_manifest.json`: source revision and file checksums. + +## Load merged weights / 加载完整合并权重 + +The verified environment uses Python 3.10, PyTorch 2.6.0, Transformers 5.4.0, torchvision 0.21.0, Pillow, and av 16.1.0. Flash Attention 2 requires a compatible flash-attn installation. Private repositories require an account with access. + +```python +import torch +from transformers import AutoModel + +model = AutoModel.from_pretrained( + "Valen-Team/Valen-4B", + trust_remote_code=True, + dtype=torch.bfloat16, + attn_implementation="sdpa", # or "flash_attention_2" +).to("cuda").eval() +torch.set_float32_matmul_precision("highest") +torch.backends.cudnn.allow_tf32 = False + +response = model.predict({ + "state": "There is one cat in the room.", + "questions": { + "animal": {"type": "choice", "instructions": "Which animal is present?", + "criteria": {"cat": "A cat", "dog": "A dog"}}, + "is_cat": {"type": "noul", "instructions": "There is a cat in the room."}, + }, +}, execution="shared_state") +print(response["answers"]) +``` + +For a local copy, replace the repository ID with `"./Valen-4B"`. +`execution="question"` scores questions separately. Images and video use the Valen `messages`, `image_url`, and `video_url` schema; relative media paths are resolved against `media_root`. + +## Load unmerged LoRA / 加载未合并权重 + +Download the repository first; the adapter loader expects a local directory. PEFT 0.18.1 and safetensors are also required. + +```python +import torch +from huggingface_hub import snapshot_download +from transformers import AutoModel + +folder = snapshot_download("Valen-Team/Valen-4B") +model = AutoModel.from_pretrained( + folder + "/unmerged", + trust_remote_code=True, + local_files_only=False, # download the pinned Qwen base if needed + dtype=torch.bfloat16, + attn_implementation="sdpa", +).to("cuda").eval() +torch.set_float32_matmul_precision("highest") +torch.backends.cudnn.allow_tf32 = False +``` + +For an existing local base, pass `base_model_path="./Qwen3.5-4B"` and `local_files_only=True`. The loader verifies its original weight hashes and restores LoRA, Mixer, and visual-merger weights together. `is_trainable=True` enables training those parameters. + +## Reference benchmark results / 参考评测 + +Measured on the original final **unmerged** SFT checkpoint, using shared-state inference for multimodal sets and single-question inference for JevBench: + +| Benchmark | QA | Accuracy | Choice | Noul | Score | +| --- | --- | --- | --- | --- | --- | +| eval_v1 | 2,000 | 83.06% | 85.42% | 83.25% | 54.00% | +| General | 10,000 | 88.68% | 90.68% | 85.76% | 75.60% | +| Video | 7,143 | 87.36% | 90.80% | 93.14% | 72.43% | +| JevBench | 231 | 83.12% | 84.89% | 81.08% | 77.78% | + +JevBench difficulty scores: Easy 100.00% (48/48), Standard 93.06% (67/72), Hard 69.37% (77/111). The overall score is weighted by task count: 192/231. + +The export smoke cases showed a maximum absolute probability difference of 0.01969546 between merged and unmerged inference, with no label changes in those cases. This does not establish full-benchmark equivalence. + +For eval_v1, accuracy uses 1,700 hard-label questions. Its remaining 300 soft-label Score questions contribute probability metrics and are excluded from hard-label accuracy. + +Merged BF16 matrices and separate LoRA branches can produce numerical differences. Export validation records those differences; the merged release has not been independently rerun on the complete benchmarks. The unmerged bundle preserves the original trained tensors and passed reloading checks. diff --git a/batching.py b/batching.py new file mode 100644 index 0000000000000000000000000000000000000000..6bd343e1d7a8479c6bbc45d73b987b1d1d2d5c28 --- /dev/null +++ b/batching.py @@ -0,0 +1,62 @@ +"""Pad language rows and concatenate visual patches. / 文本补齐,视觉 patch 拼接。""" +import torch +from torch.nn.utils.rnn import pad_sequence + + +SEQUENCE_KEYS = {"input_ids", "attention_mask", "mm_token_type_ids"} +VISUAL_KEYS = {"pixel_values", "pixel_values_videos", "image_grid_thw", "video_grid_thw"} + + +def collate_branches(branches, pad_token_id=0): + if not branches: + raise ValueError("Cannot collate an empty branch batch") + inputs = [branch.inputs for branch in branches] + unknown = set().union(*(row.keys() for row in inputs)) - SEQUENCE_KEYS - VISUAL_KEYS + if unknown: + raise ValueError(f"Unsupported batched Qwen inputs: {sorted(unknown)}") + if any(row["input_ids"].ndim != 2 or row["input_ids"].shape[0] != 1 for row in inputs): + raise ValueError("Each compiled branch must contain one language row") + result = {} + for key in SEQUENCE_KEYS: + if key != "input_ids" and not any(key in row for row in inputs): + continue + rows = [] + for row in inputs: + value = row.get(key) + if value is None: + value = (torch.ones_like(row["input_ids"]) if key == "attention_mask" + else torch.zeros_like(row["input_ids"])) + if value.shape != row["input_ids"].shape: + raise ValueError(f"{key} must match the branch input_ids shape") + rows.append(value[0]) + # Right padding keeps all compiler readout positions and spans unchanged. + # 右侧补齐,候选位置和角色区间无需偏移。 + result[key] = pad_sequence(rows, batch_first=True, + padding_value=pad_token_id if key == "input_ids" else 0) + if "attention_mask" not in result: + result["attention_mask"] = pad_sequence([torch.ones_like(r["input_ids"][0]) for r in inputs], + batch_first=True, padding_value=0) + for key in VISUAL_KEYS: + values = [row[key] for row in inputs if key in row] + if values: + result[key] = torch.cat(values, dim=0) + return result + + +def branch_batches(questions, max_tokens): + """Limit padded tokens per backbone forward, keeping Score branch order.""" + if type(max_tokens) is not int or max_tokens <= 0: + raise ValueError("microbatch_max_tokens must be a positive integer") + batch, longest = [], 0 + for question_index, question in enumerate(questions): + if not question.branches: + raise ValueError("A Qwen question requires at least one branch") + for branch in question.branches: + length = branch.inputs["input_ids"].shape[1] + if batch and max(longest, length) * (len(batch) + 1) > max_tokens: + yield batch + batch, longest = [], 0 + batch.append((question_index, branch)) + longest = max(longest, length) + if batch: + yield batch diff --git a/chat_template.jinja b/chat_template.jinja new file mode 100644 index 0000000000000000000000000000000000000000..a585dec894e63da457d9440ec6aa7caa16d20860 --- /dev/null +++ b/chat_template.jinja @@ -0,0 +1,154 @@ +{%- set image_count = namespace(value=0) %} +{%- set video_count = namespace(value=0) %} +{%- macro render_content(content, do_vision_count, is_system_content=false) %} + {%- if content is string %} + {{- content }} + {%- elif content is iterable and content is not mapping %} + {%- for item in content %} + {%- if 'image' in item or 'image_url' in item or item.type == 'image' %} + {%- if is_system_content %} + {{- raise_exception('System message cannot contain images.') }} + {%- endif %} + {%- if do_vision_count %} + {%- set image_count.value = image_count.value + 1 %} + {%- endif %} + {%- if add_vision_id %} + {{- 'Picture ' ~ image_count.value ~ ': ' }} + {%- endif %} + {{- '<|vision_start|><|image_pad|><|vision_end|>' }} + {%- elif 'video' in item or item.type == 'video' %} + {%- if is_system_content %} + {{- raise_exception('System message cannot contain videos.') }} + {%- endif %} + {%- if do_vision_count %} + {%- set video_count.value = video_count.value + 1 %} + {%- endif %} + {%- if add_vision_id %} + {{- 'Video ' ~ video_count.value ~ ': ' }} + {%- endif %} + {{- '<|vision_start|><|video_pad|><|vision_end|>' }} + {%- elif 'text' in item %} + {{- item.text }} + {%- else %} + {{- raise_exception('Unexpected item type in content.') }} + {%- endif %} + {%- endfor %} + {%- elif content is none or content is undefined %} + {{- '' }} + {%- else %} + {{- raise_exception('Unexpected content type.') }} + {%- endif %} +{%- endmacro %} +{%- if not messages %} + {{- raise_exception('No messages provided.') }} +{%- endif %} +{%- if tools and tools is iterable and tools is not mapping %} + {{- '<|im_start|>system\n' }} + {{- "# Tools\n\nYou have access to the following functions:\n\n" }} + {%- for tool in tools %} + {{- "\n" }} + {{- tool | tojson }} + {%- 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' }} + {%- if messages[0].role == 'system' %} + {%- set content = render_content(messages[0].content, false, true)|trim %} + {%- if content %} + {{- '\n\n' + content }} + {%- endif %} + {%- endif %} + {{- '<|im_end|>\n' }} +{%- else %} + {%- if messages[0].role == 'system' %} + {%- set content = render_content(messages[0].content, false, true)|trim %} + {{- '<|im_start|>system\n' + content + '<|im_end|>\n' }} + {%- endif %} +{%- endif %} +{%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %} +{%- for message in messages[::-1] %} + {%- set index = (messages|length - 1) - loop.index0 %} + {%- if ns.multi_step_tool and message.role == "user" %} + {%- set content = render_content(message.content, false)|trim %} + {%- if not(content.startswith('') and content.endswith('')) %} + {%- set ns.multi_step_tool = false %} + {%- set ns.last_query_index = index %} + {%- endif %} + {%- endif %} +{%- endfor %} +{%- if ns.multi_step_tool %} + {{- raise_exception('No user query found in messages.') }} +{%- endif %} +{%- for message in messages %} + {%- set content = render_content(message.content, true)|trim %} + {%- if message.role == "system" %} + {%- if not loop.first %} + {{- raise_exception('System message must be at the beginning.') }} + {%- endif %} + {%- elif message.role == "user" %} + {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }} + {%- elif message.role == "assistant" %} + {%- set reasoning_content = '' %} + {%- if message.reasoning_content is string %} + {%- set reasoning_content = message.reasoning_content %} + {%- else %} + {%- if '' in content %} + {%- set reasoning_content = content.split('')[0].rstrip('\n').split('')[-1].lstrip('\n') %} + {%- set content = content.split('')[-1].lstrip('\n') %} + {%- endif %} + {%- endif %} + {%- set reasoning_content = reasoning_content|trim %} + {%- if loop.index0 > ns.last_query_index %} + {{- '<|im_start|>' + message.role + '\n\n' + reasoning_content + '\n\n\n' + content }} + {%- else %} + {{- '<|im_start|>' + message.role + '\n' + content }} + {%- endif %} + {%- if message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %} + {%- for tool_call in message.tool_calls %} + {%- if tool_call.function is defined %} + {%- set tool_call = tool_call.function %} + {%- endif %} + {%- if loop.first %} + {%- if content|trim %} + {{- '\n\n\n\n' }} + {%- else %} + {{- '\n\n' }} + {%- endif %} + {%- else %} + {{- '\n\n\n' }} + {%- endif %} + {%- 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 %} + {%- endif %} + {{- '<|im_end|>\n' }} + {%- elif message.role == "tool" %} + {%- if loop.previtem and loop.previtem.role != "tool" %} + {{- '<|im_start|>user' }} + {%- endif %} + {{- '\n\n' }} + {{- content }} + {{- '\n' }} + {%- if not loop.last and loop.nextitem.role != "tool" %} + {{- '<|im_end|>\n' }} + {%- elif loop.last %} + {{- '<|im_end|>\n' }} + {%- endif %} + {%- else %} + {{- raise_exception('Unexpected message role.') }} + {%- endif %} +{%- endfor %} +{%- if add_generation_prompt %} + {{- '<|im_start|>assistant\n' }} + {%- if enable_thinking is defined and enable_thinking is false %} + {{- '\n\n\n\n' }} + {%- else %} + {{- '\n' }} + {%- endif %} +{%- endif %} \ No newline at end of file diff --git a/compiler.py b/compiler.py new file mode 100644 index 0000000000000000000000000000000000000000..a5b9fe08e2cc9cd8564d6325211bf10ebf789089 --- /dev/null +++ b/compiler.py @@ -0,0 +1,239 @@ +"""Compile Qwen question branches or a shared sequence with per-question readouts.""" +from copy import deepcopy +from dataclasses import dataclass +from pathlib import Path +import hashlib +import torch +from .schema import candidates, target_distribution +from .data_types import QuestionSpec + + +@dataclass +class Branch: + inputs: dict + candidate_positions: list + decision_position: int + context_span: tuple | None = None + instruction_span: tuple | None = None + candidate_spans: list | None = None + + +@dataclass(init=False) +class Question(QuestionSpec): + branches: list + + def __init__(self, qid, kind, keys, descriptions, branches, target, is_text): + # Keep the positional constructor used by existing compiler clients. + super().__init__(qid, kind, keys, descriptions, target, is_text) + self.branches = branches + + +@dataclass +class CompiledState: + questions: list + logical_tokens: int + compute_tokens: int + media: list + inputs: dict | None = None + + +class Compiler: + def __init__(self, processor, media_root=".", max_length=8192, media_kwargs=None, verified_media_hashes=None, + execution="question"): + if execution not in {"question", "shared_state"}: + raise ValueError(f"Unknown qwen_execution: {execution}") + self.execution = execution + self.processor = processor + self.tokenizer = processor.tokenizer + self.media_root = Path(media_root) + self.max_length = max_length + self.media_kwargs = media_kwargs or {} + # Optional, pre-audited immutable assets for latency measurements. + # Normal training/inference continues to hash each input at use time. + self.verified_media_hashes = verified_media_hashes or {} + + def _messages(self, state): + messages = [{"role": "user", "content": state}] if isinstance(state, str) else deepcopy(state["messages"]) + media = [] + for message in messages: + if message["role"] not in {"user", "assistant", "system"}: + raise ValueError("Unsupported state role") + if isinstance(message["content"], str): + message["content"] = [{"type": "text", "text": message["content"]}] + for item in message["content"]: + kind = item["type"] + if kind == "text": + # Prevent user text from injecting Qwen control tokens. + if any(t in item["text"] for t in self.tokenizer.all_special_tokens): + raise ValueError("Reserved tokenizer control token in state") + continue + if kind not in {"image_url", "video_url"}: + raise ValueError(f"Unsupported content type: {kind}") + url = item[kind]["url"] + if "://" in url: + raise ValueError("Materialize remote media locally with a hash before training") + path = Path(url) + path = path if path.is_absolute() else self.media_root / path + path = path.resolve(strict=True) + digest = self.verified_media_hashes.get(str(path)) + if digest is None: + digest = hashlib.sha256(path.read_bytes()).hexdigest() + media.append({"path": str(path), "sha256": digest, "type": kind}) + item.clear() + item.update(type=kind.removesuffix("_url"), path=str(path)) + return messages, media + + def compile(self, record, rng=None, labeled_only=False): + selected = [] + for qid, question in record["request"]["questions"].items(): + pairs = candidates(question) + target = record.get("targets", {}).get(qid) + if labeled_only and self.execution == "question" and target_distribution(target, [k for k, _ in pairs]) is None: + continue + if rng is not None and question["type"] == "choice": + rng.shuffle(pairs) + selected.append((qid, question, pairs, target)) + # 标签只决定监督范围,共享序列仍保留所有题。 / Labels select losses, never prompt content. + if not selected or (labeled_only and not any( + target_distribution(target, [k for k, _ in pairs]) is not None + for _, _, pairs, target in selected)): + return CompiledState([], 0, 0, []) + messages, media = self._messages(record["request"]["state"]) + expected_assets = {str((self.media_root / a["path"]).resolve()): a["sha256"] for a in record.get("assets", [])} + for entry in media: + if entry["path"] in expected_assets and expected_assets[entry["path"]] != entry["sha256"]: + raise ValueError(f"Media hash mismatch: {entry['path']}") + base = dict(self.processor.apply_chat_template( + messages, tokenize=True, add_generation_prompt=False, return_dict=True, + return_tensors="pt", processor_kwargs=dict(self.media_kwargs, return_metadata=True))) + # Metadata is audit information, never a backbone keyword argument. + metadata = base.pop("video_metadata", None) + if metadata is not None: + for entry, meta in zip([m for m in media if m["type"] == "video_url"], metadata): + entry["sampling"] = dict(meta) if isinstance(meta, dict) else vars(meta) + sampling = entry["sampling"] + indices = sampling.get("frames_indices") + if indices is not None and sampling.get("fps"): + sampling["frames_indices"] = [int(i) for i in indices] + sampling["timestamps_seconds"] = [int(i) / sampling["fps"] for i in indices] + sampling["visible_range_seconds"] = [min(sampling["timestamps_seconds"]), max(sampling["timestamps_seconds"])] + for name in ("image_grid_thw", "video_grid_thw"): + if name in base: + grid = base[name] + media.append({name: grid.tolist(), "visual_tokens": int(grid.prod(-1).sum()) // 4}) + base_length = base["input_ids"].shape[1] + if self.execution == "shared_state": + return self._compile_shared(selected, base, media, labeled_only) + logical_tokens, compute_tokens = base_length, 0 + compiled = [] + for qid, question, pairs, target in selected: + keys = [k for k, _ in pairs] + branches = [] + groups = [[pair] for pair in pairs] if question["type"] == "score" else [pairs] + for group in groups: + suffix = [] + def append(text, char_span=None): + start = base_length + len(suffix) + if char_span is None: + suffix.extend(self.tokenizer.encode(text, add_special_tokens=False)) + return None + # 保持原有分词,只额外记录区间。 / Preserve token IDs; record role spans. + encoded = self.tokenizer(text, add_special_tokens=False, return_offsets_mapping=True) + suffix.extend(encoded["input_ids"]) + indices = [i for i, (a, b) in enumerate(encoded["offset_mapping"]) + if a < char_span[1] and b > char_span[0]] + if not indices: + raise ValueError("Empty token span for decision role") + return (start + indices[0], start + indices[-1] + 1) + # Canonical segment tokenization makes endpoints exact; no string searching. + suffix.extend(self.tokenizer.encode("<|im_start|>user\n", add_special_tokens=False)) + for value in [question["instructions"]] + [v for pair in group for v in pair]: + if any(t in value for t in self.tokenizer.all_special_tokens): + raise ValueError("Reserved tokenizer control token in question/criteria") + prefix = "Task: " + question["type"] + "\nQuestion: " + instruction_span = append(prefix + question["instructions"] + "\nCandidates:\n", + (len(prefix), len(prefix) + len(question["instructions"]))) + positions, candidate_spans = [], [] + for key, description in group: + # Score never sees its level ID, nor any other level description. + prefix = key + ": " if question["type"] != "score" else "" + candidate_spans.append(append(prefix + description, (len(prefix), len(prefix) + len(description)))) + positions.append(base_length + len(suffix) - 1) + append("\n") + append("Decision:") + length = base_length + len(suffix) + if length > self.max_length: + raise ValueError(f"{qid}: {length} tokens exceed max_length={self.max_length}; no truncation") + inputs = dict(base) + inputs["input_ids"] = torch.cat([base["input_ids"], torch.tensor([suffix], dtype=torch.long)], dim=1) + inputs["attention_mask"] = torch.ones_like(inputs["input_ids"]) + if "mm_token_type_ids" in base: + inputs["mm_token_type_ids"] = torch.cat([base["mm_token_type_ids"], torch.zeros((1, len(suffix)), dtype=torch.long)], dim=1) + branches.append(Branch(inputs, positions, length - 1, (0, base_length), + instruction_span, candidate_spans)) + compute_tokens += length + logical_tokens += len(suffix) + compiled.append(Question(qid, question["type"], keys, [v for _, v in pairs], branches, + target_distribution(target, keys), not media)) + return CompiledState(compiled, logical_tokens, compute_tokens, media) + + def _compile_shared(self, selected, base, media, labeled_only=False): + """All schemas precede all readouts; labels and external IDs never enter inputs. + + This is ordinary causal attention, not isolated question/Score branches. + No answer tokens or LM output layer are required by the decision heads. + """ + base_length = base["input_ids"].shape[1] + suffix, compiled = [], [] + + def append(text, span=None): + start = base_length + len(suffix) + if span is None: + suffix.extend(self.tokenizer.encode(text, add_special_tokens=False)) + return None + encoded = self.tokenizer(text, add_special_tokens=False, return_offsets_mapping=True) + suffix.extend(encoded["input_ids"]) + indices = [i for i, (a, b) in enumerate(encoded["offset_mapping"]) if a < span[1] and b > span[0]] + if not indices: + raise ValueError("Empty token span for decision role") + return start + indices[0], start + indices[-1] + 1 + + append("<|im_start|>user\n") + for index, (qid, question, pairs, target) in enumerate(selected): + for value in [question["instructions"]] + [v for pair in pairs for v in pair]: + if any(t in value for t in self.tokenizer.all_special_tokens): + raise ValueError("Reserved tokenizer control token in question/criteria") + prefix = f"Question {index + 1}\nTask: {question['type']}\nQuestion: " + instruction = append(prefix + question["instructions"] + "\nCandidates:\n", + (len(prefix), len(prefix) + len(question["instructions"]))) + positions, spans = [], [] + for key, description in pairs: + prefix = key + ": " if question["type"] != "score" else "" + spans.append(append(prefix + description, (len(prefix), len(prefix) + len(description)))) + positions.append(base_length + len(suffix) - 1) + append("\n") + # Inputs and the decision position are filled after all schemas are appended. + branch = Branch({}, positions, -1, (0, base_length), instruction, spans) + keys = [key for key, _ in pairs] + compiled.append(Question(qid, question["type"], keys, [v for _, v in pairs], [branch], + target_distribution(target, keys), not media)) + append("<|im_end|>\n<|im_start|>assistant\n") + for index, question in enumerate(compiled): + append(f"Question {index + 1} Decision:") + question.branches[0].decision_position = base_length + len(suffix) - 1 + append("\n") + length = base_length + len(suffix) + if length > self.max_length: + raise ValueError(f"Shared state: {length} tokens exceed max_length={self.max_length}; no truncation") + inputs = dict(base) + inputs["input_ids"] = torch.cat([base["input_ids"], base["input_ids"].new_tensor([suffix])], dim=1) + inputs["attention_mask"] = torch.cat([base["attention_mask"], + base["attention_mask"].new_ones((1, len(suffix)))], dim=1) + if "mm_token_type_ids" in base: + inputs["mm_token_type_ids"] = torch.cat([base["mm_token_type_ids"], + base["mm_token_type_ids"].new_zeros((1, len(suffix)))], dim=1) + for question in compiled: + question.branches[0].inputs = inputs + if labeled_only: + compiled = [question for question in compiled if question.target is not None] + return CompiledState(compiled, length, length, media, inputs) diff --git a/config.json b/config.json new file mode 100644 index 0000000000000000000000000000000000000000..1be34fc1c9d3569e7dc57ce6606eaa9ebe60de42 --- /dev/null +++ b/config.json @@ -0,0 +1,138 @@ +{ + "architectures": [ + "ValenQwenForDecisionMaking" + ], + "auto_map": { + "AutoConfig": "configuration_valen.ValenQwenConfig", + "AutoModel": "modeling_valen.ValenQwenForDecisionMaking" + }, + "dtype": "bfloat16", + "image_token_id": 248056, + "model_type": "valen_qwen", + "qwen_execution": "shared_state", + "text_config": { + "attention_bias": false, + "attention_dropout": 0.0, + "attn_output_gate": true, + "bos_token_id": null, + "dtype": "bfloat16", + "eos_token_id": 248044, + "full_attention_interval": 4, + "head_dim": 256, + "hidden_act": "silu", + "hidden_size": 2560, + "initializer_range": 0.02, + "intermediate_size": 9216, + "layer_types": [ + "linear_attention", + "linear_attention", + "linear_attention", + "full_attention", + "linear_attention", + "linear_attention", + "linear_attention", + "full_attention", + "linear_attention", + "linear_attention", + "linear_attention", + "full_attention", + "linear_attention", + "linear_attention", + "linear_attention", + "full_attention", + "linear_attention", + "linear_attention", + "linear_attention", + "full_attention", + "linear_attention", + "linear_attention", + "linear_attention", + "full_attention", + "linear_attention", + "linear_attention", + "linear_attention", + "full_attention", + "linear_attention", + "linear_attention", + "linear_attention", + "full_attention" + ], + "linear_conv_kernel_dim": 4, + "linear_key_head_dim": 128, + "linear_num_key_heads": 16, + "linear_num_value_heads": 32, + "linear_value_head_dim": 128, + "mamba_ssm_dtype": "float32", + "max_position_embeddings": 262144, + "mlp_only_layers": [], + "model_type": "qwen3_5_text", + "mtp_num_hidden_layers": 1, + "mtp_use_dedicated_embeddings": false, + "num_attention_heads": 16, + "num_hidden_layers": 32, + "num_key_value_heads": 4, + "pad_token_id": null, + "partial_rotary_factor": 0.25, + "rms_norm_eps": 1e-06, + "rope_parameters": { + "mrope_interleaved": true, + "mrope_section": [ + 11, + 11, + 10 + ], + "partial_rotary_factor": 0.25, + "rope_theta": 10000000, + "rope_type": "default" + }, + "tie_word_embeddings": true, + "use_cache": true, + "vocab_size": 248320 + }, + "tie_word_embeddings": true, + "transformers_version": "5.4.0", + "valen_head": { + "head_channel_hidden_dim": 1024, + "head_layers": 2, + "head_token_hidden_dim": 16, + "head_type": "mixer", + "head_width": 256 + }, + "valen_max_length": 32768, + "valen_media_kwargs": { + "images_kwargs": { + "size": { + "longest_edge": 262144, + "shortest_edge": 65536 + } + }, + "videos_kwargs": { + "fps": null, + "num_frames": 16, + "size": { + "longest_edge": 2097152, + "shortest_edge": 131072 + } + } + }, + "video_token_id": 248057, + "vision_config": { + "deepstack_visual_indexes": [], + "depth": 24, + "dtype": "bfloat16", + "hidden_act": "gelu_pytorch_tanh", + "hidden_size": 1024, + "in_channels": 3, + "initializer_range": 0.02, + "intermediate_size": 4096, + "model_type": "qwen3_5", + "num_heads": 16, + "num_position_embeddings": 2304, + "out_hidden_size": 2560, + "patch_size": 16, + "spatial_merge_size": 2, + "temporal_patch_size": 2 + }, + "vision_end_token_id": 248054, + "vision_start_token_id": 248053 +} diff --git a/configuration_valen.py b/configuration_valen.py new file mode 100644 index 0000000000000000000000000000000000000000..a9252326abac70b4afc90518b61999f6ff07284c --- /dev/null +++ b/configuration_valen.py @@ -0,0 +1,16 @@ +"""Standalone Qwen decision configuration. / 独立的 Qwen 决策模型配置。""" +from transformers import Qwen3_5Config + + +class ValenQwenConfig(Qwen3_5Config): + model_type = "valen_qwen" + + def __init__(self, valen_head=None, qwen_execution="shared_state", valen_max_length=32768, + valen_media_kwargs=None, **kwargs): + if qwen_execution not in {"question", "shared_state"}: + raise ValueError("qwen_execution must be question or shared_state") + self.valen_head = valen_head or {"head_type": "mixer"} + self.qwen_execution = qwen_execution + self.valen_max_length = valen_max_length + self.valen_media_kwargs = valen_media_kwargs or {} + super().__init__(**kwargs) diff --git a/data_types.py b/data_types.py new file mode 100644 index 0000000000000000000000000000000000000000..ce1d6a8d6ee0f46600b13865ea941dcd7d803de0 --- /dev/null +++ b/data_types.py @@ -0,0 +1,12 @@ +"""Model-independent decision metadata; encoded tensors stay with each compiler.""" +from dataclasses import dataclass + + +@dataclass +class QuestionSpec: + qid: str + kind: str + keys: list + descriptions: list + target: list | None + is_text: bool diff --git a/export_manifest.json b/export_manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..34502ed249514e3e6a8b2f6f4fc98b77c3e880f6 --- /dev/null +++ b/export_manifest.json @@ -0,0 +1,82 @@ +{ + "format": "valen_qwen_merged_v1", + "created_utc": "2026-10-06T06:52:07.182367+00:00", + "model": "Valen-4B", + "architecture": "Qwen3.5 + two-layer Mixer", + "execution": "shared_state", + "source_checkpoint_sha256": "b4193b4e907f44b913fd54a8d6b998e7050a1528306269a000f1e5e8bd8dffc7", + "training_step": 325, + "training_records": 1225000, + "training_data_sha256": "648cb127fe4830f9faaa6d4595445cc2573ef0c152f8f74c9c776dc8a9223d7f", + "base": { + "repo": "Qwen/Qwen3.5-4B", + "revision": "851bf6e806efd8d0a36b00ddf55e13ccb7b8cd0a", + "weight_sha256": { + "model.safetensors-00001-of-00002.safetensors": "26a93f066e1916adb13453dae5a0c707c0fbc71299ed98779571a907b8e74c61", + "model.safetensors-00002-of-00002.safetensors": "cb544bd9bfae93dc59b0f22b292f5933573854a7f9b97835c67060d7d910e188" + }, + "files_sha256": { + ".gitattributes": "34448b82c17d60fec9b65b1f093c115ddbaadc04beb1b0140b6bfed2e012a930", + "LICENSE": "bbedc3fda3305820b977265f01b8619d87570a6739de3a5582c3464840f1e57a", + "README.md": "1406be1b6b8fd8a6545870da516912804756593628a1d0fb0a7965211e82a7bb", + "chat_template.jinja": "a4aee8afcf2e0711942cf848899be66016f8d14a889ff9ede07bca099c28f715", + "config.json": "ddc63e1c717afa86c865bb5e01313d89d72bb53b97ad4a8a03ba8510c0621670", + "merges.txt": "a9d356d7bdf1ef4949e3e748e95b8e10ad9d4e2e838eddc38a0a7b6b94d1db8d", + "model.safetensors-00001-of-00002.safetensors": "26a93f066e1916adb13453dae5a0c707c0fbc71299ed98779571a907b8e74c61", + "model.safetensors-00002-of-00002.safetensors": "cb544bd9bfae93dc59b0f22b292f5933573854a7f9b97835c67060d7d910e188", + "model.safetensors.index.json": "cf3f798ee02ba45f9622aa8892a47369ab667d0afbf154ee7c2212de42e6302d", + "preprocessor_config.json": "27225450ac9c6529872ee1924fcb0962ff5634834f817040f444118116f4e516", + "tokenizer.json": "5f9e4d4901a92b997e463c1f46055088b6cca5ca61a6522d1b9f64c4bb81cb42", + "tokenizer_config.json": "316230d6a809701f4db5ea8f8fc862bc3a6f3229c937c174e674ff3ca0a64ac8", + "video_preprocessor_config.json": "7768af27c1fafa9cc9011c1dc20067e03f8915e03b63504550e11d5066986d13", + "vocab.json": "ce99b4cb2983d118806ce0a8b777a35b093e2000a503ebde25853284c9dfa003" + }, + "verified_from": "download_manifest.json; every LFS SHA256 matched" + }, + "merge": "FP32 base+LoRA accumulation, stored BF16; trained visual merger and FP32 Mixer retained", + "merged_linear_layers": 248, + "runtime_source_sha256": { + "valen/modeling/qwen/heads.py": "63b5970a8bfa121eff94d50ffd35e1fa8387f3af5abccc5f5b75381fb084fc34", + "valen/modeling/qwen/batching.py": "ea45d4724bcafca559fc5a2a18092918b633746771c19da6554c29bc5f2cef64", + "valen/modeling/qwen/model.py": "37b97e52bd16ada6a841fd553454ec0b0e458f3966ca0bef8a1bfe15293c2271", + "valen/data/compilers/qwen.py": "cae0389c407a9e67e1b14776b56d87767046b4ad119e93d138e1ae2f20fcadb2", + "valen/data/schema.py": "253825862b60016e37fd1040492008ad7f303679c092313d8a6527cf509f3b6e", + "valen/data/types.py": "b06ce08081d8f7b2bf36abf302410a96086395e75a04f9e9b1c591db519b1641", + "valen/evaluation/inference.py": "ccb47efd9f029f19a70cc462e262143cbab021deb4b8f4d11d2ecec054cbe553" + }, + "versions": { + "torch": "2.6.0", + "transformers": "5.4.0", + "peft": "0.18.1", + "safetensors": "0.6.2", + "flash-attn": "2.7.4.post1", + "torchvision": "0.21.0", + "Pillow": "11.3.0", + "av": "16.1.0" + }, + "files_sha256": { + "LICENSE": "bbedc3fda3305820b977265f01b8619d87570a6739de3a5582c3464840f1e57a", + "MODEL_USAGE.md": "cc6beb959e63059e68d8e5badb4df45090a22f1b049b1762262deb1988a61590", + "batching.py": "ea45d4724bcafca559fc5a2a18092918b633746771c19da6554c29bc5f2cef64", + "chat_template.jinja": "a4aee8afcf2e0711942cf848899be66016f8d14a889ff9ede07bca099c28f715", + "compiler.py": "f35bab2e71b6beb1228daaa5b7baecdacf04eaf713aee14e8082b97090f910b4", + "config.json": "15dd1b0e94aa6ad330d3d8c50e4f9ea579edbb21fb2ba13c02b32c3e0ede6527", + "configuration_valen.py": "735b02402fb5b6c7a1652f6691ba66d066ef99e84500042faec396ff7a668fe5", + "data_types.py": "b06ce08081d8f7b2bf36abf302410a96086395e75a04f9e9b1c591db519b1641", + "heads.py": "63b5970a8bfa121eff94d50ffd35e1fa8387f3af5abccc5f5b75381fb084fc34", + "model-00001-of-00003.safetensors": "21fef5c5b93c2d9f1e54100f31709aaeb1651058784b9d38c47d9345fdba50d0", + "model-00002-of-00003.safetensors": "9ec6792a776db86b348b97ae3e9ff5feaa055dba2ea28035aac9f1d543623e9b", + "model-00003-of-00003.safetensors": "c7b96a0d85eb01475c0f775a51f88e4455aeae31143cc86c8457723d9019c13e", + "model.safetensors.index.json": "69f50ed2c7dcbbda30cc1b9ec3413ef84f2ac9aa569f357eec9f8ab63d1fdb95", + "modeling_valen.py": "07f87481334cb1e28e9daee036c27bab3654645abf3df7983346b316e7788848", + "processor_config.json": "d89ef49ce9cd37fbf510158e13c1ef063d9286411c1ec9049932dbe0487143b1", + "responses.py": "298016b0070f1000a38d033e1048e038ff5df6fc1dcbe830601105b181f1d228", + "runtime_model.py": "98bf0443ca196900b9f2b056129c84932041b8b53395d111f2fe6d3f2bc1e0a6", + "schema.py": "253825862b60016e37fd1040492008ad7f303679c092313d8a6527cf509f3b6e", + "tokenizer.json": "87a7830d63fcf43bf241c3c5242e96e62dd3fdc29224ca26fed8ea333db72de4", + "tokenizer_config.json": "e98f1901ac6f0adff67b1d540bfa0c36ac1a0cf59eb72ed78146ef89aafa1182", + "validation.json": "0ed2de1bc25b85c42d2329e42eb53bb6bad85e1ee3e2ec598a1dff643a3aa509", + "README.md": "fc0d6e3a980891edd2264d5a705da824cb1c0a31ebf52f44da54903c13d2b4c3", + "fresh_process_validation.json": "5945d5fc669cb573bb47db5fd41c3bb3ceb51b81b6951eea30681c7451505d43" + } +} diff --git a/fresh_process_validation.json b/fresh_process_validation.json new file mode 100644 index 0000000000000000000000000000000000000000..653a095b72586e569f260f197ed3be6999d9d1ce --- /dev/null +++ b/fresh_process_validation.json @@ -0,0 +1,112 @@ +{ + "passed": true, + "isolated_python": true, + "valen_imports_blocked": true, + "all_real_modalities_and_question_types_passed": true, + "sdpa_example_passed": true, + "cases": 20, + "max_probability_abs_error": 0.0, + "max_logit_abs_error": 0.0, + "details": [ + { + "case": "shared_state/text_multi/choice", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/text_multi/noul", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/text_multi/score", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/text_multi/score_many", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/image_score/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/image_noul/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/image_choice/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/video_multi/q000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/video_multi/score_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/video_multi/noul_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/text_multi/choice", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/text_multi/noul", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/text_multi/score", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/text_multi/score_many", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/image_score/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/image_noul/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/image_choice/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/video_multi/q000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/video_multi/score_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/video_multi/noul_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + } + ] +} diff --git a/heads.py b/heads.py new file mode 100644 index 0000000000000000000000000000000000000000..47627b2dc79bfafeea627683628f949f80ab7692 --- /dev/null +++ b/heads.py @@ -0,0 +1,143 @@ +"""可替换的候选评分头。 / Interchangeable, candidate-wise decision heads.""" +import math + +import torch +from torch import nn + + +def head_signature(config): + """用于构建与恢复校验。 / Canonical architecture settings for loading.""" + kind = config.get("head_type", "bilinear") + defaults = { + "bilinear": {"projection_dim": 256}, + "mlp": {"head_hidden_dim": 512, "head_bottleneck_dim": 128}, + "role_mlp": {"head_width": 256, "head_hidden_dim": 1024}, + "mixer": {"head_width": 256, "head_layers": 2, + "head_token_hidden_dim": 16, "head_channel_hidden_dim": 1024}, + } + if kind not in defaults: + raise ValueError(f"Unknown Qwen head_type: {kind!r}") + values = {key: config.get(key, value) for key, value in defaults[kind].items()} + if any(type(value) is not int or value <= 0 for value in values.values()): + raise ValueError("Decision head dimensions must be positive integers") + return {"head_type": kind, **values} + + +class DecisionHead(nn.Module): + """原有参数名保持兼容。 / Preserve legacy bilinear parameter names.""" + def __init__(self, hidden_size, projection_dim=256): + super().__init__() + self.decision = nn.Linear(hidden_size, projection_dim, bias=False) + self.candidate = nn.Linear(hidden_size, projection_dim, bias=False) + self.scale = math.sqrt(projection_dim) + + def forward(self, hidden, positions, decision_position): + d = self.decision(hidden[0, decision_position].float()) + c = self.candidate(hidden[0, positions].float()) + return (c * d).sum(-1) / self.scale + + def extract_features(self, hidden, branch): + return hidden[:, [*branch.candidate_positions, branch.decision_position], :] + + def score_features(self, features): + return self(features, list(range(features.shape[1] - 1)), features.shape[1] - 1) + + +class MLPHead(nn.Module): + """每个候选共享一个 MLP。 / One shared MLP for arbitrary candidate counts.""" + def __init__(self, hidden_size, hidden_dim=512, bottleneck_dim=128): + super().__init__() + self.decision_norm = nn.LayerNorm(hidden_size) + self.candidate_norm = nn.LayerNorm(hidden_size) + self.network = nn.Sequential(nn.Linear(2 * hidden_size, hidden_dim), nn.GELU(), + nn.Linear(hidden_dim, bottleneck_dim), nn.GELU(), + nn.Linear(bottleneck_dim, 1)) + + def extract_features(self, hidden, branch): + c = hidden[0, branch.candidate_positions] + d = hidden[0, branch.decision_position].expand_as(c) + return torch.stack((d, c), dim=1) + + def score_features(self, features): + d, c = features.float().unbind(1) + return self.network(torch.cat((self.decision_norm(d), self.candidate_norm(c)), -1)).squeeze(-1) + + +def role_features(hidden, branch): + """先池化再投影,可缓存冻结特征。 / Pool before trainable projections.""" + spans = (getattr(branch, "context_span", None), getattr(branch, "instruction_span", None)) + candidates = getattr(branch, "candidate_spans", None) + if any(span is None for span in spans) or not candidates or len(candidates) != len(branch.candidate_positions): + raise ValueError("Role heads require compiler context, instruction and candidate spans") + + def pool(span): + start, end = span + if not 0 <= start < end <= hidden.shape[1]: + raise ValueError(f"Invalid role span: {span}") + return hidden[0, start:end].float().mean(0) + + context, instruction = (pool(span) for span in spans) + decision = hidden[0, branch.decision_position].float() + return torch.stack([torch.stack((context, instruction, pool(span), decision)) for span in candidates]) + + +class RoleHead(nn.Module): + def __init__(self, hidden_size, width): + super().__init__() + self.input_norm = nn.LayerNorm(hidden_size) + self.projection = nn.Linear(hidden_size, width) + self.roles = nn.Parameter(torch.zeros(1, 4, width)) + + def extract_features(self, hidden, branch): + return role_features(hidden, branch) + + def project(self, features): + return self.projection(self.input_norm(features.float())) + self.roles + + +class RoleMLPHead(RoleHead): + """与 Mixer 使用相同输入。 / Control for the Mixer's richer input features.""" + def __init__(self, hidden_size, width=256, hidden_dim=1024): + super().__init__(hidden_size, width) + self.network = nn.Sequential(nn.Linear(4 * width, hidden_dim), nn.GELU(), nn.Linear(hidden_dim, 1)) + + def score_features(self, features): + return self.network(self.project(features).flatten(1)).squeeze(-1) + + +class MixerBlock(nn.Module): + def __init__(self, width, token_hidden, channel_hidden): + super().__init__() + self.token_norm = nn.LayerNorm(width) + self.token_mlp = nn.Sequential(nn.Linear(4, token_hidden), nn.GELU(), nn.Linear(token_hidden, 4)) + self.channel_norm = nn.LayerNorm(width) + self.channel_mlp = nn.Sequential(nn.Linear(width, channel_hidden), nn.GELU(), nn.Linear(channel_hidden, width)) + + def forward(self, x): + # 混合角色,不混合不同候选。 / Mix fixed roles, never candidate rows. + x = x + self.token_mlp(self.token_norm(x).transpose(1, 2)).transpose(1, 2) + return x + self.channel_mlp(self.channel_norm(x)) + + +class MixerHead(RoleHead): + def __init__(self, hidden_size, width=256, layers=2, token_hidden=16, channel_hidden=1024): + super().__init__(hidden_size, width) + self.blocks = nn.Sequential(*(MixerBlock(width, token_hidden, channel_hidden) for _ in range(layers))) + self.output = nn.Sequential(nn.LayerNorm(width), nn.Linear(width, 1)) + + def score_features(self, features): + # 第三行是候选角色。 / Read the updated candidate role. + return self.output(self.blocks(self.project(features))[:, 2]).squeeze(-1) + + +def build_head(hidden_size, config): + settings = head_signature(config) + kind = settings.pop("head_type") + if kind == "bilinear": + return DecisionHead(hidden_size, settings["projection_dim"]) + if kind == "mlp": + return MLPHead(hidden_size, settings["head_hidden_dim"], settings["head_bottleneck_dim"]) + if kind == "role_mlp": + return RoleMLPHead(hidden_size, settings["head_width"], settings["head_hidden_dim"]) + return MixerHead(hidden_size, settings["head_width"], settings["head_layers"], + settings["head_token_hidden_dim"], settings["head_channel_hidden_dim"]) diff --git a/model-00001-of-00003.safetensors b/model-00001-of-00003.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..2b75b810f61570d0dd0d0632dc8f621663f8f3d4 --- /dev/null +++ b/model-00001-of-00003.safetensors @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21fef5c5b93c2d9f1e54100f31709aaeb1651058784b9d38c47d9345fdba50d0 +size 3991299376 diff --git a/model-00002-of-00003.safetensors b/model-00002-of-00003.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..34d1812a12904fdf0f2ee7abf769ff673ecd977b --- /dev/null +++ b/model-00002-of-00003.safetensors @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ec6792a776db86b348b97ae3e9ff5feaa055dba2ea28035aac9f1d543623e9b +size 3979833864 diff --git a/model-00003-of-00003.safetensors b/model-00003-of-00003.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..3bcd19335665e4a03a59b28ba6085623981748d8 --- /dev/null +++ b/model-00003-of-00003.safetensors @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c7b96a0d85eb01475c0f775a51f88e4455aeae31143cc86c8457723d9019c13e +size 1114356012 diff --git a/model.safetensors.index.json b/model.safetensors.index.json new file mode 100644 index 0000000000000000000000000000000000000000..26e247fc33f850d2b05df4f98f4da0640d52da1d --- /dev/null +++ b/model.safetensors.index.json @@ -0,0 +1,764 @@ +{ + "metadata": { + "total_parameters": 4540981545, + "total_size": 9085395108 + }, + "weight_map": { + "backbone.language_model.embed_tokens.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.0.input_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.0.linear_attn.A_log": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.0.linear_attn.conv1d.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.0.linear_attn.dt_bias": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.0.linear_attn.in_proj_a.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.0.linear_attn.in_proj_b.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.0.linear_attn.in_proj_qkv.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.0.linear_attn.in_proj_z.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.0.linear_attn.norm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.0.linear_attn.out_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.0.mlp.down_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.0.mlp.gate_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.0.mlp.up_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.0.post_attention_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.1.input_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.1.linear_attn.A_log": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.1.linear_attn.conv1d.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.1.linear_attn.dt_bias": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.1.linear_attn.in_proj_a.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.1.linear_attn.in_proj_b.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.1.linear_attn.in_proj_qkv.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.1.linear_attn.in_proj_z.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.1.linear_attn.norm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.1.linear_attn.out_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.1.mlp.down_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.1.mlp.gate_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.1.mlp.up_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.1.post_attention_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.10.input_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.10.linear_attn.A_log": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.10.linear_attn.conv1d.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.10.linear_attn.dt_bias": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.10.linear_attn.in_proj_a.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.10.linear_attn.in_proj_b.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.10.linear_attn.in_proj_qkv.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.10.linear_attn.in_proj_z.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.10.linear_attn.norm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.10.linear_attn.out_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.10.mlp.down_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.10.mlp.gate_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.10.mlp.up_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.10.post_attention_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.11.input_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.11.mlp.down_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.11.mlp.gate_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.11.mlp.up_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.11.post_attention_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.11.self_attn.k_norm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.11.self_attn.k_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.11.self_attn.o_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.11.self_attn.q_norm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.11.self_attn.q_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.11.self_attn.v_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.12.input_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.12.linear_attn.A_log": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.12.linear_attn.conv1d.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.12.linear_attn.dt_bias": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.12.linear_attn.in_proj_a.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.12.linear_attn.in_proj_b.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.12.linear_attn.in_proj_qkv.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.12.linear_attn.in_proj_z.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.12.linear_attn.norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.12.linear_attn.out_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.12.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.12.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.12.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.12.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.13.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.13.linear_attn.A_log": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.13.linear_attn.conv1d.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.13.linear_attn.dt_bias": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.13.linear_attn.in_proj_a.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.13.linear_attn.in_proj_b.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.13.linear_attn.in_proj_qkv.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.13.linear_attn.in_proj_z.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.13.linear_attn.norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.13.linear_attn.out_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.13.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.13.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.13.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.13.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.14.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.14.linear_attn.A_log": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.14.linear_attn.conv1d.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.14.linear_attn.dt_bias": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.14.linear_attn.in_proj_a.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.14.linear_attn.in_proj_b.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.14.linear_attn.in_proj_qkv.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.14.linear_attn.in_proj_z.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.14.linear_attn.norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.14.linear_attn.out_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.14.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.14.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.14.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.14.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.15.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.15.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.15.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.15.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.15.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.15.self_attn.k_norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.15.self_attn.k_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.15.self_attn.o_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.15.self_attn.q_norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.15.self_attn.q_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.15.self_attn.v_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.16.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.16.linear_attn.A_log": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.16.linear_attn.conv1d.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.16.linear_attn.dt_bias": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.16.linear_attn.in_proj_a.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.16.linear_attn.in_proj_b.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.16.linear_attn.in_proj_qkv.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.16.linear_attn.in_proj_z.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.16.linear_attn.norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.16.linear_attn.out_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.16.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.16.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.16.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.16.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.17.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.17.linear_attn.A_log": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.17.linear_attn.conv1d.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.17.linear_attn.dt_bias": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.17.linear_attn.in_proj_a.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.17.linear_attn.in_proj_b.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.17.linear_attn.in_proj_qkv.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.17.linear_attn.in_proj_z.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.17.linear_attn.norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.17.linear_attn.out_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.17.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.17.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.17.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.17.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.18.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.18.linear_attn.A_log": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.18.linear_attn.conv1d.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.18.linear_attn.dt_bias": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.18.linear_attn.in_proj_a.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.18.linear_attn.in_proj_b.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.18.linear_attn.in_proj_qkv.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.18.linear_attn.in_proj_z.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.18.linear_attn.norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.18.linear_attn.out_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.18.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.18.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.18.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.18.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.19.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.19.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.19.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.19.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.19.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.19.self_attn.k_norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.19.self_attn.k_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.19.self_attn.o_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.19.self_attn.q_norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.19.self_attn.q_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.19.self_attn.v_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.2.input_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.2.linear_attn.A_log": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.2.linear_attn.conv1d.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.2.linear_attn.dt_bias": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.2.linear_attn.in_proj_a.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.2.linear_attn.in_proj_b.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.2.linear_attn.in_proj_qkv.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.2.linear_attn.in_proj_z.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.2.linear_attn.norm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.2.linear_attn.out_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.2.mlp.down_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.2.mlp.gate_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.2.mlp.up_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.2.post_attention_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.20.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.20.linear_attn.A_log": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.20.linear_attn.conv1d.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.20.linear_attn.dt_bias": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.20.linear_attn.in_proj_a.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.20.linear_attn.in_proj_b.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.20.linear_attn.in_proj_qkv.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.20.linear_attn.in_proj_z.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.20.linear_attn.norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.20.linear_attn.out_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.20.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.20.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.20.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.20.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.21.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.21.linear_attn.A_log": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.21.linear_attn.conv1d.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.21.linear_attn.dt_bias": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.21.linear_attn.in_proj_a.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.21.linear_attn.in_proj_b.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.21.linear_attn.in_proj_qkv.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.21.linear_attn.in_proj_z.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.21.linear_attn.norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.21.linear_attn.out_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.21.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.21.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.21.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.21.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.22.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.22.linear_attn.A_log": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.22.linear_attn.conv1d.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.22.linear_attn.dt_bias": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.22.linear_attn.in_proj_a.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.22.linear_attn.in_proj_b.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.22.linear_attn.in_proj_qkv.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.22.linear_attn.in_proj_z.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.22.linear_attn.norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.22.linear_attn.out_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.22.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.22.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.22.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.22.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.23.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.23.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.23.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.23.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.23.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.23.self_attn.k_norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.23.self_attn.k_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.23.self_attn.o_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.23.self_attn.q_norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.23.self_attn.q_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.23.self_attn.v_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.24.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.24.linear_attn.A_log": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.24.linear_attn.conv1d.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.24.linear_attn.dt_bias": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.24.linear_attn.in_proj_a.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.24.linear_attn.in_proj_b.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.24.linear_attn.in_proj_qkv.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.24.linear_attn.in_proj_z.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.24.linear_attn.norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.24.linear_attn.out_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.24.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.24.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.24.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.24.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.25.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.25.linear_attn.A_log": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.25.linear_attn.conv1d.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.25.linear_attn.dt_bias": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.25.linear_attn.in_proj_a.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.25.linear_attn.in_proj_b.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.25.linear_attn.in_proj_qkv.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.25.linear_attn.in_proj_z.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.25.linear_attn.norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.25.linear_attn.out_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.25.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.25.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.25.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.25.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.26.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.26.linear_attn.A_log": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.26.linear_attn.conv1d.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.26.linear_attn.dt_bias": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.26.linear_attn.in_proj_a.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.26.linear_attn.in_proj_b.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.26.linear_attn.in_proj_qkv.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.26.linear_attn.in_proj_z.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.26.linear_attn.norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.26.linear_attn.out_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.26.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.26.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.26.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.26.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.27.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.27.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.27.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.27.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.27.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.27.self_attn.k_norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.27.self_attn.k_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.27.self_attn.o_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.27.self_attn.q_norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.27.self_attn.q_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.27.self_attn.v_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.28.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.28.linear_attn.A_log": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.28.linear_attn.conv1d.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.28.linear_attn.dt_bias": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.28.linear_attn.in_proj_a.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.28.linear_attn.in_proj_b.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.28.linear_attn.in_proj_qkv.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.28.linear_attn.in_proj_z.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.28.linear_attn.norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.28.linear_attn.out_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.28.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.28.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.28.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.28.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.29.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.29.linear_attn.A_log": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.29.linear_attn.conv1d.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.29.linear_attn.dt_bias": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.29.linear_attn.in_proj_a.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.29.linear_attn.in_proj_b.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.29.linear_attn.in_proj_qkv.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.29.linear_attn.in_proj_z.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.29.linear_attn.norm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.29.linear_attn.out_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.29.mlp.down_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.29.mlp.gate_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.29.mlp.up_proj.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.29.post_attention_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.3.input_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.3.mlp.down_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.3.mlp.gate_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.3.mlp.up_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.3.post_attention_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.3.self_attn.k_norm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.3.self_attn.k_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.3.self_attn.o_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.3.self_attn.q_norm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.3.self_attn.q_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.3.self_attn.v_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.30.input_layernorm.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.30.linear_attn.A_log": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.30.linear_attn.conv1d.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.30.linear_attn.dt_bias": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.30.linear_attn.in_proj_a.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.30.linear_attn.in_proj_b.weight": "model-00002-of-00003.safetensors", + "backbone.language_model.layers.30.linear_attn.in_proj_qkv.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.30.linear_attn.in_proj_z.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.30.linear_attn.norm.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.30.linear_attn.out_proj.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.30.mlp.down_proj.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.30.mlp.gate_proj.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.30.mlp.up_proj.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.30.post_attention_layernorm.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.31.input_layernorm.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.31.mlp.down_proj.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.31.mlp.gate_proj.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.31.mlp.up_proj.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.31.post_attention_layernorm.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.31.self_attn.k_norm.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.31.self_attn.k_proj.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.31.self_attn.o_proj.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.31.self_attn.q_norm.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.31.self_attn.q_proj.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.31.self_attn.v_proj.weight": "model-00003-of-00003.safetensors", + "backbone.language_model.layers.4.input_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.4.linear_attn.A_log": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.4.linear_attn.conv1d.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.4.linear_attn.dt_bias": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.4.linear_attn.in_proj_a.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.4.linear_attn.in_proj_b.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.4.linear_attn.in_proj_qkv.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.4.linear_attn.in_proj_z.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.4.linear_attn.norm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.4.linear_attn.out_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.4.mlp.down_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.4.mlp.gate_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.4.mlp.up_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.4.post_attention_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.5.input_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.5.linear_attn.A_log": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.5.linear_attn.conv1d.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.5.linear_attn.dt_bias": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.5.linear_attn.in_proj_a.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.5.linear_attn.in_proj_b.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.5.linear_attn.in_proj_qkv.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.5.linear_attn.in_proj_z.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.5.linear_attn.norm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.5.linear_attn.out_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.5.mlp.down_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.5.mlp.gate_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.5.mlp.up_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.5.post_attention_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.6.input_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.6.linear_attn.A_log": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.6.linear_attn.conv1d.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.6.linear_attn.dt_bias": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.6.linear_attn.in_proj_a.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.6.linear_attn.in_proj_b.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.6.linear_attn.in_proj_qkv.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.6.linear_attn.in_proj_z.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.6.linear_attn.norm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.6.linear_attn.out_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.6.mlp.down_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.6.mlp.gate_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.6.mlp.up_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.6.post_attention_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.7.input_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.7.mlp.down_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.7.mlp.gate_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.7.mlp.up_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.7.post_attention_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.7.self_attn.k_norm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.7.self_attn.k_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.7.self_attn.o_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.7.self_attn.q_norm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.7.self_attn.q_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.7.self_attn.v_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.8.input_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.8.linear_attn.A_log": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.8.linear_attn.conv1d.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.8.linear_attn.dt_bias": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.8.linear_attn.in_proj_a.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.8.linear_attn.in_proj_b.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.8.linear_attn.in_proj_qkv.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.8.linear_attn.in_proj_z.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.8.linear_attn.norm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.8.linear_attn.out_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.8.mlp.down_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.8.mlp.gate_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.8.mlp.up_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.8.post_attention_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.9.input_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.9.linear_attn.A_log": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.9.linear_attn.conv1d.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.9.linear_attn.dt_bias": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.9.linear_attn.in_proj_a.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.9.linear_attn.in_proj_b.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.9.linear_attn.in_proj_qkv.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.9.linear_attn.in_proj_z.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.9.linear_attn.norm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.9.linear_attn.out_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.9.mlp.down_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.9.mlp.gate_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.9.mlp.up_proj.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.layers.9.post_attention_layernorm.weight": "model-00001-of-00003.safetensors", + "backbone.language_model.norm.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.0.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.0.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.0.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.0.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.0.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.0.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.0.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.0.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.0.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.0.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.0.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.0.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.1.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.1.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.1.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.1.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.1.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.1.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.1.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.1.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.1.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.1.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.1.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.1.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.10.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.10.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.10.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.10.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.10.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.10.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.10.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.10.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.10.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.10.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.10.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.10.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.11.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.11.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.11.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.11.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.11.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.11.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.11.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.11.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.11.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.11.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.11.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.11.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.12.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.12.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.12.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.12.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.12.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.12.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.12.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.12.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.12.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.12.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.12.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.12.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.13.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.13.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.13.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.13.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.13.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.13.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.13.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.13.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.13.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.13.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.13.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.13.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.14.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.14.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.14.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.14.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.14.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.14.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.14.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.14.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.14.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.14.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.14.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.14.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.15.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.15.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.15.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.15.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.15.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.15.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.15.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.15.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.15.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.15.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.15.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.15.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.16.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.16.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.16.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.16.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.16.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.16.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.16.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.16.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.16.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.16.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.16.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.16.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.17.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.17.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.17.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.17.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.17.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.17.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.17.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.17.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.17.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.17.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.17.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.17.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.18.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.18.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.18.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.18.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.18.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.18.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.18.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.18.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.18.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.18.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.18.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.18.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.19.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.19.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.19.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.19.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.19.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.19.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.19.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.19.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.19.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.19.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.19.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.19.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.2.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.2.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.2.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.2.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.2.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.2.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.2.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.2.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.2.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.2.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.2.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.2.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.20.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.20.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.20.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.20.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.20.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.20.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.20.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.20.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.20.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.20.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.20.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.20.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.21.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.21.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.21.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.21.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.21.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.21.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.21.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.21.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.21.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.21.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.21.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.21.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.22.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.22.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.22.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.22.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.22.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.22.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.22.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.22.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.22.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.22.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.22.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.22.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.23.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.23.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.23.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.23.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.23.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.23.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.23.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.23.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.23.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.23.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.23.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.23.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.3.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.3.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.3.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.3.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.3.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.3.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.3.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.3.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.3.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.3.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.3.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.3.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.4.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.4.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.4.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.4.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.4.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.4.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.4.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.4.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.4.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.4.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.4.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.4.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.5.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.5.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.5.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.5.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.5.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.5.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.5.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.5.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.5.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.5.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.5.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.5.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.6.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.6.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.6.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.6.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.6.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.6.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.6.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.6.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.6.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.6.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.6.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.6.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.7.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.7.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.7.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.7.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.7.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.7.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.7.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.7.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.7.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.7.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.7.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.7.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.8.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.8.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.8.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.8.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.8.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.8.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.8.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.8.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.8.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.8.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.8.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.8.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.9.attn.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.9.attn.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.9.attn.qkv.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.9.attn.qkv.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.9.mlp.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.9.mlp.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.9.mlp.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.9.mlp.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.9.norm1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.9.norm1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.9.norm2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.blocks.9.norm2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.merger.linear_fc1.bias": "model-00003-of-00003.safetensors", + "backbone.visual.merger.linear_fc1.weight": "model-00003-of-00003.safetensors", + "backbone.visual.merger.linear_fc2.bias": "model-00003-of-00003.safetensors", + "backbone.visual.merger.linear_fc2.weight": "model-00003-of-00003.safetensors", + "backbone.visual.merger.norm.bias": "model-00003-of-00003.safetensors", + "backbone.visual.merger.norm.weight": "model-00003-of-00003.safetensors", + "backbone.visual.patch_embed.proj.bias": "model-00003-of-00003.safetensors", + "backbone.visual.patch_embed.proj.weight": "model-00003-of-00003.safetensors", + "backbone.visual.pos_embed.weight": "model-00003-of-00003.safetensors", + "head.blocks.0.channel_mlp.0.bias": "model-00003-of-00003.safetensors", + "head.blocks.0.channel_mlp.0.weight": "model-00003-of-00003.safetensors", + "head.blocks.0.channel_mlp.2.bias": "model-00003-of-00003.safetensors", + "head.blocks.0.channel_mlp.2.weight": "model-00003-of-00003.safetensors", + "head.blocks.0.channel_norm.bias": "model-00003-of-00003.safetensors", + "head.blocks.0.channel_norm.weight": "model-00003-of-00003.safetensors", + "head.blocks.0.token_mlp.0.bias": "model-00003-of-00003.safetensors", + "head.blocks.0.token_mlp.0.weight": "model-00003-of-00003.safetensors", + "head.blocks.0.token_mlp.2.bias": "model-00003-of-00003.safetensors", + "head.blocks.0.token_mlp.2.weight": "model-00003-of-00003.safetensors", + "head.blocks.0.token_norm.bias": "model-00003-of-00003.safetensors", + "head.blocks.0.token_norm.weight": "model-00003-of-00003.safetensors", + "head.blocks.1.channel_mlp.0.bias": "model-00003-of-00003.safetensors", + "head.blocks.1.channel_mlp.0.weight": "model-00003-of-00003.safetensors", + "head.blocks.1.channel_mlp.2.bias": "model-00003-of-00003.safetensors", + "head.blocks.1.channel_mlp.2.weight": "model-00003-of-00003.safetensors", + "head.blocks.1.channel_norm.bias": "model-00003-of-00003.safetensors", + "head.blocks.1.channel_norm.weight": "model-00003-of-00003.safetensors", + "head.blocks.1.token_mlp.0.bias": "model-00003-of-00003.safetensors", + "head.blocks.1.token_mlp.0.weight": "model-00003-of-00003.safetensors", + "head.blocks.1.token_mlp.2.bias": "model-00003-of-00003.safetensors", + "head.blocks.1.token_mlp.2.weight": "model-00003-of-00003.safetensors", + "head.blocks.1.token_norm.bias": "model-00003-of-00003.safetensors", + "head.blocks.1.token_norm.weight": "model-00003-of-00003.safetensors", + "head.input_norm.bias": "model-00003-of-00003.safetensors", + "head.input_norm.weight": "model-00003-of-00003.safetensors", + "head.output.0.bias": "model-00003-of-00003.safetensors", + "head.output.0.weight": "model-00003-of-00003.safetensors", + "head.output.1.bias": "model-00003-of-00003.safetensors", + "head.output.1.weight": "model-00003-of-00003.safetensors", + "head.projection.bias": "model-00003-of-00003.safetensors", + "head.projection.weight": "model-00003-of-00003.safetensors", + "head.roles": "model-00003-of-00003.safetensors" + } +} diff --git a/modeling_valen.py b/modeling_valen.py new file mode 100644 index 0000000000000000000000000000000000000000..3c8d3a4ae3d4dfde9e3ece865bc57bccd4d1d6cd --- /dev/null +++ b/modeling_valen.py @@ -0,0 +1,84 @@ +"""Complete merged Qwen + decision head. / 已合并的完整 Qwen 和决策头。""" +import torch +from transformers import AutoProcessor +from transformers.models.qwen3_5.modeling_qwen3_5 import Qwen3_5Model, Qwen3_5PreTrainedModel + +from .configuration_valen import ValenQwenConfig +from .heads import build_head +from .runtime_model import ValenQwen +from .compiler import Compiler +from .responses import answer +# List transitive files explicitly for Transformers' local dynamic loader. +# 本地动态加载需要显式列出间接依赖,否则搬移后可能缺少这些模块。 +from .batching import collate_branches +from .schema import candidates +from .data_types import QuestionSpec + + +class ValenQwenForDecisionMaking(Qwen3_5PreTrainedModel): + config_class = ValenQwenConfig + base_model_prefix = "backbone" + model_name = "Valen" + architecture = "qwen" + # The trained Mixer stays FP32 with a BF16 backbone. / BF16 基座、FP32 决策头。 + _keep_in_fp32_modules_strict = ["head"] + + def __init__(self, config, backbone=None, head=None): + super().__init__(config) + if (backbone is None) != (head is None): + raise ValueError("Supply both a merged backbone and a trained head") + self.backbone = backbone if backbone is not None else Qwen3_5Model(config) + self.head = head if head is not None else build_head(config.text_config.hidden_size, config.valen_head) + self.head.float() + self._processor = None + # Supplied weights are already trained: do not reinitialize them. + # 传入的参数已训练完成,不能再次调用初始化覆盖它们。 + if backbone is not None: + for module in self.modules(): + module._is_hf_initialized = True + self.post_init() + + def get_input_embeddings(self): + return self.backbone.get_input_embeddings() + + def set_input_embeddings(self, value): + self.backbone.set_input_embeddings(value) + + def forward(self, question=None, **inputs): + if question is None: + return self.backbone(**inputs) + if hasattr(question, "questions"): + return self.forward_state(question) + return ValenQwen.forward(self, question) + + # Use the exact trained readouts and batching implementation. + # 保留训练时的特征读取和 batch 逻辑。 + extract_features = ValenQwen.extract_features + extract_state_features = ValenQwen.extract_state_features + _state_features = ValenQwen._state_features + forward_state = ValenQwen.forward_state + forward_state_batch = ValenQwen.forward_state_batch + forward_batch = ValenQwen.forward_batch + score_features = ValenQwen.score_features + + def make_compiler(self, media_root=".", execution=None, processor=None): + if processor is None: + if self._processor is None: + self._processor = AutoProcessor.from_pretrained(self.config._name_or_path, trust_remote_code=True) + processor = self._processor + return Compiler(processor, media_root, self.config.valen_max_length, self.config.valen_media_kwargs, + execution=execution or self.config.qwen_execution) + + @torch.inference_mode() + def predict(self, request, *, media_root=".", execution=None, temperature=1.0, processor=None): + self.eval() + # Only request content reaches the compiler. / 只编译输入,不读取标签。 + request = request["request"] if "request" in request else request + compiler = self.make_compiler(media_root, execution, processor) + state = compiler.compile({"request": request}) + logits = self.forward_state(state) if state.inputs is not None else [self(q) for q in state.questions] + answers = {q.qid: answer(q, z, temperature[q.kind] if isinstance(temperature, dict) else temperature) + for q, z in zip(state.questions, logits)} + return {"model": self.model_name, "answers": answers, + "usage": {"input_tokens": state.logical_tokens, "output_tokens": 0}, + "internal_usage": {"compute_tokens": state.compute_tokens}} diff --git a/processor_config.json b/processor_config.json new file mode 100644 index 0000000000000000000000000000000000000000..33818c7f9e991ad735fd240209f4fa73e6c28c50 --- /dev/null +++ b/processor_config.json @@ -0,0 +1,60 @@ +{ + "image_processor": { + "do_convert_rgb": true, + "do_normalize": true, + "do_rescale": true, + "do_resize": true, + "image_mean": [ + 0.5, + 0.5, + 0.5 + ], + "image_processor_type": "Qwen2VLImageProcessor", + "image_std": [ + 0.5, + 0.5, + 0.5 + ], + "merge_size": 2, + "patch_size": 16, + "resample": 3, + "rescale_factor": 0.00392156862745098, + "size": { + "longest_edge": 16777216, + "shortest_edge": 65536 + }, + "temporal_patch_size": 2 + }, + "processor_class": "Qwen3VLProcessor", + "video_processor": { + "do_convert_rgb": true, + "do_normalize": true, + "do_rescale": true, + "do_resize": true, + "do_sample_frames": true, + "fps": 2, + "image_mean": [ + 0.5, + 0.5, + 0.5 + ], + "image_std": [ + 0.5, + 0.5, + 0.5 + ], + "max_frames": 768, + "merge_size": 2, + "min_frames": 4, + "patch_size": 16, + "resample": 3, + "rescale_factor": 0.00392156862745098, + "return_metadata": false, + "size": { + "longest_edge": 25165824, + "shortest_edge": 4096 + }, + "temporal_patch_size": 2, + "video_processor_type": "Qwen3VLVideoProcessor" + } +} diff --git a/responses.py b/responses.py new file mode 100644 index 0000000000000000000000000000000000000000..fb4398970a9fd3827c185269a2cfa97cc78d755f --- /dev/null +++ b/responses.py @@ -0,0 +1,29 @@ +import math +import torch + +def answer(question, logits, temperature=1.0): + if not math.isfinite(temperature) or temperature <= 0: + raise ValueError("Calibration temperature must be finite and positive") + if logits.ndim != 1 or len(logits) != len(question.keys) or not torch.isfinite(logits).all(): + raise ValueError("Expected one finite logit per candidate") + probs = (logits.float() / temperature).softmax(-1).detach().cpu().tolist() + total = sum(probs) + probs = [p / total for p in probs] + result = {"type": question.kind} + if question.kind == "noul": + result["noul"] = probs[question.keys.index("true")] + return result + result["probabilities"] = dict(zip(question.keys, probs)) + mode = max(range(len(probs)), key=probs.__getitem__) + if question.kind == "choice": + result["choice"] = question.keys[mode] + result["confidence"] = 1.0 if len(probs) == 1 else max(0.0, (max(probs) - 1/len(probs)) / (1 - 1/len(probs))) + else: + result["score"] = sum(i * p for i, p in enumerate(probs)) + result["legend"] = dict(zip(question.keys, question.descriptions)) + # Independently implemented formula from pinned system-one adapter: + # fb52b1030b7fc1f4f1cf39910afa5da54f9835e3, confidence_metrics.py. + distance = sum(p * abs(i - mode) for i, p in enumerate(probs)) + uniform_mad = sum(abs(i - (len(probs)-1)/2) for i in range(len(probs))) / len(probs) + result["confidence"] = max(0.0, 1.0 - distance / uniform_mad) + return result diff --git a/runtime_model.py b/runtime_model.py new file mode 100644 index 0000000000000000000000000000000000000000..38f601b00ea984e6e0f221dfcbd106aa8ed7d775 --- /dev/null +++ b/runtime_model.py @@ -0,0 +1,101 @@ +import torch +from torch import nn +MODEL_NAME = "Valen" +from .heads import DecisionHead, build_head +from .batching import branch_batches, collate_branches + + +class ValenQwen(nn.Module): + """Qwen3.5 backbone with a shared candidate decision head.""" + + model_name = MODEL_NAME + architecture = "qwen" + + def __init__(self, backbone, projection_dim=256, head_config=None): + super().__init__() + self.backbone = backbone + self.head = build_head(backbone.config.text_config.hidden_size, + dict({"projection_dim": projection_dim}, **(head_config or {}))) + + def forward(self, question): + device = next(self.backbone.parameters()).device + outputs = [] + for branch in question.branches: + inputs = {k: v.to(device) if isinstance(v, torch.Tensor) else v for k, v in branch.inputs.items()} + hidden = self.backbone(**inputs, use_cache=False, return_dict=True).last_hidden_state + outputs.append(self.head.score_features(self.head.extract_features(hidden, branch))) + return torch.cat(outputs) + + def extract_features(self, question): + """缓存投影前的特征。 / Cache raw readouts before trainable head layers.""" + device = next(self.backbone.parameters()).device + features = [] + for branch in question.branches: + inputs = {k: v.to(device) if isinstance(v, torch.Tensor) else v for k, v in branch.inputs.items()} + hidden = self.backbone(**inputs, use_cache=False, return_dict=True).last_hidden_state + features.append(self.head.extract_features(hidden, branch)) + return features + + def extract_state_features(self, state): + """一次编码 state,读取各题特征。 / One backbone graph for every question.""" + if not state.questions: + return [] + if state.inputs is None: + raise ValueError("Shared-state features require compiled shared inputs") + device = next(self.backbone.parameters()).device + inputs = {k: v.to(device) if isinstance(v, torch.Tensor) else v for k, v in state.inputs.items()} + hidden = self.backbone(**inputs, use_cache=False, return_dict=True).last_hidden_state + return self._state_features(hidden, state) + + def _state_features(self, hidden, state): + return [[self.head.extract_features(hidden, branch) for branch in q.branches] + for q in state.questions] + + def forward_state(self, state): + return [self.score_features(features) for features in self.extract_state_features(state)] + + def forward_state_batch(self, states, max_tokens=32768): + """不同 state 组成 batch,同一 state 的题目共用一行。 / One row per shared state.""" + device = next(self.backbone.parameters()).device + pad_token_id = getattr(self.backbone.config.text_config, "pad_token_id", None) or 0 + outputs = [[] for _ in states] + representatives = [] + indices = [] + for index, state in enumerate(states): + if not state.questions: + continue + if state.inputs is None or any(branch.inputs is not state.inputs + for q in state.questions for branch in q.branches): + raise ValueError("Shared-state batch requires one shared input per state") + representatives.append(state.questions[0]) + indices.append(index) + for batch in branch_batches(representatives, max_tokens): + inputs = collate_branches([branch for _, branch in batch], pad_token_id) + inputs = {key: value.to(device) for key, value in inputs.items()} + hidden = self.backbone(**inputs, use_cache=False, return_dict=True).last_hidden_state + for row, (index, _) in enumerate(batch): + original = indices[index] + features = self._state_features(hidden[row:row + 1], states[original]) + outputs[original] = [self.score_features(f) for f in features] + return outputs + + def forward_batch(self, questions, max_tokens=32768): + """Forward several QAs together; each keeps its own decision head inputs. + + 多条 QA 并行;每条保留独立的候选、角色区间和 Score 分支。 + """ + device = next(self.backbone.parameters()).device + pad_token_id = getattr(self.backbone.config.text_config, "pad_token_id", None) or 0 + outputs = [[] for _ in questions] + for batch in branch_batches(questions, max_tokens): + inputs = collate_branches([branch for _, branch in batch], pad_token_id) + inputs = {key: value.to(device) for key, value in inputs.items()} + hidden = self.backbone(**inputs, use_cache=False, return_dict=True).last_hidden_state + for row, (question_index, branch) in enumerate(batch): + features = self.head.extract_features(hidden[row:row + 1], branch) + outputs[question_index].append(self.head.score_features(features)) + return [torch.cat(branches) for branches in outputs] + + def score_features(self, features, head=None): + head = self.head if head is None else head + return torch.cat([head.score_features(hidden) for hidden in features]) diff --git a/schema.py b/schema.py new file mode 100644 index 0000000000000000000000000000000000000000..f3c3483045739bd5e38210e4a1ac32d13db44b07 --- /dev/null +++ b/schema.py @@ -0,0 +1,71 @@ +"""Strict JSONL contract. IDs and labels never enter the model prompt.""" +import json +import math +from pathlib import Path + + +def candidates(question): + kind = question.get("type") + if not isinstance(question.get("instructions"), str) or not question["instructions"].strip(): + raise ValueError("instructions must be nonempty text") + criteria = question.get("criteria") + if kind == "noul": + return [("true", "True / 是:满足问题中的条件。"), ("false", "False / 否:不满足问题中的条件。")] + if kind == "choice": + if not isinstance(criteria, dict) or not 1 <= len(criteria) <= 255: + raise ValueError("Choice needs 1–255 named criteria") + result = list(criteria.items()) + elif kind == "score": + if not isinstance(criteria, list) or not 2 <= len(criteria) <= 255: + raise ValueError("Score criteria must be an ordered list of 2–255 descriptions") + result = [(str(i), text) for i, text in enumerate(criteria)] + else: + raise ValueError(f"Unsupported question type: {kind}") + if any(not isinstance(k, str) or not k or not isinstance(v, str) or not v.strip() for k, v in result): + raise ValueError("Candidate names and descriptions must be nonempty strings") + return result + + +def target_distribution(target, keys): + if target is None or target.get("probabilities") is None: + return None + probs = target["probabilities"] + if not isinstance(probs, dict) or set(probs) != set(keys): + raise ValueError(f"Probability keys must exactly match {keys}") + values = [probs[k] for k in keys] + if any(isinstance(v, bool) or not isinstance(v, (int, float)) or not math.isfinite(v) or v < 0 for v in values): + raise ValueError("Probabilities must be finite nonnegative numbers") + if not math.isclose(sum(values), 1.0, abs_tol=1e-6): + raise ValueError("Target probabilities must sum to 1") + return values + + +def validate_record(record, candidate_fn=candidates): + request = record["request"] + state = request["state"] + if not isinstance(state, (str, dict)): + raise ValueError("state must be text or a messages object") + if not isinstance(request["questions"], dict) or not request["questions"]: + raise ValueError("questions must be a nonempty mapping") + targets = record.get("targets", {}) + if set(targets) - set(request["questions"]): + raise ValueError("Unknown target question IDs") + for qid, question in request["questions"].items(): + target_distribution(targets.get(qid), [k for k, _ in candidate_fn(question)]) + if not record.get("group_id"): + raise ValueError("group_id is required for leakage-free splits") + return record + + +def read_jsonl(path, candidate_fn=candidates): + records = [] + with Path(path).open(encoding="utf-8") as stream: + for line_number, line in enumerate(stream, 1): + if line.strip(): + try: + records.append(validate_record(json.loads(line), candidate_fn)) + except (ValueError, KeyError, TypeError, AttributeError) as exc: + raise ValueError(f"{path}:{line_number}: {exc}") from exc + if not records: + raise ValueError("Empty dataset") + return records diff --git a/tokenizer.json b/tokenizer.json new file mode 100644 index 0000000000000000000000000000000000000000..67741b04f23bfdb46501f748ce27865ec82eccfb --- /dev/null +++ b/tokenizer.json @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87a7830d63fcf43bf241c3c5242e96e62dd3fdc29224ca26fed8ea333db72de4 +size 19989343 diff --git a/tokenizer_config.json b/tokenizer_config.json new file mode 100644 index 0000000000000000000000000000000000000000..a068e2468cff426a9b105006e74e044030a6faf4 --- /dev/null +++ b/tokenizer_config.json @@ -0,0 +1,32 @@ +{ + "add_prefix_space": false, + "audio_bos_token": "<|audio_start|>", + "audio_eos_token": "<|audio_end|>", + "audio_token": "<|audio_pad|>", + "backend": "tokenizers", + "bos_token": null, + "clean_up_tokenization_spaces": false, + "eos_token": "<|im_end|>", + "errors": "replace", + "image_token": "<|image_pad|>", + "is_local": true, + "model_max_length": 262144, + "model_specific_special_tokens": { + "audio_bos_token": "<|audio_start|>", + "audio_eos_token": "<|audio_end|>", + "audio_token": "<|audio_pad|>", + "image_token": "<|image_pad|>", + "video_token": "<|video_pad|>", + "vision_bos_token": "<|vision_start|>", + "vision_eos_token": "<|vision_end|>" + }, + "pad_token": "<|endoftext|>", + "pretokenize_regex": "(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\\r\\n\\p{L}\\p{N}]?[\\p{L}\\p{M}]+|\\p{N}| ?[^\\s\\p{L}\\p{M}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+", + "processor_class": "Qwen3VLProcessor", + "split_special_tokens": false, + "tokenizer_class": "TokenizersBackend", + "unk_token": null, + "video_token": "<|video_pad|>", + "vision_bos_token": "<|vision_start|>", + "vision_eos_token": "<|vision_end|>" +} diff --git a/unmerged/COMPLETE.json b/unmerged/COMPLETE.json new file mode 100644 index 0000000000000000000000000000000000000000..fa8551c9df5becfed54eaa655087f9a246bbd15b --- /dev/null +++ b/unmerged/COMPLETE.json @@ -0,0 +1,4 @@ +{ + "validated": true, + "source_checkpoint_sha256": "b4193b4e907f44b913fd54a8d6b998e7050a1528306269a000f1e5e8bd8dffc7" +} diff --git a/unmerged/LICENSE b/unmerged/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..f938136e3adacfd92be087f6e113b5d6d97f678f --- /dev/null +++ b/unmerged/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 Alibaba Cloud + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/unmerged/README.md b/unmerged/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f24c93ea49804cfcded2f7e6874f7f8cba5217a0 --- /dev/null +++ b/unmerged/README.md @@ -0,0 +1,50 @@ +# Valen-4B — unmerged LoRA + +原始 Qwen3.5 基座 + 未合并的 LoRA + FP32 Mixer + 训练后的视觉 merger。 +Original base with separate LoRA, Mixer, and trained visual merger weights. +来源:1195k + JevBench 30k,两阶段 SFT,最终 step 325。 + +## 文件 / Files + +- `lora/adapter_model.safetensors`、`lora/adapter_config.json`:标准 PEFT LoRA。 +- `mixer.safetensors`:完整 FP32 Mixer 决策头。 +- `visual_merger.safetensors`:联合微调时训练的视觉 merger,加载时一并恢复。 +- `config.json`、processor、tokenizer 和 Python 文件:模型配置及独立加载代码。 + +## 完整模型加载 / Load the complete decision model + +环境沿用父目录:PyTorch 2.6.0、Transformers 5.4.0,另需 PEFT 0.18.1 和 safetensors。 +Flash Attention 2 可通过 `attn_implementation="flash_attention_2"` 启用。 + +```python +import torch +from transformers import AutoModel + +model = AutoModel.from_pretrained( + "./Valen-4B/unmerged", + base_model_path="./Qwen3.5-4B", # 原始官方基座 / original published base + trust_remote_code=True, + dtype=torch.bfloat16, + attn_implementation="sdpa", +).to("cuda").eval() +torch.set_float32_matmul_precision("highest") +torch.backends.cudnn.allow_tf32 = False + +result = model.predict({ + "state": "There is one cat in the room.", + "questions": { + "animal": {"type": "choice", "instructions": "Which animal is present?", + "criteria": {"cat": "A cat", "dog": "A dog"}}, + "is_cat": {"type": "noul", "instructions": "There is a cat in the room."}, + }, +}) +print(result["answers"]) +``` + +`base_model_path` 指向原始官方 `Qwen/Qwen3.5-4B` 权重,本目录中的加载器会核对基座 SHA-256。 +省略该参数时使用配置记录的仓库及固定 revision;离线环境需提前缓存该版本。 +默认 share_state,也支持 `model.predict(..., execution="question")`;视频采样 16 帧。 +内部使用 `PeftModel.from_pretrained(backbone.language_model, .../lora)` 加载语言 LoRA,随后恢复 Mixer 和视觉 merger。 +适配器不会被融合。`is_trainable=True` 可启用 LoRA、Mixer 和视觉 merger 的梯度。 + +`validation.json` 记录恢复后与原 checkpoint 的一致性;文件来源和校验和见 `export_manifest.json`。 diff --git a/unmerged/batching.py b/unmerged/batching.py new file mode 100644 index 0000000000000000000000000000000000000000..6bd343e1d7a8479c6bbc45d73b987b1d1d2d5c28 --- /dev/null +++ b/unmerged/batching.py @@ -0,0 +1,62 @@ +"""Pad language rows and concatenate visual patches. / 文本补齐,视觉 patch 拼接。""" +import torch +from torch.nn.utils.rnn import pad_sequence + + +SEQUENCE_KEYS = {"input_ids", "attention_mask", "mm_token_type_ids"} +VISUAL_KEYS = {"pixel_values", "pixel_values_videos", "image_grid_thw", "video_grid_thw"} + + +def collate_branches(branches, pad_token_id=0): + if not branches: + raise ValueError("Cannot collate an empty branch batch") + inputs = [branch.inputs for branch in branches] + unknown = set().union(*(row.keys() for row in inputs)) - SEQUENCE_KEYS - VISUAL_KEYS + if unknown: + raise ValueError(f"Unsupported batched Qwen inputs: {sorted(unknown)}") + if any(row["input_ids"].ndim != 2 or row["input_ids"].shape[0] != 1 for row in inputs): + raise ValueError("Each compiled branch must contain one language row") + result = {} + for key in SEQUENCE_KEYS: + if key != "input_ids" and not any(key in row for row in inputs): + continue + rows = [] + for row in inputs: + value = row.get(key) + if value is None: + value = (torch.ones_like(row["input_ids"]) if key == "attention_mask" + else torch.zeros_like(row["input_ids"])) + if value.shape != row["input_ids"].shape: + raise ValueError(f"{key} must match the branch input_ids shape") + rows.append(value[0]) + # Right padding keeps all compiler readout positions and spans unchanged. + # 右侧补齐,候选位置和角色区间无需偏移。 + result[key] = pad_sequence(rows, batch_first=True, + padding_value=pad_token_id if key == "input_ids" else 0) + if "attention_mask" not in result: + result["attention_mask"] = pad_sequence([torch.ones_like(r["input_ids"][0]) for r in inputs], + batch_first=True, padding_value=0) + for key in VISUAL_KEYS: + values = [row[key] for row in inputs if key in row] + if values: + result[key] = torch.cat(values, dim=0) + return result + + +def branch_batches(questions, max_tokens): + """Limit padded tokens per backbone forward, keeping Score branch order.""" + if type(max_tokens) is not int or max_tokens <= 0: + raise ValueError("microbatch_max_tokens must be a positive integer") + batch, longest = [], 0 + for question_index, question in enumerate(questions): + if not question.branches: + raise ValueError("A Qwen question requires at least one branch") + for branch in question.branches: + length = branch.inputs["input_ids"].shape[1] + if batch and max(longest, length) * (len(batch) + 1) > max_tokens: + yield batch + batch, longest = [], 0 + batch.append((question_index, branch)) + longest = max(longest, length) + if batch: + yield batch diff --git a/unmerged/chat_template.jinja b/unmerged/chat_template.jinja new file mode 100644 index 0000000000000000000000000000000000000000..a585dec894e63da457d9440ec6aa7caa16d20860 --- /dev/null +++ b/unmerged/chat_template.jinja @@ -0,0 +1,154 @@ +{%- set image_count = namespace(value=0) %} +{%- set video_count = namespace(value=0) %} +{%- macro render_content(content, do_vision_count, is_system_content=false) %} + {%- if content is string %} + {{- content }} + {%- elif content is iterable and content is not mapping %} + {%- for item in content %} + {%- if 'image' in item or 'image_url' in item or item.type == 'image' %} + {%- if is_system_content %} + {{- raise_exception('System message cannot contain images.') }} + {%- endif %} + {%- if do_vision_count %} + {%- set image_count.value = image_count.value + 1 %} + {%- endif %} + {%- if add_vision_id %} + {{- 'Picture ' ~ image_count.value ~ ': ' }} + {%- endif %} + {{- '<|vision_start|><|image_pad|><|vision_end|>' }} + {%- elif 'video' in item or item.type == 'video' %} + {%- if is_system_content %} + {{- raise_exception('System message cannot contain videos.') }} + {%- endif %} + {%- if do_vision_count %} + {%- set video_count.value = video_count.value + 1 %} + {%- endif %} + {%- if add_vision_id %} + {{- 'Video ' ~ video_count.value ~ ': ' }} + {%- endif %} + {{- '<|vision_start|><|video_pad|><|vision_end|>' }} + {%- elif 'text' in item %} + {{- item.text }} + {%- else %} + {{- raise_exception('Unexpected item type in content.') }} + {%- endif %} + {%- endfor %} + {%- elif content is none or content is undefined %} + {{- '' }} + {%- else %} + {{- raise_exception('Unexpected content type.') }} + {%- endif %} +{%- endmacro %} +{%- if not messages %} + {{- raise_exception('No messages provided.') }} +{%- endif %} +{%- if tools and tools is iterable and tools is not mapping %} + {{- '<|im_start|>system\n' }} + {{- "# Tools\n\nYou have access to the following functions:\n\n" }} + {%- for tool in tools %} + {{- "\n" }} + {{- tool | tojson }} + {%- 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' }} + {%- if messages[0].role == 'system' %} + {%- set content = render_content(messages[0].content, false, true)|trim %} + {%- if content %} + {{- '\n\n' + content }} + {%- endif %} + {%- endif %} + {{- '<|im_end|>\n' }} +{%- else %} + {%- if messages[0].role == 'system' %} + {%- set content = render_content(messages[0].content, false, true)|trim %} + {{- '<|im_start|>system\n' + content + '<|im_end|>\n' }} + {%- endif %} +{%- endif %} +{%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %} +{%- for message in messages[::-1] %} + {%- set index = (messages|length - 1) - loop.index0 %} + {%- if ns.multi_step_tool and message.role == "user" %} + {%- set content = render_content(message.content, false)|trim %} + {%- if not(content.startswith('') and content.endswith('')) %} + {%- set ns.multi_step_tool = false %} + {%- set ns.last_query_index = index %} + {%- endif %} + {%- endif %} +{%- endfor %} +{%- if ns.multi_step_tool %} + {{- raise_exception('No user query found in messages.') }} +{%- endif %} +{%- for message in messages %} + {%- set content = render_content(message.content, true)|trim %} + {%- if message.role == "system" %} + {%- if not loop.first %} + {{- raise_exception('System message must be at the beginning.') }} + {%- endif %} + {%- elif message.role == "user" %} + {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }} + {%- elif message.role == "assistant" %} + {%- set reasoning_content = '' %} + {%- if message.reasoning_content is string %} + {%- set reasoning_content = message.reasoning_content %} + {%- else %} + {%- if '' in content %} + {%- set reasoning_content = content.split('')[0].rstrip('\n').split('')[-1].lstrip('\n') %} + {%- set content = content.split('')[-1].lstrip('\n') %} + {%- endif %} + {%- endif %} + {%- set reasoning_content = reasoning_content|trim %} + {%- if loop.index0 > ns.last_query_index %} + {{- '<|im_start|>' + message.role + '\n\n' + reasoning_content + '\n\n\n' + content }} + {%- else %} + {{- '<|im_start|>' + message.role + '\n' + content }} + {%- endif %} + {%- if message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %} + {%- for tool_call in message.tool_calls %} + {%- if tool_call.function is defined %} + {%- set tool_call = tool_call.function %} + {%- endif %} + {%- if loop.first %} + {%- if content|trim %} + {{- '\n\n\n\n' }} + {%- else %} + {{- '\n\n' }} + {%- endif %} + {%- else %} + {{- '\n\n\n' }} + {%- endif %} + {%- 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 %} + {%- endif %} + {{- '<|im_end|>\n' }} + {%- elif message.role == "tool" %} + {%- if loop.previtem and loop.previtem.role != "tool" %} + {{- '<|im_start|>user' }} + {%- endif %} + {{- '\n\n' }} + {{- content }} + {{- '\n' }} + {%- if not loop.last and loop.nextitem.role != "tool" %} + {{- '<|im_end|>\n' }} + {%- elif loop.last %} + {{- '<|im_end|>\n' }} + {%- endif %} + {%- else %} + {{- raise_exception('Unexpected message role.') }} + {%- endif %} +{%- endfor %} +{%- if add_generation_prompt %} + {{- '<|im_start|>assistant\n' }} + {%- if enable_thinking is defined and enable_thinking is false %} + {{- '\n\n\n\n' }} + {%- else %} + {{- '\n' }} + {%- endif %} +{%- endif %} \ No newline at end of file diff --git a/unmerged/compiler.py b/unmerged/compiler.py new file mode 100644 index 0000000000000000000000000000000000000000..a5b9fe08e2cc9cd8564d6325211bf10ebf789089 --- /dev/null +++ b/unmerged/compiler.py @@ -0,0 +1,239 @@ +"""Compile Qwen question branches or a shared sequence with per-question readouts.""" +from copy import deepcopy +from dataclasses import dataclass +from pathlib import Path +import hashlib +import torch +from .schema import candidates, target_distribution +from .data_types import QuestionSpec + + +@dataclass +class Branch: + inputs: dict + candidate_positions: list + decision_position: int + context_span: tuple | None = None + instruction_span: tuple | None = None + candidate_spans: list | None = None + + +@dataclass(init=False) +class Question(QuestionSpec): + branches: list + + def __init__(self, qid, kind, keys, descriptions, branches, target, is_text): + # Keep the positional constructor used by existing compiler clients. + super().__init__(qid, kind, keys, descriptions, target, is_text) + self.branches = branches + + +@dataclass +class CompiledState: + questions: list + logical_tokens: int + compute_tokens: int + media: list + inputs: dict | None = None + + +class Compiler: + def __init__(self, processor, media_root=".", max_length=8192, media_kwargs=None, verified_media_hashes=None, + execution="question"): + if execution not in {"question", "shared_state"}: + raise ValueError(f"Unknown qwen_execution: {execution}") + self.execution = execution + self.processor = processor + self.tokenizer = processor.tokenizer + self.media_root = Path(media_root) + self.max_length = max_length + self.media_kwargs = media_kwargs or {} + # Optional, pre-audited immutable assets for latency measurements. + # Normal training/inference continues to hash each input at use time. + self.verified_media_hashes = verified_media_hashes or {} + + def _messages(self, state): + messages = [{"role": "user", "content": state}] if isinstance(state, str) else deepcopy(state["messages"]) + media = [] + for message in messages: + if message["role"] not in {"user", "assistant", "system"}: + raise ValueError("Unsupported state role") + if isinstance(message["content"], str): + message["content"] = [{"type": "text", "text": message["content"]}] + for item in message["content"]: + kind = item["type"] + if kind == "text": + # Prevent user text from injecting Qwen control tokens. + if any(t in item["text"] for t in self.tokenizer.all_special_tokens): + raise ValueError("Reserved tokenizer control token in state") + continue + if kind not in {"image_url", "video_url"}: + raise ValueError(f"Unsupported content type: {kind}") + url = item[kind]["url"] + if "://" in url: + raise ValueError("Materialize remote media locally with a hash before training") + path = Path(url) + path = path if path.is_absolute() else self.media_root / path + path = path.resolve(strict=True) + digest = self.verified_media_hashes.get(str(path)) + if digest is None: + digest = hashlib.sha256(path.read_bytes()).hexdigest() + media.append({"path": str(path), "sha256": digest, "type": kind}) + item.clear() + item.update(type=kind.removesuffix("_url"), path=str(path)) + return messages, media + + def compile(self, record, rng=None, labeled_only=False): + selected = [] + for qid, question in record["request"]["questions"].items(): + pairs = candidates(question) + target = record.get("targets", {}).get(qid) + if labeled_only and self.execution == "question" and target_distribution(target, [k for k, _ in pairs]) is None: + continue + if rng is not None and question["type"] == "choice": + rng.shuffle(pairs) + selected.append((qid, question, pairs, target)) + # 标签只决定监督范围,共享序列仍保留所有题。 / Labels select losses, never prompt content. + if not selected or (labeled_only and not any( + target_distribution(target, [k for k, _ in pairs]) is not None + for _, _, pairs, target in selected)): + return CompiledState([], 0, 0, []) + messages, media = self._messages(record["request"]["state"]) + expected_assets = {str((self.media_root / a["path"]).resolve()): a["sha256"] for a in record.get("assets", [])} + for entry in media: + if entry["path"] in expected_assets and expected_assets[entry["path"]] != entry["sha256"]: + raise ValueError(f"Media hash mismatch: {entry['path']}") + base = dict(self.processor.apply_chat_template( + messages, tokenize=True, add_generation_prompt=False, return_dict=True, + return_tensors="pt", processor_kwargs=dict(self.media_kwargs, return_metadata=True))) + # Metadata is audit information, never a backbone keyword argument. + metadata = base.pop("video_metadata", None) + if metadata is not None: + for entry, meta in zip([m for m in media if m["type"] == "video_url"], metadata): + entry["sampling"] = dict(meta) if isinstance(meta, dict) else vars(meta) + sampling = entry["sampling"] + indices = sampling.get("frames_indices") + if indices is not None and sampling.get("fps"): + sampling["frames_indices"] = [int(i) for i in indices] + sampling["timestamps_seconds"] = [int(i) / sampling["fps"] for i in indices] + sampling["visible_range_seconds"] = [min(sampling["timestamps_seconds"]), max(sampling["timestamps_seconds"])] + for name in ("image_grid_thw", "video_grid_thw"): + if name in base: + grid = base[name] + media.append({name: grid.tolist(), "visual_tokens": int(grid.prod(-1).sum()) // 4}) + base_length = base["input_ids"].shape[1] + if self.execution == "shared_state": + return self._compile_shared(selected, base, media, labeled_only) + logical_tokens, compute_tokens = base_length, 0 + compiled = [] + for qid, question, pairs, target in selected: + keys = [k for k, _ in pairs] + branches = [] + groups = [[pair] for pair in pairs] if question["type"] == "score" else [pairs] + for group in groups: + suffix = [] + def append(text, char_span=None): + start = base_length + len(suffix) + if char_span is None: + suffix.extend(self.tokenizer.encode(text, add_special_tokens=False)) + return None + # 保持原有分词,只额外记录区间。 / Preserve token IDs; record role spans. + encoded = self.tokenizer(text, add_special_tokens=False, return_offsets_mapping=True) + suffix.extend(encoded["input_ids"]) + indices = [i for i, (a, b) in enumerate(encoded["offset_mapping"]) + if a < char_span[1] and b > char_span[0]] + if not indices: + raise ValueError("Empty token span for decision role") + return (start + indices[0], start + indices[-1] + 1) + # Canonical segment tokenization makes endpoints exact; no string searching. + suffix.extend(self.tokenizer.encode("<|im_start|>user\n", add_special_tokens=False)) + for value in [question["instructions"]] + [v for pair in group for v in pair]: + if any(t in value for t in self.tokenizer.all_special_tokens): + raise ValueError("Reserved tokenizer control token in question/criteria") + prefix = "Task: " + question["type"] + "\nQuestion: " + instruction_span = append(prefix + question["instructions"] + "\nCandidates:\n", + (len(prefix), len(prefix) + len(question["instructions"]))) + positions, candidate_spans = [], [] + for key, description in group: + # Score never sees its level ID, nor any other level description. + prefix = key + ": " if question["type"] != "score" else "" + candidate_spans.append(append(prefix + description, (len(prefix), len(prefix) + len(description)))) + positions.append(base_length + len(suffix) - 1) + append("\n") + append("Decision:") + length = base_length + len(suffix) + if length > self.max_length: + raise ValueError(f"{qid}: {length} tokens exceed max_length={self.max_length}; no truncation") + inputs = dict(base) + inputs["input_ids"] = torch.cat([base["input_ids"], torch.tensor([suffix], dtype=torch.long)], dim=1) + inputs["attention_mask"] = torch.ones_like(inputs["input_ids"]) + if "mm_token_type_ids" in base: + inputs["mm_token_type_ids"] = torch.cat([base["mm_token_type_ids"], torch.zeros((1, len(suffix)), dtype=torch.long)], dim=1) + branches.append(Branch(inputs, positions, length - 1, (0, base_length), + instruction_span, candidate_spans)) + compute_tokens += length + logical_tokens += len(suffix) + compiled.append(Question(qid, question["type"], keys, [v for _, v in pairs], branches, + target_distribution(target, keys), not media)) + return CompiledState(compiled, logical_tokens, compute_tokens, media) + + def _compile_shared(self, selected, base, media, labeled_only=False): + """All schemas precede all readouts; labels and external IDs never enter inputs. + + This is ordinary causal attention, not isolated question/Score branches. + No answer tokens or LM output layer are required by the decision heads. + """ + base_length = base["input_ids"].shape[1] + suffix, compiled = [], [] + + def append(text, span=None): + start = base_length + len(suffix) + if span is None: + suffix.extend(self.tokenizer.encode(text, add_special_tokens=False)) + return None + encoded = self.tokenizer(text, add_special_tokens=False, return_offsets_mapping=True) + suffix.extend(encoded["input_ids"]) + indices = [i for i, (a, b) in enumerate(encoded["offset_mapping"]) if a < span[1] and b > span[0]] + if not indices: + raise ValueError("Empty token span for decision role") + return start + indices[0], start + indices[-1] + 1 + + append("<|im_start|>user\n") + for index, (qid, question, pairs, target) in enumerate(selected): + for value in [question["instructions"]] + [v for pair in pairs for v in pair]: + if any(t in value for t in self.tokenizer.all_special_tokens): + raise ValueError("Reserved tokenizer control token in question/criteria") + prefix = f"Question {index + 1}\nTask: {question['type']}\nQuestion: " + instruction = append(prefix + question["instructions"] + "\nCandidates:\n", + (len(prefix), len(prefix) + len(question["instructions"]))) + positions, spans = [], [] + for key, description in pairs: + prefix = key + ": " if question["type"] != "score" else "" + spans.append(append(prefix + description, (len(prefix), len(prefix) + len(description)))) + positions.append(base_length + len(suffix) - 1) + append("\n") + # Inputs and the decision position are filled after all schemas are appended. + branch = Branch({}, positions, -1, (0, base_length), instruction, spans) + keys = [key for key, _ in pairs] + compiled.append(Question(qid, question["type"], keys, [v for _, v in pairs], [branch], + target_distribution(target, keys), not media)) + append("<|im_end|>\n<|im_start|>assistant\n") + for index, question in enumerate(compiled): + append(f"Question {index + 1} Decision:") + question.branches[0].decision_position = base_length + len(suffix) - 1 + append("\n") + length = base_length + len(suffix) + if length > self.max_length: + raise ValueError(f"Shared state: {length} tokens exceed max_length={self.max_length}; no truncation") + inputs = dict(base) + inputs["input_ids"] = torch.cat([base["input_ids"], base["input_ids"].new_tensor([suffix])], dim=1) + inputs["attention_mask"] = torch.cat([base["attention_mask"], + base["attention_mask"].new_ones((1, len(suffix)))], dim=1) + if "mm_token_type_ids" in base: + inputs["mm_token_type_ids"] = torch.cat([base["mm_token_type_ids"], + base["mm_token_type_ids"].new_zeros((1, len(suffix)))], dim=1) + for question in compiled: + question.branches[0].inputs = inputs + if labeled_only: + compiled = [question for question in compiled if question.target is not None] + return CompiledState(compiled, length, length, media, inputs) diff --git a/unmerged/config.json b/unmerged/config.json new file mode 100644 index 0000000000000000000000000000000000000000..7c80462e381738b1fdef603716657e6bbb6943da --- /dev/null +++ b/unmerged/config.json @@ -0,0 +1,163 @@ +{ + "architectures": [ + "ValenQwenWithLoRA" + ], + "auto_map": { + "AutoConfig": "configuration_valen.ValenQwenConfig", + "AutoModel": "modeling_valen_lora.ValenQwenWithLoRA" + }, + "dtype": "bfloat16", + "image_token_id": 248056, + "model_type": "valen_qwen", + "qwen_execution": "shared_state", + "text_config": { + "attention_bias": false, + "attention_dropout": 0.0, + "attn_output_gate": true, + "bos_token_id": null, + "dtype": "bfloat16", + "eos_token_id": 248044, + "full_attention_interval": 4, + "head_dim": 256, + "hidden_act": "silu", + "hidden_size": 2560, + "initializer_range": 0.02, + "intermediate_size": 9216, + "layer_types": [ + "linear_attention", + "linear_attention", + "linear_attention", + "full_attention", + "linear_attention", + "linear_attention", + "linear_attention", + "full_attention", + "linear_attention", + "linear_attention", + "linear_attention", + "full_attention", + "linear_attention", + "linear_attention", + "linear_attention", + "full_attention", + "linear_attention", + "linear_attention", + "linear_attention", + "full_attention", + "linear_attention", + "linear_attention", + "linear_attention", + "full_attention", + "linear_attention", + "linear_attention", + "linear_attention", + "full_attention", + "linear_attention", + "linear_attention", + "linear_attention", + "full_attention" + ], + "linear_conv_kernel_dim": 4, + "linear_key_head_dim": 128, + "linear_num_key_heads": 16, + "linear_num_value_heads": 32, + "linear_value_head_dim": 128, + "mamba_ssm_dtype": "float32", + "max_position_embeddings": 262144, + "mlp_only_layers": [], + "model_type": "qwen3_5_text", + "mtp_num_hidden_layers": 1, + "mtp_use_dedicated_embeddings": false, + "num_attention_heads": 16, + "num_hidden_layers": 32, + "num_key_value_heads": 4, + "pad_token_id": null, + "partial_rotary_factor": 0.25, + "rms_norm_eps": 1e-06, + "rope_parameters": { + "mrope_interleaved": true, + "mrope_section": [ + 11, + 11, + 10 + ], + "partial_rotary_factor": 0.25, + "rope_theta": 10000000, + "rope_type": "default" + }, + "tie_word_embeddings": true, + "use_cache": true, + "vocab_size": 248320 + }, + "tie_word_embeddings": true, + "transformers_version": "5.4.0", + "valen_head": { + "head_channel_hidden_dim": 1024, + "head_layers": 2, + "head_token_hidden_dim": 16, + "head_type": "mixer", + "head_width": 256 + }, + "valen_max_length": 32768, + "valen_media_kwargs": { + "images_kwargs": { + "size": { + "longest_edge": 262144, + "shortest_edge": 65536 + } + }, + "videos_kwargs": { + "fps": null, + "num_frames": 16, + "size": { + "longest_edge": 2097152, + "shortest_edge": 131072 + } + } + }, + "video_token_id": 248057, + "vision_config": { + "deepstack_visual_indexes": [], + "depth": 24, + "dtype": "bfloat16", + "hidden_act": "gelu_pytorch_tanh", + "hidden_size": 1024, + "in_channels": 3, + "initializer_range": 0.02, + "intermediate_size": 4096, + "model_type": "qwen3_5", + "num_heads": 16, + "num_position_embeddings": 2304, + "out_hidden_size": 2560, + "patch_size": 16, + "spatial_merge_size": 2, + "temporal_patch_size": 2 + }, + "vision_end_token_id": 248054, + "vision_start_token_id": 248053, + "valen_base": { + "repo": "Qwen/Qwen3.5-4B", + "revision": "851bf6e806efd8d0a36b00ddf55e13ccb7b8cd0a", + "weight_sha256": { + "model.safetensors-00001-of-00002.safetensors": "26a93f066e1916adb13453dae5a0c707c0fbc71299ed98779571a907b8e74c61", + "model.safetensors-00002-of-00002.safetensors": "cb544bd9bfae93dc59b0f22b292f5933573854a7f9b97835c67060d7d910e188" + }, + "files_sha256": { + ".gitattributes": "34448b82c17d60fec9b65b1f093c115ddbaadc04beb1b0140b6bfed2e012a930", + "LICENSE": "bbedc3fda3305820b977265f01b8619d87570a6739de3a5582c3464840f1e57a", + "README.md": "1406be1b6b8fd8a6545870da516912804756593628a1d0fb0a7965211e82a7bb", + "chat_template.jinja": "a4aee8afcf2e0711942cf848899be66016f8d14a889ff9ede07bca099c28f715", + "config.json": "ddc63e1c717afa86c865bb5e01313d89d72bb53b97ad4a8a03ba8510c0621670", + "merges.txt": "a9d356d7bdf1ef4949e3e748e95b8e10ad9d4e2e838eddc38a0a7b6b94d1db8d", + "model.safetensors-00001-of-00002.safetensors": "26a93f066e1916adb13453dae5a0c707c0fbc71299ed98779571a907b8e74c61", + "model.safetensors-00002-of-00002.safetensors": "cb544bd9bfae93dc59b0f22b292f5933573854a7f9b97835c67060d7d910e188", + "model.safetensors.index.json": "cf3f798ee02ba45f9622aa8892a47369ab667d0afbf154ee7c2212de42e6302d", + "preprocessor_config.json": "27225450ac9c6529872ee1924fcb0962ff5634834f817040f444118116f4e516", + "tokenizer.json": "5f9e4d4901a92b997e463c1f46055088b6cca5ca61a6522d1b9f64c4bb81cb42", + "tokenizer_config.json": "316230d6a809701f4db5ea8f8fc862bc3a6f3229c937c174e674ff3ca0a64ac8", + "video_preprocessor_config.json": "7768af27c1fafa9cc9011c1dc20067e03f8915e03b63504550e11d5066986d13", + "vocab.json": "ce99b4cb2983d118806ce0a8b777a35b093e2000a503ebde25853284c9dfa003" + }, + "verified_from": "download_manifest.json; every LFS SHA256 matched" + } +} diff --git a/unmerged/configuration_valen.py b/unmerged/configuration_valen.py new file mode 100644 index 0000000000000000000000000000000000000000..a9252326abac70b4afc90518b61999f6ff07284c --- /dev/null +++ b/unmerged/configuration_valen.py @@ -0,0 +1,16 @@ +"""Standalone Qwen decision configuration. / 独立的 Qwen 决策模型配置。""" +from transformers import Qwen3_5Config + + +class ValenQwenConfig(Qwen3_5Config): + model_type = "valen_qwen" + + def __init__(self, valen_head=None, qwen_execution="shared_state", valen_max_length=32768, + valen_media_kwargs=None, **kwargs): + if qwen_execution not in {"question", "shared_state"}: + raise ValueError("qwen_execution must be question or shared_state") + self.valen_head = valen_head or {"head_type": "mixer"} + self.qwen_execution = qwen_execution + self.valen_max_length = valen_max_length + self.valen_media_kwargs = valen_media_kwargs or {} + super().__init__(**kwargs) diff --git a/unmerged/data_types.py b/unmerged/data_types.py new file mode 100644 index 0000000000000000000000000000000000000000..ce1d6a8d6ee0f46600b13865ea941dcd7d803de0 --- /dev/null +++ b/unmerged/data_types.py @@ -0,0 +1,12 @@ +"""Model-independent decision metadata; encoded tensors stay with each compiler.""" +from dataclasses import dataclass + + +@dataclass +class QuestionSpec: + qid: str + kind: str + keys: list + descriptions: list + target: list | None + is_text: bool diff --git a/unmerged/export_manifest.json b/unmerged/export_manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..bbcca2d926f902cf47572cafe07f47e55def59c3 --- /dev/null +++ b/unmerged/export_manifest.json @@ -0,0 +1,68 @@ +{ + "format": "valen_qwen_unmerged_v1", + "created_utc": "2026-10-06T06:53:45.813755+00:00", + "model": "Valen-4B", + "source_checkpoint_sha256": "b4193b4e907f44b913fd54a8d6b998e7050a1528306269a000f1e5e8bd8dffc7", + "training_step": 325, + "training_records": 1225000, + "training_data_sha256": "648cb127fe4830f9faaa6d4595445cc2573ef0c152f8f74c9c776dc8a9223d7f", + "base": { + "repo": "Qwen/Qwen3.5-4B", + "revision": "851bf6e806efd8d0a36b00ddf55e13ccb7b8cd0a", + "weight_sha256": { + "model.safetensors-00001-of-00002.safetensors": "26a93f066e1916adb13453dae5a0c707c0fbc71299ed98779571a907b8e74c61", + "model.safetensors-00002-of-00002.safetensors": "cb544bd9bfae93dc59b0f22b292f5933573854a7f9b97835c67060d7d910e188" + }, + "files_sha256": { + ".gitattributes": "34448b82c17d60fec9b65b1f093c115ddbaadc04beb1b0140b6bfed2e012a930", + "LICENSE": "bbedc3fda3305820b977265f01b8619d87570a6739de3a5582c3464840f1e57a", + "README.md": "1406be1b6b8fd8a6545870da516912804756593628a1d0fb0a7965211e82a7bb", + "chat_template.jinja": "a4aee8afcf2e0711942cf848899be66016f8d14a889ff9ede07bca099c28f715", + "config.json": "ddc63e1c717afa86c865bb5e01313d89d72bb53b97ad4a8a03ba8510c0621670", + "merges.txt": "a9d356d7bdf1ef4949e3e748e95b8e10ad9d4e2e838eddc38a0a7b6b94d1db8d", + "model.safetensors-00001-of-00002.safetensors": "26a93f066e1916adb13453dae5a0c707c0fbc71299ed98779571a907b8e74c61", + "model.safetensors-00002-of-00002.safetensors": "cb544bd9bfae93dc59b0f22b292f5933573854a7f9b97835c67060d7d910e188", + "model.safetensors.index.json": "cf3f798ee02ba45f9622aa8892a47369ab667d0afbf154ee7c2212de42e6302d", + "preprocessor_config.json": "27225450ac9c6529872ee1924fcb0962ff5634834f817040f444118116f4e516", + "tokenizer.json": "5f9e4d4901a92b997e463c1f46055088b6cca5ca61a6522d1b9f64c4bb81cb42", + "tokenizer_config.json": "316230d6a809701f4db5ea8f8fc862bc3a6f3229c937c174e674ff3ca0a64ac8", + "video_preprocessor_config.json": "7768af27c1fafa9cc9011c1dc20067e03f8915e03b63504550e11d5066986d13", + "vocab.json": "ce99b4cb2983d118806ce0a8b777a35b093e2000a503ebde25853284c9dfa003" + }, + "verified_from": "download_manifest.json; every LFS SHA256 matched" + }, + "execution": "shared_state", + "trainable_tensor_count": 535, + "versions": { + "torch": "2.6.0", + "transformers": "5.4.0", + "peft": "0.18.1", + "safetensors": "0.6.2" + }, + "files_sha256": { + "LICENSE": "bbedc3fda3305820b977265f01b8619d87570a6739de3a5582c3464840f1e57a", + "README.md": "19dade0ed4951da63d3f556939f52d16e81d6a77fea4372816754824c52a3983", + "batching.py": "ea45d4724bcafca559fc5a2a18092918b633746771c19da6554c29bc5f2cef64", + "chat_template.jinja": "a4aee8afcf2e0711942cf848899be66016f8d14a889ff9ede07bca099c28f715", + "compiler.py": "f35bab2e71b6beb1228daaa5b7baecdacf04eaf713aee14e8082b97090f910b4", + "config.json": "63d39d4399bf06747f5f06d6b68db7b17fa3e96e8bc219fb9823742a700a06c1", + "configuration_valen.py": "735b02402fb5b6c7a1652f6691ba66d066ef99e84500042faec396ff7a668fe5", + "data_types.py": "b06ce08081d8f7b2bf36abf302410a96086395e75a04f9e9b1c591db519b1641", + "heads.py": "63b5970a8bfa121eff94d50ffd35e1fa8387f3af5abccc5f5b75381fb084fc34", + "lora/README.md": "761f9a02d12a6434a0444d774b01bd6e13cd98c392c154f2442665b8e632819b", + "lora/adapter_config.json": "83e2bc08b862c2cec7326c9f1ef2f44580e422c5f4ba2eea1148c8cd12bc979a", + "lora/adapter_model.safetensors": "b162b622b6d92720a87c678931a88ff05fd5e4b93b356997153c124bfac87708", + "mixer.safetensors": "64d368877bac6f4d9e8662d07ed6f21d3e4e58bec4e7a5dc6b4ac555fb4028d9", + "modeling_valen.py": "07f87481334cb1e28e9daee036c27bab3654645abf3df7983346b316e7788848", + "modeling_valen_lora.py": "0102d4e71596dc7e1f6f3c95e6cf5fb514c50bff9f27c4870f16ad618874d4be", + "processor_config.json": "d89ef49ce9cd37fbf510158e13c1ef063d9286411c1ec9049932dbe0487143b1", + "responses.py": "298016b0070f1000a38d033e1048e038ff5df6fc1dcbe830601105b181f1d228", + "runtime_model.py": "98bf0443ca196900b9f2b056129c84932041b8b53395d111f2fe6d3f2bc1e0a6", + "schema.py": "253825862b60016e37fd1040492008ad7f303679c092313d8a6527cf509f3b6e", + "tokenizer.json": "87a7830d63fcf43bf241c3c5242e96e62dd3fdc29224ca26fed8ea333db72de4", + "tokenizer_config.json": "e98f1901ac6f0adff67b1d540bfa0c36ac1a0cf59eb72ed78146ef89aafa1182", + "validation.json": "6e66db946145cba9c89033b82036e048845ac0f4e81920dcc9a8992a7f88edd2", + "visual_merger.safetensors": "8379c8434e846ff5007de471cd6174092ac0d30699007fbea7780882106774c1", + "fresh_process_validation.json": "d5f7b9a17d0f1011d02177a0dc0af7530912c2a5f191f06ee98a3a94cbd39b0c" + } +} diff --git a/unmerged/fresh_process_validation.json b/unmerged/fresh_process_validation.json new file mode 100644 index 0000000000000000000000000000000000000000..47567ef157db8e34ce3e94b81280eae2acc2f09f --- /dev/null +++ b/unmerged/fresh_process_validation.json @@ -0,0 +1,113 @@ +{ + "passed": true, + "isolated_python": true, + "valen_imports_blocked": true, + "lora_remains_unmerged": true, + "all_real_modalities_and_question_types_passed": true, + "sdpa_example_passed": true, + "cases": 20, + "max_probability_abs_error": 0.0, + "max_logit_abs_error": 0.0, + "details": [ + { + "case": "shared_state/text_multi/choice", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/text_multi/noul", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/text_multi/score", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/text_multi/score_many", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/image_score/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/image_noul/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/image_choice/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/video_multi/q000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/video_multi/score_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "shared_state/video_multi/noul_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/text_multi/choice", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/text_multi/noul", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/text_multi/score", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/text_multi/score_many", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/image_score/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/image_noul/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/image_choice/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/video_multi/q000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/video_multi/score_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + }, + { + "case": "question/video_multi/noul_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0 + } + ] +} diff --git a/unmerged/heads.py b/unmerged/heads.py new file mode 100644 index 0000000000000000000000000000000000000000..47627b2dc79bfafeea627683628f949f80ab7692 --- /dev/null +++ b/unmerged/heads.py @@ -0,0 +1,143 @@ +"""可替换的候选评分头。 / Interchangeable, candidate-wise decision heads.""" +import math + +import torch +from torch import nn + + +def head_signature(config): + """用于构建与恢复校验。 / Canonical architecture settings for loading.""" + kind = config.get("head_type", "bilinear") + defaults = { + "bilinear": {"projection_dim": 256}, + "mlp": {"head_hidden_dim": 512, "head_bottleneck_dim": 128}, + "role_mlp": {"head_width": 256, "head_hidden_dim": 1024}, + "mixer": {"head_width": 256, "head_layers": 2, + "head_token_hidden_dim": 16, "head_channel_hidden_dim": 1024}, + } + if kind not in defaults: + raise ValueError(f"Unknown Qwen head_type: {kind!r}") + values = {key: config.get(key, value) for key, value in defaults[kind].items()} + if any(type(value) is not int or value <= 0 for value in values.values()): + raise ValueError("Decision head dimensions must be positive integers") + return {"head_type": kind, **values} + + +class DecisionHead(nn.Module): + """原有参数名保持兼容。 / Preserve legacy bilinear parameter names.""" + def __init__(self, hidden_size, projection_dim=256): + super().__init__() + self.decision = nn.Linear(hidden_size, projection_dim, bias=False) + self.candidate = nn.Linear(hidden_size, projection_dim, bias=False) + self.scale = math.sqrt(projection_dim) + + def forward(self, hidden, positions, decision_position): + d = self.decision(hidden[0, decision_position].float()) + c = self.candidate(hidden[0, positions].float()) + return (c * d).sum(-1) / self.scale + + def extract_features(self, hidden, branch): + return hidden[:, [*branch.candidate_positions, branch.decision_position], :] + + def score_features(self, features): + return self(features, list(range(features.shape[1] - 1)), features.shape[1] - 1) + + +class MLPHead(nn.Module): + """每个候选共享一个 MLP。 / One shared MLP for arbitrary candidate counts.""" + def __init__(self, hidden_size, hidden_dim=512, bottleneck_dim=128): + super().__init__() + self.decision_norm = nn.LayerNorm(hidden_size) + self.candidate_norm = nn.LayerNorm(hidden_size) + self.network = nn.Sequential(nn.Linear(2 * hidden_size, hidden_dim), nn.GELU(), + nn.Linear(hidden_dim, bottleneck_dim), nn.GELU(), + nn.Linear(bottleneck_dim, 1)) + + def extract_features(self, hidden, branch): + c = hidden[0, branch.candidate_positions] + d = hidden[0, branch.decision_position].expand_as(c) + return torch.stack((d, c), dim=1) + + def score_features(self, features): + d, c = features.float().unbind(1) + return self.network(torch.cat((self.decision_norm(d), self.candidate_norm(c)), -1)).squeeze(-1) + + +def role_features(hidden, branch): + """先池化再投影,可缓存冻结特征。 / Pool before trainable projections.""" + spans = (getattr(branch, "context_span", None), getattr(branch, "instruction_span", None)) + candidates = getattr(branch, "candidate_spans", None) + if any(span is None for span in spans) or not candidates or len(candidates) != len(branch.candidate_positions): + raise ValueError("Role heads require compiler context, instruction and candidate spans") + + def pool(span): + start, end = span + if not 0 <= start < end <= hidden.shape[1]: + raise ValueError(f"Invalid role span: {span}") + return hidden[0, start:end].float().mean(0) + + context, instruction = (pool(span) for span in spans) + decision = hidden[0, branch.decision_position].float() + return torch.stack([torch.stack((context, instruction, pool(span), decision)) for span in candidates]) + + +class RoleHead(nn.Module): + def __init__(self, hidden_size, width): + super().__init__() + self.input_norm = nn.LayerNorm(hidden_size) + self.projection = nn.Linear(hidden_size, width) + self.roles = nn.Parameter(torch.zeros(1, 4, width)) + + def extract_features(self, hidden, branch): + return role_features(hidden, branch) + + def project(self, features): + return self.projection(self.input_norm(features.float())) + self.roles + + +class RoleMLPHead(RoleHead): + """与 Mixer 使用相同输入。 / Control for the Mixer's richer input features.""" + def __init__(self, hidden_size, width=256, hidden_dim=1024): + super().__init__(hidden_size, width) + self.network = nn.Sequential(nn.Linear(4 * width, hidden_dim), nn.GELU(), nn.Linear(hidden_dim, 1)) + + def score_features(self, features): + return self.network(self.project(features).flatten(1)).squeeze(-1) + + +class MixerBlock(nn.Module): + def __init__(self, width, token_hidden, channel_hidden): + super().__init__() + self.token_norm = nn.LayerNorm(width) + self.token_mlp = nn.Sequential(nn.Linear(4, token_hidden), nn.GELU(), nn.Linear(token_hidden, 4)) + self.channel_norm = nn.LayerNorm(width) + self.channel_mlp = nn.Sequential(nn.Linear(width, channel_hidden), nn.GELU(), nn.Linear(channel_hidden, width)) + + def forward(self, x): + # 混合角色,不混合不同候选。 / Mix fixed roles, never candidate rows. + x = x + self.token_mlp(self.token_norm(x).transpose(1, 2)).transpose(1, 2) + return x + self.channel_mlp(self.channel_norm(x)) + + +class MixerHead(RoleHead): + def __init__(self, hidden_size, width=256, layers=2, token_hidden=16, channel_hidden=1024): + super().__init__(hidden_size, width) + self.blocks = nn.Sequential(*(MixerBlock(width, token_hidden, channel_hidden) for _ in range(layers))) + self.output = nn.Sequential(nn.LayerNorm(width), nn.Linear(width, 1)) + + def score_features(self, features): + # 第三行是候选角色。 / Read the updated candidate role. + return self.output(self.blocks(self.project(features))[:, 2]).squeeze(-1) + + +def build_head(hidden_size, config): + settings = head_signature(config) + kind = settings.pop("head_type") + if kind == "bilinear": + return DecisionHead(hidden_size, settings["projection_dim"]) + if kind == "mlp": + return MLPHead(hidden_size, settings["head_hidden_dim"], settings["head_bottleneck_dim"]) + if kind == "role_mlp": + return RoleMLPHead(hidden_size, settings["head_width"], settings["head_hidden_dim"]) + return MixerHead(hidden_size, settings["head_width"], settings["head_layers"], + settings["head_token_hidden_dim"], settings["head_channel_hidden_dim"]) diff --git a/unmerged/lora/README.md b/unmerged/lora/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7daea40193544e018122f7a2bb1a91aae8fd7e96 --- /dev/null +++ b/unmerged/lora/README.md @@ -0,0 +1,206 @@ +--- +base_model: '' +library_name: peft +tags: +- 'base_model:adapter:' +- lora +- transformers +--- + +# Model Card for Model ID + + + + + +## Model Details + +### Model Description + + + + + +- **Developed by:** [More Information Needed] +- **Funded by [optional]:** [More Information Needed] +- **Shared by [optional]:** [More Information Needed] +- **Model type:** [More Information Needed] +- **Language(s) (NLP):** [More Information Needed] +- **License:** [More Information Needed] +- **Finetuned from model [optional]:** [More Information Needed] + +### Model Sources [optional] + + + +- **Repository:** [More Information Needed] +- **Paper [optional]:** [More Information Needed] +- **Demo [optional]:** [More Information Needed] + +## Uses + + + +### Direct Use + + + +[More Information Needed] + +### Downstream Use [optional] + + + +[More Information Needed] + +### Out-of-Scope Use + + + +[More Information Needed] + +## Bias, Risks, and Limitations + + + +[More Information Needed] + +### Recommendations + + + +Users (both direct and downstream) should be made aware of the risks, biases and limitations of the model. More information needed for further recommendations. + +## How to Get Started with the Model + +Use the code below to get started with the model. + +[More Information Needed] + +## Training Details + +### Training Data + + + +[More Information Needed] + +### Training Procedure + + + +#### Preprocessing [optional] + +[More Information Needed] + + +#### Training Hyperparameters + +- **Training regime:** [More Information Needed] + +#### Speeds, Sizes, Times [optional] + + + +[More Information Needed] + +## Evaluation + + + +### Testing Data, Factors & Metrics + +#### Testing Data + + + +[More Information Needed] + +#### Factors + + + +[More Information Needed] + +#### Metrics + + + +[More Information Needed] + +### Results + +[More Information Needed] + +#### Summary + + + +## Model Examination [optional] + + + +[More Information Needed] + +## Environmental Impact + + + +Carbon emissions can be estimated using the [Machine Learning Impact calculator](https://mlco2.github.io/impact#compute) presented in [Lacoste et al. (2019)](https://arxiv.org/abs/1910.09700). + +- **Hardware Type:** [More Information Needed] +- **Hours used:** [More Information Needed] +- **Cloud Provider:** [More Information Needed] +- **Compute Region:** [More Information Needed] +- **Carbon Emitted:** [More Information Needed] + +## Technical Specifications [optional] + +### Model Architecture and Objective + +[More Information Needed] + +### Compute Infrastructure + +[More Information Needed] + +#### Hardware + +[More Information Needed] + +#### Software + +[More Information Needed] + +## Citation [optional] + + + +**BibTeX:** + +[More Information Needed] + +**APA:** + +[More Information Needed] + +## Glossary [optional] + + + +[More Information Needed] + +## More Information [optional] + +[More Information Needed] + +## Model Card Authors [optional] + +[More Information Needed] + +## Model Card Contact + +[More Information Needed] +### Framework versions + +- PEFT 0.18.1 \ No newline at end of file diff --git a/unmerged/lora/adapter_config.json b/unmerged/lora/adapter_config.json new file mode 100644 index 0000000000000000000000000000000000000000..198b360aff5fd62c12ff3209d2b88a60fd6d5348 --- /dev/null +++ b/unmerged/lora/adapter_config.json @@ -0,0 +1,54 @@ +{ + "alora_invocation_tokens": null, + "alpha_pattern": {}, + "arrow_config": null, + "auto_mapping": { + "base_model_class": "Qwen3_5TextModel", + "parent_library": "transformers.models.qwen3_5.modeling_qwen3_5" + }, + "base_model_name_or_path": "Qwen/Qwen3.5-4B", + "bias": "none", + "corda_config": null, + "ensure_weight_tying": false, + "eva_config": null, + "exclude_modules": null, + "fan_in_fan_out": false, + "inference_mode": true, + "init_lora_weights": true, + "layer_replication": null, + "layers_pattern": null, + "layers_to_transform": null, + "loftq_config": {}, + "lora_alpha": 64, + "lora_bias": false, + "lora_dropout": 0.0, + "megatron_config": null, + "megatron_core": "megatron.core", + "modules_to_save": null, + "peft_type": "LORA", + "peft_version": "0.18.1", + "qalora_group_size": 16, + "r": 32, + "rank_pattern": {}, + "revision": "851bf6e806efd8d0a36b00ddf55e13ccb7b8cd0a", + "target_modules": [ + "in_proj_qkv", + "out_proj", + "in_proj_z", + "gate_proj", + "o_proj", + "up_proj", + "k_proj", + "in_proj_a", + "in_proj_b", + "v_proj", + "q_proj", + "down_proj" + ], + "target_parameters": null, + "task_type": null, + "trainable_token_indices": null, + "use_dora": false, + "use_qalora": false, + "use_rslora": false +} \ No newline at end of file diff --git a/unmerged/lora/adapter_model.safetensors b/unmerged/lora/adapter_model.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..c5a50b982b26fa7b8209374d1c27a2f327ec232e --- /dev/null +++ b/unmerged/lora/adapter_model.safetensors @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b162b622b6d92720a87c678931a88ff05fd5e4b93b356997153c124bfac87708 +size 259784032 diff --git a/unmerged/mixer.safetensors b/unmerged/mixer.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..429c851027a4276ee55abdbc73fb9d3870a35c9a --- /dev/null +++ b/unmerged/mixer.safetensors @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:64d368877bac6f4d9e8662d07ed6f21d3e4e58bec4e7a5dc6b4ac555fb4028d9 +size 6867012 diff --git a/unmerged/modeling_valen.py b/unmerged/modeling_valen.py new file mode 100644 index 0000000000000000000000000000000000000000..3c8d3a4ae3d4dfde9e3ece865bc57bccd4d1d6cd --- /dev/null +++ b/unmerged/modeling_valen.py @@ -0,0 +1,84 @@ +"""Complete merged Qwen + decision head. / 已合并的完整 Qwen 和决策头。""" +import torch +from transformers import AutoProcessor +from transformers.models.qwen3_5.modeling_qwen3_5 import Qwen3_5Model, Qwen3_5PreTrainedModel + +from .configuration_valen import ValenQwenConfig +from .heads import build_head +from .runtime_model import ValenQwen +from .compiler import Compiler +from .responses import answer +# List transitive files explicitly for Transformers' local dynamic loader. +# 本地动态加载需要显式列出间接依赖,否则搬移后可能缺少这些模块。 +from .batching import collate_branches +from .schema import candidates +from .data_types import QuestionSpec + + +class ValenQwenForDecisionMaking(Qwen3_5PreTrainedModel): + config_class = ValenQwenConfig + base_model_prefix = "backbone" + model_name = "Valen" + architecture = "qwen" + # The trained Mixer stays FP32 with a BF16 backbone. / BF16 基座、FP32 决策头。 + _keep_in_fp32_modules_strict = ["head"] + + def __init__(self, config, backbone=None, head=None): + super().__init__(config) + if (backbone is None) != (head is None): + raise ValueError("Supply both a merged backbone and a trained head") + self.backbone = backbone if backbone is not None else Qwen3_5Model(config) + self.head = head if head is not None else build_head(config.text_config.hidden_size, config.valen_head) + self.head.float() + self._processor = None + # Supplied weights are already trained: do not reinitialize them. + # 传入的参数已训练完成,不能再次调用初始化覆盖它们。 + if backbone is not None: + for module in self.modules(): + module._is_hf_initialized = True + self.post_init() + + def get_input_embeddings(self): + return self.backbone.get_input_embeddings() + + def set_input_embeddings(self, value): + self.backbone.set_input_embeddings(value) + + def forward(self, question=None, **inputs): + if question is None: + return self.backbone(**inputs) + if hasattr(question, "questions"): + return self.forward_state(question) + return ValenQwen.forward(self, question) + + # Use the exact trained readouts and batching implementation. + # 保留训练时的特征读取和 batch 逻辑。 + extract_features = ValenQwen.extract_features + extract_state_features = ValenQwen.extract_state_features + _state_features = ValenQwen._state_features + forward_state = ValenQwen.forward_state + forward_state_batch = ValenQwen.forward_state_batch + forward_batch = ValenQwen.forward_batch + score_features = ValenQwen.score_features + + def make_compiler(self, media_root=".", execution=None, processor=None): + if processor is None: + if self._processor is None: + self._processor = AutoProcessor.from_pretrained(self.config._name_or_path, trust_remote_code=True) + processor = self._processor + return Compiler(processor, media_root, self.config.valen_max_length, self.config.valen_media_kwargs, + execution=execution or self.config.qwen_execution) + + @torch.inference_mode() + def predict(self, request, *, media_root=".", execution=None, temperature=1.0, processor=None): + self.eval() + # Only request content reaches the compiler. / 只编译输入,不读取标签。 + request = request["request"] if "request" in request else request + compiler = self.make_compiler(media_root, execution, processor) + state = compiler.compile({"request": request}) + logits = self.forward_state(state) if state.inputs is not None else [self(q) for q in state.questions] + answers = {q.qid: answer(q, z, temperature[q.kind] if isinstance(temperature, dict) else temperature) + for q, z in zip(state.questions, logits)} + return {"model": self.model_name, "answers": answers, + "usage": {"input_tokens": state.logical_tokens, "output_tokens": 0}, + "internal_usage": {"compute_tokens": state.compute_tokens}} diff --git a/unmerged/modeling_valen_lora.py b/unmerged/modeling_valen_lora.py new file mode 100644 index 0000000000000000000000000000000000000000..c4d6031baef21b588dbb3c293151bb77cebc5a5b --- /dev/null +++ b/unmerged/modeling_valen_lora.py @@ -0,0 +1,92 @@ +"""Original base + separate trained deltas. / 原始基座与未融合的训练权重。""" +import hashlib +from pathlib import Path + +import torch +from peft import PeftModel +from safetensors.torch import load_file +from transformers import Qwen3_5ForConditionalGeneration + +from .configuration_valen import ValenQwenConfig +from .modeling_valen import ValenQwenForDecisionMaking +# Explicit dependencies keep local HF dynamic loading portable. +# 显式列出依赖,保证 HF 本地动态加载能复制完整的运行代码。 +from .heads import build_head +from .compiler import Compiler +from .runtime_model import ValenQwen +from .responses import answer +from .batching import collate_branches +from .schema import candidates +from .data_types import QuestionSpec + + +def _verify_local_base(base_path, expected): + if not Path(base_path).is_dir(): + return + for filename, digest in expected.items(): + path = Path(base_path) / filename + if not path.is_file(): + raise FileNotFoundError(f"Original base shard is required: {path}") + actual = hashlib.sha256() + with path.open("rb") as stream: + for chunk in iter(lambda: stream.read(8 << 20), b""): + actual.update(chunk) + if actual.hexdigest() != digest: + raise ValueError(f"Base weights differ from the trained revision: {filename}") + + +class ValenQwenWithLoRA(ValenQwenForDecisionMaking): + @classmethod + def from_pretrained(cls, pretrained_model_name_or_path, *model_args, config=None, + base_model_path=None, device=None, dtype=None, attn_implementation=None, + is_trainable=False, local_files_only=True, output_loading_info=False, + verify_base=True, **kwargs): + if model_args: + raise TypeError("Pass loader options as named arguments") + folder = Path(pretrained_model_name_or_path).resolve(strict=True) + if config is None: + config = ValenQwenConfig.from_pretrained(folder, local_files_only=True) + base = str(base_model_path or config.valen_base["repo"]) + dtype = dtype or kwargs.pop("torch_dtype", None) or config.dtype or torch.bfloat16 + if isinstance(dtype, str): + dtype = getattr(torch, dtype) + if dtype != torch.bfloat16: + raise ValueError("Use dtype=torch.bfloat16 to reproduce this adapter bundle") + attention = attn_implementation or config._attn_implementation or "sdpa" + if kwargs.pop("device_map", None) is not None: + raise ValueError("Use device=... or model.to(...) for this adapter bundle") + # AutoModel also supplies flags for loading the bundle's custom code. + # AutoModel 会传入自定义代码标记,它们不应改变原始基座的加载配置。 + for name in ("trust_remote_code", "_from_auto", "_commit_hash", "adapter_kwargs", "revision", "subfolder"): + kwargs.pop(name, None) + base_options = {name:kwargs.pop(name) for name in + ("cache_dir", "token", "force_download", "proxies", "low_cpu_mem_usage") if name in kwargs} + if kwargs: + raise TypeError(f"Unsupported loader options: {sorted(kwargs)}") + if verify_base: + _verify_local_base(base, config.valen_base["weight_sha256"]) + # Load the published conditional model first to preserve language prefixes. + # 先完整加载官方模型,再取出主干,避免语言参数前缀被错误映射。 + container, loading = Qwen3_5ForConditionalGeneration.from_pretrained( + base, revision=config.valen_base["revision"], dtype=dtype, + attn_implementation=attention, local_files_only=local_files_only, + output_loading_info=True, **base_options) + if any(loading.get(key) for key in ("missing_keys", "unexpected_keys", "mismatched_keys", "error_msgs")): + raise ValueError(f"Incomplete original base load: {loading}") + backbone = container.model + del container + backbone.requires_grad_(False) + backbone.language_model = PeftModel.from_pretrained( + backbone.language_model, folder / "lora", is_trainable=is_trainable, + autocast_adapter_dtype=True, torch_device="cpu", local_files_only=True) + backbone.visual.merger.load_state_dict(load_file(folder / "visual_merger.safetensors"), strict=True) + head = build_head(config.text_config.hidden_size, config.valen_head).float() + head.load_state_dict(load_file(folder / "mixer.safetensors"), strict=True) + config._name_or_path = str(folder) + model = cls(config, backbone=backbone, head=head) + model.head.requires_grad_(is_trainable) + model.backbone.visual.merger.requires_grad_(is_trainable) + if device is not None: + model.to(device) + model.eval() + return (model, loading) if output_loading_info else model diff --git a/unmerged/processor_config.json b/unmerged/processor_config.json new file mode 100644 index 0000000000000000000000000000000000000000..33818c7f9e991ad735fd240209f4fa73e6c28c50 --- /dev/null +++ b/unmerged/processor_config.json @@ -0,0 +1,60 @@ +{ + "image_processor": { + "do_convert_rgb": true, + "do_normalize": true, + "do_rescale": true, + "do_resize": true, + "image_mean": [ + 0.5, + 0.5, + 0.5 + ], + "image_processor_type": "Qwen2VLImageProcessor", + "image_std": [ + 0.5, + 0.5, + 0.5 + ], + "merge_size": 2, + "patch_size": 16, + "resample": 3, + "rescale_factor": 0.00392156862745098, + "size": { + "longest_edge": 16777216, + "shortest_edge": 65536 + }, + "temporal_patch_size": 2 + }, + "processor_class": "Qwen3VLProcessor", + "video_processor": { + "do_convert_rgb": true, + "do_normalize": true, + "do_rescale": true, + "do_resize": true, + "do_sample_frames": true, + "fps": 2, + "image_mean": [ + 0.5, + 0.5, + 0.5 + ], + "image_std": [ + 0.5, + 0.5, + 0.5 + ], + "max_frames": 768, + "merge_size": 2, + "min_frames": 4, + "patch_size": 16, + "resample": 3, + "rescale_factor": 0.00392156862745098, + "return_metadata": false, + "size": { + "longest_edge": 25165824, + "shortest_edge": 4096 + }, + "temporal_patch_size": 2, + "video_processor_type": "Qwen3VLVideoProcessor" + } +} diff --git a/unmerged/responses.py b/unmerged/responses.py new file mode 100644 index 0000000000000000000000000000000000000000..fb4398970a9fd3827c185269a2cfa97cc78d755f --- /dev/null +++ b/unmerged/responses.py @@ -0,0 +1,29 @@ +import math +import torch + +def answer(question, logits, temperature=1.0): + if not math.isfinite(temperature) or temperature <= 0: + raise ValueError("Calibration temperature must be finite and positive") + if logits.ndim != 1 or len(logits) != len(question.keys) or not torch.isfinite(logits).all(): + raise ValueError("Expected one finite logit per candidate") + probs = (logits.float() / temperature).softmax(-1).detach().cpu().tolist() + total = sum(probs) + probs = [p / total for p in probs] + result = {"type": question.kind} + if question.kind == "noul": + result["noul"] = probs[question.keys.index("true")] + return result + result["probabilities"] = dict(zip(question.keys, probs)) + mode = max(range(len(probs)), key=probs.__getitem__) + if question.kind == "choice": + result["choice"] = question.keys[mode] + result["confidence"] = 1.0 if len(probs) == 1 else max(0.0, (max(probs) - 1/len(probs)) / (1 - 1/len(probs))) + else: + result["score"] = sum(i * p for i, p in enumerate(probs)) + result["legend"] = dict(zip(question.keys, question.descriptions)) + # Independently implemented formula from pinned system-one adapter: + # fb52b1030b7fc1f4f1cf39910afa5da54f9835e3, confidence_metrics.py. + distance = sum(p * abs(i - mode) for i, p in enumerate(probs)) + uniform_mad = sum(abs(i - (len(probs)-1)/2) for i in range(len(probs))) / len(probs) + result["confidence"] = max(0.0, 1.0 - distance / uniform_mad) + return result diff --git a/unmerged/runtime_model.py b/unmerged/runtime_model.py new file mode 100644 index 0000000000000000000000000000000000000000..38f601b00ea984e6e0f221dfcbd106aa8ed7d775 --- /dev/null +++ b/unmerged/runtime_model.py @@ -0,0 +1,101 @@ +import torch +from torch import nn +MODEL_NAME = "Valen" +from .heads import DecisionHead, build_head +from .batching import branch_batches, collate_branches + + +class ValenQwen(nn.Module): + """Qwen3.5 backbone with a shared candidate decision head.""" + + model_name = MODEL_NAME + architecture = "qwen" + + def __init__(self, backbone, projection_dim=256, head_config=None): + super().__init__() + self.backbone = backbone + self.head = build_head(backbone.config.text_config.hidden_size, + dict({"projection_dim": projection_dim}, **(head_config or {}))) + + def forward(self, question): + device = next(self.backbone.parameters()).device + outputs = [] + for branch in question.branches: + inputs = {k: v.to(device) if isinstance(v, torch.Tensor) else v for k, v in branch.inputs.items()} + hidden = self.backbone(**inputs, use_cache=False, return_dict=True).last_hidden_state + outputs.append(self.head.score_features(self.head.extract_features(hidden, branch))) + return torch.cat(outputs) + + def extract_features(self, question): + """缓存投影前的特征。 / Cache raw readouts before trainable head layers.""" + device = next(self.backbone.parameters()).device + features = [] + for branch in question.branches: + inputs = {k: v.to(device) if isinstance(v, torch.Tensor) else v for k, v in branch.inputs.items()} + hidden = self.backbone(**inputs, use_cache=False, return_dict=True).last_hidden_state + features.append(self.head.extract_features(hidden, branch)) + return features + + def extract_state_features(self, state): + """一次编码 state,读取各题特征。 / One backbone graph for every question.""" + if not state.questions: + return [] + if state.inputs is None: + raise ValueError("Shared-state features require compiled shared inputs") + device = next(self.backbone.parameters()).device + inputs = {k: v.to(device) if isinstance(v, torch.Tensor) else v for k, v in state.inputs.items()} + hidden = self.backbone(**inputs, use_cache=False, return_dict=True).last_hidden_state + return self._state_features(hidden, state) + + def _state_features(self, hidden, state): + return [[self.head.extract_features(hidden, branch) for branch in q.branches] + for q in state.questions] + + def forward_state(self, state): + return [self.score_features(features) for features in self.extract_state_features(state)] + + def forward_state_batch(self, states, max_tokens=32768): + """不同 state 组成 batch,同一 state 的题目共用一行。 / One row per shared state.""" + device = next(self.backbone.parameters()).device + pad_token_id = getattr(self.backbone.config.text_config, "pad_token_id", None) or 0 + outputs = [[] for _ in states] + representatives = [] + indices = [] + for index, state in enumerate(states): + if not state.questions: + continue + if state.inputs is None or any(branch.inputs is not state.inputs + for q in state.questions for branch in q.branches): + raise ValueError("Shared-state batch requires one shared input per state") + representatives.append(state.questions[0]) + indices.append(index) + for batch in branch_batches(representatives, max_tokens): + inputs = collate_branches([branch for _, branch in batch], pad_token_id) + inputs = {key: value.to(device) for key, value in inputs.items()} + hidden = self.backbone(**inputs, use_cache=False, return_dict=True).last_hidden_state + for row, (index, _) in enumerate(batch): + original = indices[index] + features = self._state_features(hidden[row:row + 1], states[original]) + outputs[original] = [self.score_features(f) for f in features] + return outputs + + def forward_batch(self, questions, max_tokens=32768): + """Forward several QAs together; each keeps its own decision head inputs. + + 多条 QA 并行;每条保留独立的候选、角色区间和 Score 分支。 + """ + device = next(self.backbone.parameters()).device + pad_token_id = getattr(self.backbone.config.text_config, "pad_token_id", None) or 0 + outputs = [[] for _ in questions] + for batch in branch_batches(questions, max_tokens): + inputs = collate_branches([branch for _, branch in batch], pad_token_id) + inputs = {key: value.to(device) for key, value in inputs.items()} + hidden = self.backbone(**inputs, use_cache=False, return_dict=True).last_hidden_state + for row, (question_index, branch) in enumerate(batch): + features = self.head.extract_features(hidden[row:row + 1], branch) + outputs[question_index].append(self.head.score_features(features)) + return [torch.cat(branches) for branches in outputs] + + def score_features(self, features, head=None): + head = self.head if head is None else head + return torch.cat([head.score_features(hidden) for hidden in features]) diff --git a/unmerged/schema.py b/unmerged/schema.py new file mode 100644 index 0000000000000000000000000000000000000000..f3c3483045739bd5e38210e4a1ac32d13db44b07 --- /dev/null +++ b/unmerged/schema.py @@ -0,0 +1,71 @@ +"""Strict JSONL contract. IDs and labels never enter the model prompt.""" +import json +import math +from pathlib import Path + + +def candidates(question): + kind = question.get("type") + if not isinstance(question.get("instructions"), str) or not question["instructions"].strip(): + raise ValueError("instructions must be nonempty text") + criteria = question.get("criteria") + if kind == "noul": + return [("true", "True / 是:满足问题中的条件。"), ("false", "False / 否:不满足问题中的条件。")] + if kind == "choice": + if not isinstance(criteria, dict) or not 1 <= len(criteria) <= 255: + raise ValueError("Choice needs 1–255 named criteria") + result = list(criteria.items()) + elif kind == "score": + if not isinstance(criteria, list) or not 2 <= len(criteria) <= 255: + raise ValueError("Score criteria must be an ordered list of 2–255 descriptions") + result = [(str(i), text) for i, text in enumerate(criteria)] + else: + raise ValueError(f"Unsupported question type: {kind}") + if any(not isinstance(k, str) or not k or not isinstance(v, str) or not v.strip() for k, v in result): + raise ValueError("Candidate names and descriptions must be nonempty strings") + return result + + +def target_distribution(target, keys): + if target is None or target.get("probabilities") is None: + return None + probs = target["probabilities"] + if not isinstance(probs, dict) or set(probs) != set(keys): + raise ValueError(f"Probability keys must exactly match {keys}") + values = [probs[k] for k in keys] + if any(isinstance(v, bool) or not isinstance(v, (int, float)) or not math.isfinite(v) or v < 0 for v in values): + raise ValueError("Probabilities must be finite nonnegative numbers") + if not math.isclose(sum(values), 1.0, abs_tol=1e-6): + raise ValueError("Target probabilities must sum to 1") + return values + + +def validate_record(record, candidate_fn=candidates): + request = record["request"] + state = request["state"] + if not isinstance(state, (str, dict)): + raise ValueError("state must be text or a messages object") + if not isinstance(request["questions"], dict) or not request["questions"]: + raise ValueError("questions must be a nonempty mapping") + targets = record.get("targets", {}) + if set(targets) - set(request["questions"]): + raise ValueError("Unknown target question IDs") + for qid, question in request["questions"].items(): + target_distribution(targets.get(qid), [k for k, _ in candidate_fn(question)]) + if not record.get("group_id"): + raise ValueError("group_id is required for leakage-free splits") + return record + + +def read_jsonl(path, candidate_fn=candidates): + records = [] + with Path(path).open(encoding="utf-8") as stream: + for line_number, line in enumerate(stream, 1): + if line.strip(): + try: + records.append(validate_record(json.loads(line), candidate_fn)) + except (ValueError, KeyError, TypeError, AttributeError) as exc: + raise ValueError(f"{path}:{line_number}: {exc}") from exc + if not records: + raise ValueError("Empty dataset") + return records diff --git a/unmerged/tokenizer.json b/unmerged/tokenizer.json new file mode 100644 index 0000000000000000000000000000000000000000..67741b04f23bfdb46501f748ce27865ec82eccfb --- /dev/null +++ b/unmerged/tokenizer.json @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87a7830d63fcf43bf241c3c5242e96e62dd3fdc29224ca26fed8ea333db72de4 +size 19989343 diff --git a/unmerged/tokenizer_config.json b/unmerged/tokenizer_config.json new file mode 100644 index 0000000000000000000000000000000000000000..a068e2468cff426a9b105006e74e044030a6faf4 --- /dev/null +++ b/unmerged/tokenizer_config.json @@ -0,0 +1,32 @@ +{ + "add_prefix_space": false, + "audio_bos_token": "<|audio_start|>", + "audio_eos_token": "<|audio_end|>", + "audio_token": "<|audio_pad|>", + "backend": "tokenizers", + "bos_token": null, + "clean_up_tokenization_spaces": false, + "eos_token": "<|im_end|>", + "errors": "replace", + "image_token": "<|image_pad|>", + "is_local": true, + "model_max_length": 262144, + "model_specific_special_tokens": { + "audio_bos_token": "<|audio_start|>", + "audio_eos_token": "<|audio_end|>", + "audio_token": "<|audio_pad|>", + "image_token": "<|image_pad|>", + "video_token": "<|video_pad|>", + "vision_bos_token": "<|vision_start|>", + "vision_eos_token": "<|vision_end|>" + }, + "pad_token": "<|endoftext|>", + "pretokenize_regex": "(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\\r\\n\\p{L}\\p{N}]?[\\p{L}\\p{M}]+|\\p{N}| ?[^\\s\\p{L}\\p{M}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+", + "processor_class": "Qwen3VLProcessor", + "split_special_tokens": false, + "tokenizer_class": "TokenizersBackend", + "unk_token": null, + "video_token": "<|video_pad|>", + "vision_bos_token": "<|vision_start|>", + "vision_eos_token": "<|vision_end|>" +} diff --git a/unmerged/validation.json b/unmerged/validation.json new file mode 100644 index 0000000000000000000000000000000000000000..45c05162d4d9ca42258185d82bedf5a9b8341acf --- /dev/null +++ b/unmerged/validation.json @@ -0,0 +1,136 @@ +{ + "passed": true, + "all_training_deltas_bitwise_reloaded": true, + "all_backbone_buffers_bitwise_preserved": true, + "trainable_tensor_count": 535, + "reload_vs_checkpoint": { + "cases": 20, + "changed_labels": [], + "max_probability_abs_error": 0.0, + "max_logit_abs_error": 0.0, + "details": [ + { + "case": "shared_state/text_multi/choice", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/text_multi/noul", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/text_multi/score", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/text_multi/score_many", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/image_score/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/image_noul/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/image_choice/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/video_multi/q000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/video_multi/score_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/video_multi/noul_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/text_multi/choice", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/text_multi/noul", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/text_multi/score", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/text_multi/score_many", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/image_score/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/image_noul/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/image_choice/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/video_multi/q000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/video_multi/score_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/video_multi/noul_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + } + ] + }, + "public_predict_passed": true, + "scope": "Text/image/video; question/shared_state; Choice/Noul/Score, including 12-level Score." +} diff --git a/unmerged/visual_merger.safetensors b/unmerged/visual_merger.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..ae93468ea3a068c697e8dbec43a75b8f4b395b96 --- /dev/null +++ b/unmerged/visual_merger.safetensors @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8379c8434e846ff5007de471cd6174092ac0d30699007fbea7780882106774c1 +size 54543872 diff --git a/validation.json b/validation.json new file mode 100644 index 0000000000000000000000000000000000000000..d0507f520b16ebca237706f9ed5276b619544043 --- /dev/null +++ b/validation.json @@ -0,0 +1,399 @@ +{ + "passed": true, + "merge_vs_adapter": { + "cases": 20, + "changed_labels": [], + "max_probability_abs_error": 0.0196954607963562, + "max_logit_abs_error": 0.2783782482147217, + "details": [ + { + "case": "shared_state/text_multi/choice", + "probability_max_abs": 7.516145706176758e-05, + "logit_max_abs": 0.1412639617919922, + "label_changed": false + }, + { + "case": "shared_state/text_multi/noul", + "probability_max_abs": 0.0020025968551635742, + "logit_max_abs": 0.08715403079986572, + "label_changed": false + }, + { + "case": "shared_state/text_multi/score", + "probability_max_abs": 0.00015294551849365234, + "logit_max_abs": 0.22236299514770508, + "label_changed": false + }, + { + "case": "shared_state/text_multi/score_many", + "probability_max_abs": 0.0007519125938415527, + "logit_max_abs": 0.21488428115844727, + "label_changed": false + }, + { + "case": "shared_state/image_score/decision", + "probability_max_abs": 0.0049536824226379395, + "logit_max_abs": 0.08501756191253662, + "label_changed": false + }, + { + "case": "shared_state/image_noul/decision", + "probability_max_abs": 0.007346063852310181, + "logit_max_abs": 0.053545475006103516, + "label_changed": false + }, + { + "case": "shared_state/image_choice/decision", + "probability_max_abs": 5.960464477539062e-07, + "logit_max_abs": 0.07563447952270508, + "label_changed": false + }, + { + "case": "shared_state/video_multi/q000", + "probability_max_abs": 0.0007462501525878906, + "logit_max_abs": 0.052941322326660156, + "label_changed": false + }, + { + "case": "shared_state/video_multi/score_000", + "probability_max_abs": 0.009998738765716553, + "logit_max_abs": 0.17007660865783691, + "label_changed": false + }, + { + "case": "shared_state/video_multi/noul_000", + "probability_max_abs": 0.004840642213821411, + "logit_max_abs": 0.023845434188842773, + "label_changed": false + }, + { + "case": "question/text_multi/choice", + "probability_max_abs": 9.876489639282227e-05, + "logit_max_abs": 0.14330768585205078, + "label_changed": false + }, + { + "case": "question/text_multi/noul", + "probability_max_abs": 0.0036571621894836426, + "logit_max_abs": 0.04279124736785889, + "label_changed": false + }, + { + "case": "question/text_multi/score", + "probability_max_abs": 0.01770859956741333, + "logit_max_abs": 0.14924001693725586, + "label_changed": false + }, + { + "case": "question/text_multi/score_many", + "probability_max_abs": 0.00689321756362915, + "logit_max_abs": 0.2783782482147217, + "label_changed": false + }, + { + "case": "question/image_score/decision", + "probability_max_abs": 0.0196954607963562, + "logit_max_abs": 0.16257822513580322, + "label_changed": false + }, + { + "case": "question/image_noul/decision", + "probability_max_abs": 0.01183822751045227, + "logit_max_abs": 0.06843137741088867, + "label_changed": false + }, + { + "case": "question/image_choice/decision", + "probability_max_abs": 7.152557373046875e-07, + "logit_max_abs": 0.1550288200378418, + "label_changed": false + }, + { + "case": "question/video_multi/q000", + "probability_max_abs": 0.0026362910866737366, + "logit_max_abs": 0.04598259925842285, + "label_changed": false + }, + { + "case": "question/video_multi/score_000", + "probability_max_abs": 0.0021969079971313477, + "logit_max_abs": 0.06780719757080078, + "label_changed": false + }, + { + "case": "question/video_multi/noul_000", + "probability_max_abs": 0.006669759750366211, + "logit_max_abs": 0.05645298957824707, + "label_changed": false + } + ] + }, + "reload_vs_merged": { + "cases": 20, + "changed_labels": [], + "max_probability_abs_error": 0.0, + "max_logit_abs_error": 0.0, + "details": [ + { + "case": "shared_state/text_multi/choice", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/text_multi/noul", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/text_multi/score", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/text_multi/score_many", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/image_score/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/image_noul/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/image_choice/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/video_multi/q000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/video_multi/score_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/video_multi/noul_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/text_multi/choice", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/text_multi/noul", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/text_multi/score", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/text_multi/score_many", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/image_score/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/image_noul/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/image_choice/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/video_multi/q000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/video_multi/score_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/video_multi/noul_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + } + ] + }, + "all_effective_lora_matrices_verified": true, + "head_and_merger_bitwise_preserved": true, + "all_exported_tensors_bitwise_reloaded": true, + "language_buffers_bitwise_preserved": true, + "all_backbone_buffers_bitwise_preserved": true, + "float32_matmul_precision": "highest", + "same_model_repeat": { + "cases": 20, + "changed_labels": [], + "max_probability_abs_error": 0.0, + "max_logit_abs_error": 0.0, + "details": [ + { + "case": "shared_state/text_multi/choice", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/text_multi/noul", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/text_multi/score", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/text_multi/score_many", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/image_score/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/image_noul/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/image_choice/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/video_multi/q000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/video_multi/score_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "shared_state/video_multi/noul_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/text_multi/choice", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/text_multi/noul", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/text_multi/score", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/text_multi/score_many", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/image_score/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/image_noul/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/image_choice/decision", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/video_multi/q000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/video_multi/score_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + }, + { + "case": "question/video_multi/noul_000", + "probability_max_abs": 0.0, + "logit_max_abs": 0.0, + "label_changed": false + } + ] + }, + "reload_tolerances": { + "probability": 1e-06, + "logit": 1e-05 + }, + "public_predict_passed": true, + "scope": "Text/image/video, Choice/Noul/Score, 12-level Score, question/shared_state; this is export validation, not benchmark evaluation." +}