-
Notifications
You must be signed in to change notification settings - Fork 215
feat(cpu): add Ling-3.0-tiny mobile CPU support #699
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Aharrypotter
wants to merge
4
commits into
UbiquitousLearning:main
Choose a base branch
from
Aharrypotter:feat/ling3-tiny
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
e3b3240
feat(cpu): add Ling-3.0-tiny mobile support
Aharrypotter 5741370
refactor(cpu): route Ling stateful ops through mllm abstractions
Aharrypotter 240ded1
refactor(ling3): adopt upstream test layout for the Ling stateful ops
Aharrypotter 0aa7d26
docs(ling3): document the retained test targets
Aharrypotter File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| add_executable(mllm-ling3-runner main.cpp) | ||
| target_link_libraries(mllm-ling3-runner PRIVATE MllmRT MllmCPUBackend) | ||
| target_include_directories(mllm-ling3-runner PRIVATE ${MLLM_INCLUDE_DIR}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| # Ling-3.0-tiny mobile CPU runner | ||
|
|
||
| This runner targets the pinned official checkpoint | ||
| `inclusionAI/Ling-3.0-tiny@a2ee06c0f2de5b171701aee7f73f70a1da75483b`. | ||
| The supported deployment envelope is batch 1, a 2048-token cache, float32 | ||
| recurrent state, and KAI W4A32 linear weights on ARM64 macOS and Android. | ||
| Build the ARM CPU backend without `-ffast-math`: Ling-3's recurrent gates are | ||
| not compatible with relaxed IEEE semantics. For Android, the validated ISA | ||
| flags are `-march=armv8.2-a+fp16+fp16fml+dotprod+i8mm`; do not append | ||
| `-ffast-math`. | ||
|
|
||
| Validate the source checkpoint before conversion: | ||
|
|
||
| ```bash | ||
| python3 validate_checkpoint.py /path/to/Ling-3.0-tiny \ | ||
| --observed-revision a2ee06c0f2de5b171701aee7f73f70a1da75483b | ||
| ``` | ||
|
|
||
| Convert with the repository V2 converter and | ||
| `quant_cfg_tiny_w4a32_kai.json`, using model name `Ling-3.0-tiny`, then seal | ||
| the output descriptor table: | ||
|
|
||
| ```bash | ||
| python3 validate_converted_model.py /path/to/Ling-3.0-tiny.mllm \ | ||
| /path/to/Ling-3.0-tiny | ||
| ``` | ||
|
|
||
| Run one deterministic smoke request: | ||
|
|
||
| ```bash | ||
| ./mllm-ling3-runner \ | ||
| --model_path /path/to/Ling-3.0-tiny.mllm \ | ||
| --tokenizer_path /path/to/Ling-3.0-tiny/tokenizer.json \ | ||
| --config_path config_tiny_w4a32_kai.json \ | ||
| --prompt '你好,请用一句话介绍你自己。' \ | ||
| --max_new_tokens 8 --print_token_ids | ||
| ``` | ||
|
|
||
| The runner emits `LING3_RUN_START`, generated token IDs, and | ||
| `LING3_RUN_OK`. A successful build or tokenizer-only test is not a full-model | ||
| runtime result; device evidence must retain the converted model SHA256 and | ||
| the runner/library identities together. | ||
|
|
||
| For a longer correctness demo, pass the prompt directly and use a 64-token | ||
| generation limit: | ||
|
|
||
| ```bash | ||
| ./mllm-ling3-runner \ | ||
| --model_path /path/to/Ling-3.0-tiny.mllm \ | ||
| --tokenizer_path /path/to/Ling-3.0-tiny/tokenizer.json \ | ||
| --config_path config_tiny_w4a32_kai.json \ | ||
| --prompt '请用中文详细介绍 Ling-3.0-tiny 的混合注意力架构,并解释 KDA、MLA 和 MoE 各自的作用。' --disable_thinking \ | ||
| --max_new_tokens 64 --print_token_ids | ||
| ``` | ||
|
|
||
| The expected completion marker is | ||
| `LING3_RUN_OK prompt_tokens=49 generated_tokens=64`. This is a generation | ||
| correctness demo, not a perplexity, model-quality, or performance benchmark. | ||
|
|
||
| ## Retained tests | ||
|
|
||
| The Ling-specific coverage follows the repository test layout (`ctest` labels | ||
| in parentheses): | ||
|
|
||
| | Layer | Target | Notes | | ||
| | --- | --- | --- | | ||
| | KDA kernel | `Mllm-Test-CPUKernel --gtest_filter='KimiDeltaAttentionKernelTest.*'` (`cpu-kernel`) | scalar-reference oracle, bitwise prefill/decode and serial/parallel checks | | ||
| | Public `nn::KimiDeltaAttention` | `Mllm-Test-Nn-KimiDeltaAttention` (`KimiDeltaAttentionFocused`) | eager reference, in-place state, chunked equivalence, trace + serialization | | ||
| | Causal convolution | upstream `Mllm-Test-Nn-CausalDepthwiseConv1D` and the `CausalDepthwiseConv*KernelTest` suites | Ling registers the upstream operation with the current-first order | | ||
| | Model | `Mllm-Test-Ling3-Config`, `Mllm-Test-Ling3-RoPE`, `Mllm-Test-Ling3-Tokenizer` (`ling3`) | set `MLLM_LING3_EXAMPLE_DIR` on a device; the tokenizer test skips unless `LING3_OFFICIAL_TOKENIZER` points at the official `tokenizer.json` | | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| { | ||
| "architectures": ["BailingMoeV3ForCausalLM"], | ||
| "model_type": "bailing_hybrid", | ||
| "hidden_size": 1536, | ||
| "intermediate_size": 4608, | ||
| "num_hidden_layers": 24, | ||
| "num_attention_heads": 16, | ||
| "num_key_value_heads": 16, | ||
| "head_dim": 128, | ||
| "vocab_size": 157184, | ||
| "max_position_embeddings": 131072, | ||
| "rms_norm_eps": 1e-06, | ||
| "rope_theta": 6000000, | ||
| "hidden_act": "silu", | ||
| "tie_word_embeddings": false, | ||
| "use_qkv_bias": false, | ||
| "layer_group_size": 4, | ||
| "short_conv_kernel_size": 4, | ||
| "no_kda_lora": true, | ||
| "kda_safe_gate": true, | ||
| "kda_lower_bound": -5, | ||
| "q_lora_rank": 256, | ||
| "kv_lora_rank": 512, | ||
| "qk_rope_head_dim": 64, | ||
| "qk_nope_head_dim": 128, | ||
| "qk_head_dim": 192, | ||
| "v_head_dim": 128, | ||
| "rope_interleave": true, | ||
| "gated_attention_proj_granularity_type": "head_wise", | ||
| "num_experts": 128, | ||
| "num_shared_experts": 1, | ||
| "num_experts_per_tok": 8, | ||
| "n_group": 8, | ||
| "topk_group": 4, | ||
| "moe_intermediate_size": 512, | ||
| "moe_shared_expert_intermediate_size": 512, | ||
| "first_k_dense_replace": 1, | ||
| "routed_scaling_factor": 2.5, | ||
| "scoring_func": "sigmoid", | ||
| "topk_method": "noaux_tc", | ||
| "moe_router_enable_expert_bias": true, | ||
| "pad_token_id": 156892, | ||
| "eos_token_id": 156895, | ||
| "max_cache_length": 2048, | ||
| "linear_impl_type": "KaiLinear_f32_qai8dxp_qsi4c32p_mxk_nxk_qai8dxp1x8_qsi4c32p8x8_1x8x32" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| // Copyright (c) MLLM Team. | ||
| // Licensed under the MIT License. | ||
|
|
||
| #include <fmt/core.h> | ||
|
|
||
| #include <mllm/engine/Context.hpp> | ||
| #include <mllm/mllm.hpp> | ||
| #include <mllm/models/ling3/modeling_ling3.hpp> | ||
| #include <mllm/models/ling3/tokenization_ling3.hpp> | ||
| #include <mllm/utils/AnyValue.hpp> | ||
|
|
||
| #include <cstdio> | ||
| #include <fstream> | ||
| #include <iostream> | ||
| #include <stdexcept> | ||
| #include <string> | ||
|
|
||
| using mllm::Argparse; | ||
|
|
||
| namespace { | ||
|
|
||
| std::string readPromptFile(const std::string& path) { | ||
| std::ifstream stream(path, std::ios::binary); | ||
| if (!stream) { throw std::invalid_argument("unable to read prompt_file: " + path); } | ||
| std::string text{std::istreambuf_iterator<char>(stream), std::istreambuf_iterator<char>()}; | ||
| while (!text.empty() && (text.back() == '\n' || text.back() == '\r')) { text.pop_back(); } | ||
| if (text.empty()) { throw std::invalid_argument("prompt_file must not be empty: " + path); } | ||
| return text; | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| MLLM_MAIN({ | ||
| auto engine_args = mllm::engineArgAttach(); | ||
| auto& help = Argparse::add<bool>("-h|--help").help("Show help message"); | ||
| auto& model_path = Argparse::add<std::string>("-m|--model_path").help("MLLM V2 model path").required(true); | ||
| auto& tokenizer_path = Argparse::add<std::string>("-t|--tokenizer_path").help("Official tokenizer.json").required(true); | ||
| auto& config_path = Argparse::add<std::string>("-c|--config_path").help("Ling-3 mobile runtime config").required(true); | ||
| auto& prompt = Argparse::add<std::string>("-p|--prompt").help("Run one prompt non-interactively").required(false); | ||
| auto& prompt_file = Argparse::add<std::string>("--prompt_file").help("Read a prompt from a UTF-8 file").required(false); | ||
| auto& max_new_tokens = | ||
| Argparse::add<int>("-g|--max_new_tokens").help("Maximum generated tokens (default: 8)").required(false); | ||
| auto& min_new_tokens = Argparse::add<int>("--min_new_tokens").help("Suppress EOS until this many tokens").required(false); | ||
| auto& disable_thinking = | ||
| Argparse::add<bool>("--disable_thinking").help("Use the official thinking-off chat template").required(false); | ||
| auto& print_token_ids = Argparse::add<bool>("--print_token_ids").help("Print generated token IDs to stderr").required(false); | ||
|
|
||
| for (int index = 1; index < argc; ++index) { | ||
| if (std::string(argv[index]) == "-h" || std::string(argv[index]) == "--help") { | ||
| Argparse::printHelp(); | ||
| return 0; | ||
| } | ||
| } | ||
| Argparse::parse(argc, argv); | ||
| mllm::configEngineWithArgs(engine_args); | ||
| (void)help; | ||
|
|
||
| const auto config = mllm::models::ling3::Ling3Config(config_path.get()); | ||
| int generation_limit = max_new_tokens.isSet() ? max_new_tokens.get() : 8; | ||
| int minimum_generation = min_new_tokens.isSet() ? min_new_tokens.get() : 0; | ||
| if (generation_limit <= 0 || generation_limit > config.max_cache_length || minimum_generation < 0 | ||
| || minimum_generation > generation_limit) { | ||
| throw std::invalid_argument("generation lengths must satisfy 0 <= min_new_tokens <= max_new_tokens <= max_cache_length"); | ||
| } | ||
| if (prompt.isSet() && prompt_file.isSet()) { throw std::invalid_argument("prompt and prompt_file are mutually exclusive"); } | ||
|
|
||
| std::string configured_prompt; | ||
| if (prompt_file.isSet()) { | ||
| configured_prompt = readPromptFile(prompt_file.get()); | ||
| } else if (prompt.isSet()) { | ||
| configured_prompt = prompt.get(); | ||
| } | ||
|
|
||
| const auto parameters = mllm::load(model_path.get(), mllm::ModelFileVersion::kV2); | ||
| mllm::models::ling3::validateLing3ModelConfigMatch(config, parameters); | ||
| auto tokenizer = mllm::models::ling3::Ling3Tokenizer(tokenizer_path.get()); | ||
| auto model = mllm::models::ling3::Ling3ForCausalLM(config); | ||
| model.load(parameters); | ||
| fmt::print("Ling-3.0-tiny: {} layers ({} MLA + {} KDA), CPU threads={}\n", config.num_hidden_layers, | ||
| config.numFullAttentionLayers(), config.numKDALayers(), mllm::Context::instance().getCpuOpThreads()); | ||
|
|
||
| int exit_code = 0; | ||
| while (true) { | ||
| std::string prompt_text = configured_prompt; | ||
| if (!prompt.isSet() && !prompt_file.isSet()) { | ||
| fmt::print("Prompt text (or 'exit/quit'): "); | ||
| if (!std::getline(std::cin, prompt_text) || prompt_text == "exit" || prompt_text == "quit") { break; } | ||
| } | ||
| if (prompt_text.empty()) { | ||
| if (prompt.isSet() || prompt_file.isSet()) { throw std::invalid_argument("prompt must not be empty"); } | ||
| continue; | ||
| } | ||
| try { | ||
| auto input = tokenizer.convertMessage({.prompt = prompt_text, | ||
| .system_prompt = "", | ||
| .enable_thinking = !(disable_thinking.isSet() && disable_thinking.get())}); | ||
| const int prompt_tokens = input.at("sequence").shape()[1]; | ||
| if (prompt_tokens + generation_limit - 1 > config.max_cache_length) { | ||
| throw std::invalid_argument("prompt plus generation exceeds max_cache_length"); | ||
| } | ||
| model.resetState(); | ||
| fmt::print("LING3_RUN_START prompt_tokens={} max_new_tokens={} min_new_tokens={}\nResponse: ", prompt_tokens, | ||
| generation_limit, minimum_generation); | ||
| int generated_tokens = 0; | ||
| for (const auto& step : model.chat(input, {{"max_length", mllm::AnyValue(generation_limit)}, | ||
| {"min_new_tokens", mllm::AnyValue(minimum_generation)}, | ||
| {"do_sample", mllm::AnyValue(false)}})) { | ||
| if (print_token_ids.isSet() && print_token_ids.get()) { fmt::print(stderr, "LING3_TOKEN_ID:{}\n", step.cur_token_id); } | ||
| fmt::print("{}", tokenizer.detokenizeBytes(step.cur_token_id)); | ||
| std::fflush(stdout); | ||
| ++generated_tokens; | ||
| } | ||
| fmt::print("\nLING3_RUN_OK prompt_tokens={} generated_tokens={}\n", prompt_tokens, generated_tokens); | ||
| } catch (const std::exception& error) { | ||
| fmt::print(stderr, "LING3_RUN_ERROR:{}\n", error.what()); | ||
| exit_code = 1; | ||
| } | ||
| if (prompt.isSet() || prompt_file.isSet()) { break; } | ||
| } | ||
|
|
||
| model.perfSummary(); | ||
| mllm::memoryReport(); | ||
| return exit_code; | ||
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| { | ||
| "^model\\.layers\\.\\d+\\.attention\\.(q_proj|k_proj|v_proj|f_proj)\\.weight$": { | ||
| "hints": {"quant_method": "kai", "kai_matmul_triplet": "f32_qai8dxp_qsi4c32p", "kai_matmul_layout": "mxk_nxk", "kai_matmul_tile_cfg": "qai8dxp1x8_qsi4c32p8x8_1x8x32", "shape": [2048, 1536], "replace": true} | ||
| }, | ||
| "^model\\.layers\\.(?:[0-2]|[4-6]|8|9|10|12|13|14|16|17|18|20|21|22)\\.attention\\.g_proj\\.weight$": { | ||
| "hints": {"quant_method": "kai", "kai_matmul_triplet": "f32_qai8dxp_qsi4c32p", "kai_matmul_layout": "mxk_nxk", "kai_matmul_tile_cfg": "qai8dxp1x8_qsi4c32p8x8_1x8x32", "shape": [2048, 1536], "replace": true} | ||
| }, | ||
| "^model\\.layers\\.(?:3|7|11|15|19|23)\\.attention\\.g_proj\\.weight$": { | ||
| "hints": {"quant_method": "kai", "kai_matmul_triplet": "f32_qai8dxp_qsi4c32p", "kai_matmul_layout": "mxk_nxk", "kai_matmul_tile_cfg": "qai8dxp1x8_qsi4c32p8x8_1x8x32", "shape": [16, 1536], "replace": true} | ||
| }, | ||
| "^model\\.layers\\.\\d+\\.attention\\.b_proj\\.weight$": { | ||
| "hints": {"quant_method": "kai", "kai_matmul_triplet": "f32_qai8dxp_qsi4c32p", "kai_matmul_layout": "mxk_nxk", "kai_matmul_tile_cfg": "qai8dxp1x8_qsi4c32p8x8_1x8x32", "shape": [16, 1536], "replace": true} | ||
| }, | ||
| "^model\\.layers\\.\\d+\\.attention\\.o_proj\\.weight$": { | ||
| "hints": {"quant_method": "kai", "kai_matmul_triplet": "f32_qai8dxp_qsi4c32p", "kai_matmul_layout": "mxk_nxk", "kai_matmul_tile_cfg": "qai8dxp1x8_qsi4c32p8x8_1x8x32", "shape": [1536, 2048], "replace": true} | ||
| }, | ||
| "^model\\.layers\\.\\d+\\.attention\\.q_a_proj\\.weight$": { | ||
| "hints": {"quant_method": "kai", "kai_matmul_triplet": "f32_qai8dxp_qsi4c32p", "kai_matmul_layout": "mxk_nxk", "kai_matmul_tile_cfg": "qai8dxp1x8_qsi4c32p8x8_1x8x32", "shape": [256, 1536], "replace": true} | ||
| }, | ||
| "^model\\.layers\\.\\d+\\.attention\\.q_b_proj\\.weight$": { | ||
| "hints": {"quant_method": "kai", "kai_matmul_triplet": "f32_qai8dxp_qsi4c32p", "kai_matmul_layout": "mxk_nxk", "kai_matmul_tile_cfg": "qai8dxp1x8_qsi4c32p8x8_1x8x32", "shape": [3072, 256], "replace": true} | ||
| }, | ||
| "^model\\.layers\\.\\d+\\.attention\\.kv_a_proj_with_mqa\\.weight$": { | ||
| "hints": {"quant_method": "kai", "kai_matmul_triplet": "f32_qai8dxp_qsi4c32p", "kai_matmul_layout": "mxk_nxk", "kai_matmul_tile_cfg": "qai8dxp1x8_qsi4c32p8x8_1x8x32", "shape": [576, 1536], "replace": true} | ||
| }, | ||
| "^model\\.layers\\.\\d+\\.attention\\.kv_b_proj\\.weight$": { | ||
| "hints": {"quant_method": "kai", "kai_matmul_triplet": "f32_qai8dxp_qsi4c32p", "kai_matmul_layout": "mxk_nxk", "kai_matmul_tile_cfg": "qai8dxp1x8_qsi4c32p8x8_1x8x32", "shape": [4096, 512], "replace": true} | ||
| }, | ||
| "^model\\.layers\\.\\d+\\.attention\\.dense\\.weight$": { | ||
| "hints": {"quant_method": "kai", "kai_matmul_triplet": "f32_qai8dxp_qsi4c32p", "kai_matmul_layout": "mxk_nxk", "kai_matmul_tile_cfg": "qai8dxp1x8_qsi4c32p8x8_1x8x32", "shape": [1536, 2048], "replace": true} | ||
| }, | ||
| "^model\\.layers\\.0\\.mlp\\.(gate_proj|up_proj)\\.weight$": { | ||
| "hints": {"quant_method": "kai", "kai_matmul_triplet": "f32_qai8dxp_qsi4c32p", "kai_matmul_layout": "mxk_nxk", "kai_matmul_tile_cfg": "qai8dxp1x8_qsi4c32p8x8_1x8x32", "shape": [4608, 1536], "replace": true} | ||
| }, | ||
| "^model\\.layers\\.0\\.mlp\\.down_proj\\.weight$": { | ||
| "hints": {"quant_method": "kai", "kai_matmul_triplet": "f32_qai8dxp_qsi4c32p", "kai_matmul_layout": "mxk_nxk", "kai_matmul_tile_cfg": "qai8dxp1x8_qsi4c32p8x8_1x8x32", "shape": [1536, 4608], "replace": true} | ||
| }, | ||
| "^model\\.layers\\.(?:[1-9]|1\\d|2[0-3])\\.mlp\\.(?:experts\\.\\d+|shared_experts)\\.(gate_proj|up_proj)\\.weight$": { | ||
| "hints": {"quant_method": "kai", "kai_matmul_triplet": "f32_qai8dxp_qsi4c32p", "kai_matmul_layout": "mxk_nxk", "kai_matmul_tile_cfg": "qai8dxp1x8_qsi4c32p8x8_1x8x32", "shape": [512, 1536], "replace": true} | ||
| }, | ||
| "^model\\.layers\\.(?:[1-9]|1\\d|2[0-3])\\.mlp\\.(?:experts\\.\\d+|shared_experts)\\.down_proj\\.weight$": { | ||
| "hints": {"quant_method": "kai", "kai_matmul_triplet": "f32_qai8dxp_qsi4c32p", "kai_matmul_layout": "mxk_nxk", "kai_matmul_tile_cfg": "qai8dxp1x8_qsi4c32p8x8_1x8x32", "shape": [1536, 512], "replace": true} | ||
| }, | ||
| "^lm_head\\.weight$": { | ||
| "hints": {"quant_method": "kai", "kai_matmul_triplet": "f32_qai8dxp_qsi4c32p", "kai_matmul_layout": "mxk_nxk", "kai_matmul_tile_cfg": "qai8dxp1x8_qsi4c32p8x8_1x8x32", "shape": [157184, 1536], "replace": true} | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| # Copyright (c) MLLM Team. | ||
| # Licensed under the MIT License. | ||
|
|
||
| import json | ||
| import unittest | ||
| from pathlib import Path | ||
|
|
||
| from validate_checkpoint import ( | ||
| FULL_ATTENTION_LAYERS, | ||
| expected_shapes, | ||
| validate_config, | ||
| validate_recipe, | ||
| ) | ||
|
|
||
|
|
||
| HERE = Path(__file__).resolve().parent | ||
|
|
||
|
|
||
| class Ling3ValidatorTests(unittest.TestCase): | ||
| def test_expected_checkpoint_inventory_is_exact(self): | ||
| shapes = expected_shapes() | ||
| self.assertEqual(len(shapes), 9283) | ||
| self.assertEqual( | ||
| {layer for layer in range(24) if f"model.layers.{layer}.attention.q_a_proj.weight" in shapes}, | ||
| FULL_ATTENTION_LAYERS, | ||
| ) | ||
|
|
||
| def test_runtime_and_recipe_match_official_contract(self): | ||
| runtime = json.loads((HERE / "config_tiny_w4a32_kai.json").read_text()) | ||
| validate_config(runtime, runtime) | ||
| recipe = json.loads((HERE / "quant_cfg_tiny_w4a32_kai.json").read_text()) | ||
| matched = validate_recipe(expected_shapes(), recipe) | ||
| self.assertGreater(len(matched), 9000) | ||
| self.assertNotIn("model.word_embeddings.weight", matched) | ||
| self.assertNotIn("model.layers.1.mlp.gate.weight", matched) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| unittest.main() |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
State the required working directory for these commands.
The commands reference
validate_checkpoint.py,validate_converted_model.py, andconfig_tiny_w4a32_kai.jsonwith relative paths. They fail when users run them from the repository root.Add an explicit
cd examples/ling3step, or make all script, configuration, and runner paths repository-relative.🤖 Prompt for AI Agents