Spark-X2.5-1.7B-VibeThinker-VN

Mô tả ngắn

Spark-X2.5-1.7B-VibeThinker-VN là một mô hình ngôn ngữ 1.7B tham số được tinh chỉnh (fine-tune) bằng phương pháp sequence-level knowledge distillation từ mô hình giáo viên WeiboAI/VibeThinker-3B sang mô hình học sinh XHToken/Spark-X2.5-1.7B-Base.

  • Giáo viên (Teacher): WeiboAI/VibeThinker-3B — 3B tham số, giấy phép MIT.
  • Học sinh (Student): XHToken/Spark-X2.5-1.7B-Base — 1.7B tham số, giấy phép Apache-2.0.
  • Kết quả: Spark-X2.5-1.7B-VibeThinker-VN — 1.7B tham số, giấy phép Apache-2.0.
  • Ngôn ngữ: Tiếng Việt (chính) + Tiếng Anh (cho phần code).

Mục tiêu của dự án là chưng cất khả năng suy luận từng bước (chain-of-thought) và giải toán/code/logic của giáo viên 3B xuống một mô hình học sinh 1.7B nhỏ gọn hơn, có thể chạy trên phần cứng phổ thông (Tesla T4 16GB, CPU qua GGUF), trong khi vẫn giữ được chất lượng suy luận tiếng Việt ở mức hợp lý.


📜 GIẤY PHÉP VÀ BẢN QUYỀN

Đây là phần quan trọng nhất của model card này. Mô hình là sản phẩm phái sinh từ hai mô hình gốc có giấy phép khác nhau, do đó cần tuân thủ nghiêm ngặt cả hai.

Bảng giấy phép 3 lớp

Thành phần Tên mô hình Giấy phép Quyền phái sinh Quyền thương mại
Teacher WeiboAI/VibeThinker-3B MIT ✅ Có ✅ Có
Student (Base) XHToken/Spark-X2.5-1.7B-Base Apache-2.0 ✅ Có ✅ Có
Model này Spark-X2.5-1.7B-VibeThinker-VN Apache-2.0 ✅ Có ✅ Có

Tuyên bố tuân thủ

Chúng tôi tuyên bố tuân thủ đầy đủ các điều khoản của cả hai giấy phép gốc:

(a) Quyền phái sinh và thương mại. Cả giấy phép MIT (của VibeThinker-3B) và Apache-2.0 (của Spark-X2.5-1.7B-Base) đều cho phép tạo tác phẩm phái sinh (derivative works), sử dụng cho mục đích thương mại, và phân phối lại. Việc chưng cất tri thức (knowledge distillation) được xem là một dạng tác phẩm phái sinh hợp lệ theo cả hai giấy phép.

(b) Ghi công đầy đủ.

  • Ghi công WeiboAI với mô hình VibeThinker-3B (giấy phép MIT).
  • Ghi công XHToken với mô hình Spark-X2.5-1.7B-Base (giấy phép Apache-2.0).
  • Toàn bộ thông tin ghi công được giữ trong phần Citation và Acknowledgments của model card này.

(c) Chỉ sử dụng output văn bản của teacher. Chúng tôi chỉ sử dụng văn bản đầu ra (text output) do teacher sinh ra để huấn luyện học sinh. Chúng tôi KHÔNG:

  • Sao chép trọng số (weights) của teacher.
  • Sao chép kiến trúc mạng (architecture) của teacher.
  • Sao chép mã nguồn (source code) của teacher.
  • Truy cập vào logits hoặc phân phối xác suất nội bộ của teacher.

Đây là lý do kỹ thuật bắt buộc: teacher và student dùng tokenizer khác nhau (teacher 151.667 token, student 131.072 token), nên không thể dùng logit-level KD; chỉ có thể dùng sequence-level KD.

(d) Không sử dụng dữ liệu có bản quyền. Toàn bộ dữ liệu huấn luyện được sinh tự động (toán) hoặc viết tay bởi tác giả (5 lĩnh vực còn lại). Chúng tôi KHÔNG sử dụng bất kỳ dataset bên thứ ba nào, bao gồm nhưng không giới hạn: GSM8K, MATH, hay bất kỳ dataset có bản quyền nào khác.

File LICENSE trong repo

Repo cần chứa hai thành phần giấy phép:

  1. File LICENSE — toàn văn Apache-2.0 (áp dụng cho mô hình này).
  2. Dòng ghi nhận MIT ở đầu file LICENSE:
    This model is a derivative of WeiboAI/VibeThinker-3B (MIT License).
    Copyright (c) WeiboAI.
    

🧭 Tổng quan

Thuộc tính Giá trị
Teacher WeiboAI/VibeThinker-3B (3B, MIT)
Student (Base) XHToken/Spark-X2.5-1.7B-Base (1.7B, Apache-2.0)
Model kết quả Spark-X2.5-1.7B-VibeThinker-VN (Apache-2.0)
Phương pháp Sequence-level knowledge distillation + Rejection sampling + LoRA
Dữ liệu 1.328 mẫu, 6 lĩnh vực, sinh tự động + viết tay
Lĩnh vực Toán, Code, Logic, Câu đố, Khoa học-STEM, Lập luận
Phần cứng 1× Tesla T4 16GB (Google Colab)
Thời gian train ~38 phút (train), ~2.5 giờ (toàn pipeline)
Định dạng Safetensors (LoRA + merged), GGUF (q4_k_m)
Ngôn ngữ Tiếng Việt (chính), Tiếng Anh (code)
Context length 1.024 token (giới hạn khi train)

🔬 Phương pháp

1. Vì sao dùng sequence-level KD thay vì logit-level KD?

Knowledge distillation cổ điển (Hinton et al.) sử dụng logit-level KD: học sinh học phân phối xác suất đầu ra của giáo viên thông qua Kullback-Leibler divergence. Phương pháp này yêu cầu teacher và student chia sẻ cùng vocabulary để logits có thể so sánh trực tiếp.

Trong dự án này:

  • Teacher VibeThinker-3B dùng tokenizer 151.667 token.
  • Student Spark-X2.5-1.7B-Base dùng tokenizer 131.072 token.

Hai vocabulary không khớp nhau → không thể căn chỉnh logits → buộc phải dùng sequence-level KD.

2. Sequence-level knowledge distillation

Ở sequence-level KD (Kim & Rush, 2016), học sinh học từ chuỗi văn bản hoàn chỉnh do giáo viên sinh ra, thay vì học từ phân phối xác suất. Cụ thể:

  1. Với mỗi prompt trong tập dữ liệu, teacher sinh ra một lời giải hoàn chỉnh (chain-of-thought + đáp án cuối).
  2. Lời giải này được kiểm tra tự động (rejection sampling).
  3. Chỉ những lời giải đúng đáp án mới được giữ lại làm dữ liệu huấn luyện cho học sinh.
  4. Học sinh được fine-tune theo cross-entropy loss trên các cặp (prompt, lời giải đúng).

3. Rejection sampling

Để đảm bảo chất lượng dữ liệu chưng cất, chúng tôi áp dụng rejection sampling:

  • Teacher sinh lời giải ở temperature = 0.7 (đủ đa dạng nhưng không quá ngẫu nhiên).
  • Với mỗi câu có đáp án chuẩn, hệ thống trích số cuối cùng trong lời giải của teacher.
  • So sánh với đáp án chuẩn với dung sai 1e-4.
  • Chỉ giữ những lời giải cho ra đúng đáp án.
  • Tỷ lệ giữ: ~70% (1.328 / ~1.900 mẫu).

4. LoRA (Low-Rank Adaptation)

Thay vì fine-tune toàn bộ 1.7B tham số, chúng tôi dùng LoRA để giảm chi phí bộ nhớ và tăng tốc huấn luyện:

Tham số LoRA Giá trị
r (rank) 32
alpha 64
dropout 0.05
target_modules q_k_v_proj, g_proj, gate_proj, out_proj, up_proj, down_proj
Trainable params 33.496.064
Tổng params 1.741.153.280
Tỷ lệ trainable 1,92%

📊 Phân bố dữ liệu

Tổng cộng 1.328 mẫu sau rejection sampling, chia theo 6 lĩnh vực:

Lĩnh vực Số mẫu Tỷ lệ
Toán 664 50%
Code 133 10%
Logic 133 10%
Câu đố 133 10%
Khoa học-STEM 133 10%
Lập luận 132 10%
Tổng 1.328 100%

Chạy lệnh sau trên Colab để có số thật, điền lại vào bảng:

import json, collections
c = collections.Counter()
p = "/content/drive/MyDrive/distill_vibethinker_spark/teacher_data.jsonl"
for line in open(p, encoding="utf-8"):
    line = line.strip()
    if line:
        c[json.loads(line).get("domain", "?")] += 1
for k, v in c.most_common():
    print("%-10s %5d  %5.1f%%" % (k, v, 100 * v / sum(c.values())))

Nguồn dữ liệu

  • Toán (50% theo tỷ lệ sinh): Sinh tự động bằng máy với 15 dạng bài khác nhau (số học, đại số, hình học, tỷ lệ, phần trăm, v.v.). Đáp án được tính bằng công thức, không qua LLM.
  • Code, Logic, Câu đố, Khoa học-STEM, Lập luận: Prompt do tác giả viết tay, sau đó teacher sinh lời giải và lọc qua rejection sampling.
  • KHÔNG sử dụng dataset bên thứ ba. Không GSM8K, không MATH, không bất kỳ dataset có bản quyền nào.

⚙️ Hyperparameters

Hyperparameter Giá trị
epochs 4
micro_batch_size 2
gradient_accumulation_steps 4
effective_batch_size 8
learning_rate 2e-4
lr_scheduler Cosine
warmup_ratio 3%
gradient_clip 1.0
precision FP16 (T4 không hỗ trợ BF16)
optimizer AdamW8bit
max_len 1024
attn_implementation eager (bắt buộc, Spark chưa hỗ trợ SDPA)
total_steps 664 (~111 bước/lĩnh vực)

📉 Kết quả huấn luyện

Loss theo epoch

Epoch Loss trung bình
1 0.741
2 0.573
3 0.494
4 0.422

Nhận xét

  • Loss khởi đầu: 1.575.
  • Loss cuối: 0.402.
  • Mức giảm: ~75%.
  • Loss giảm đều qua 4 epoch, không có dấu hiệu hội tụ sớm rõ rệt.
  • Dao động loss giữa các step trong epoch 1 khá lớn (0.556–1.575), sau đó ổn định dần ở epoch 3–4.

📊 Benchmark

⚠️ Chưa đánh giá, cần điền số thực tế. Các bảng dưới đây được để trống có chủ đích. KHÔNG bịa số.

Bảng 1: Toán tiếng Việt

Benchmark Spark gốc Model này Chênh lệch
GSM8K-Vi (tùy chỉnh) — — —
MATH-Vi (tùy chỉnh) — — —
Toán tiểu học (tự tạo) — — —

Bảng 2: Code và Logic

Benchmark Spark gốc Model này Chênh lệch
HumanEval-Vi (tùy chỉnh) — — —
Logic reasoning (tự tạo) — — —
Câu đố (tự tạo) — — —

Bảng 3: Tổng hợp

Benchmark Spark gốc Model này Chênh lệch
Điểm trung bình 6 lĩnh vực — — —
Tỷ lệ đúng toán — — —
Tỷ lệ đúng code — — —

⚠️ Giới hạn

Chúng tôi nói thẳng về các giới hạn của mô hình này:

  1. Quy mô dữ liệu nhỏ. Chỉ 1.328 mẫu huấn luyện. Đây là con số rất nhỏ so với các mô hình reasoning hiện đại (thường hàng trăm nghìn đến hàng triệu mẫu). Mô hình có thể học tốt format và một số pattern, nhưng khó tổng quát hóa sâu.

  2. Format tăng mạnh nhưng năng lực tăng vừa phải. Mô hình học rất tốt định dạng chain-of-thought (trình bày từng bước, kết luận rõ ràng) từ teacher, nhưng năng lực suy luận thực tế có thể chỉ tăng ở mức vừa phải do giới hạn dữ liệu và kích thước học sinh 1.7B.

  3. Rủi ro overfit với 4 epoch. Với chỉ 1.328 mẫu và 4 epoch (664 bước), mô hình có nguy cơ overfit vào tập huấn luyện. Loss giảm mạnh có thể phản ánh việc học thuộc format hơn là học suy luận thực sự.

  4. Chưa đánh giá định lượng. Chúng tôi chưa chạy benchmark độc lập trên mô hình này. Mọi đánh giá hiện tại chỉ dựa trên loss huấn luyện, không đủ để kết luận về chất lượng thực tế.

  5. Kế thừa giới hạn của base 1.7B. Mô hình học sinh chỉ có 1.7B tham số, nhỏ hơn nhiều so với teacher 3B và các mô hình reasoning lớn khác. Nó kế thừa mọi giới hạn về kiến thức, độ chính xác, và khả năng suy luận của base model.

  6. Chỉ học output văn bản của teacher. Vì dùng sequence-level KD, mô hình không học được phân phối xác suất, logits, hay bất kỳ thông tin nội bộ nào của teacher. Đây là giới hạn kỹ thuật bắt buộc do tokenizer khác nhau.

  7. Kế thừa định hướng sử dụng của teacher. Theo khuyến nghị từ WeiboAI, VibeThinker-3B không phù hợp cho function calling, API orchestration, hay autonomous coding agent. Mô hình này phù hợp nhất cho toán, code thi đấu (LeetCode-style), và STEM reasoning có đáp án kiểm chứng được.


🚀 Cách sử dụng

1. Với Transformers (Python)

⚠️ Quan trọng — 3 điểm bắt buộc (thiếu là hỏng):

  1. trust_remote_code=True — 2 chỗ (tokenizer + model).
  2. attn_implementation="eager" — Spark chưa hỗ trợ SDPA.
  3. apply_chat_template — vì lúc train dùng đúng định dạng này.
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

model_id = "N14QM/Spark-X2.5-1.7B-VibeThinker-VN"

tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    dtype=torch.float16,          # torch_dtype đã deprecated
    device_map="auto",
    trust_remote_code=True,       # BẮT BUỘC: Spark dùng modeling_spark.py riêng
    attn_implementation="eager",  # BẮT BUỘC: Spark chưa hỗ trợ SDPA
).eval()

q = "Tinh 15% cua 240."
t = tokenizer.apply_chat_template([{"role": "user", "content": q}],
                                  tokenize=False, add_generation_prompt=True)
i = tokenizer(t, return_tensors="pt").to(model.device)

with torch.no_grad():
    o = model.generate(**i, max_new_tokens=512, temperature=0.7,
                       top_p=0.9, do_sample=True)
print(tokenizer.decode(o[0][i["input_ids"].shape[1]:], skip_special_tokens=True))

2. Với llama.cpp / Ollama (GGUF)

Mô hình đã được xuất sang định dạng GGUF q4_k_m. Lưu ý: llama.cpp gốc không hỗ trợ kiến trúc Spark; cần dùng fork của XHToken.

# Clone fork llama.cpp của XHToken
git clone https://github.com/XHToken/llama.cpp
cd llama.cpp

# Build (CMake)
cmake -S . -B build && cmake --build build --config Release -j

# Chạy inference với GGUF
./build/bin/llama-cli -m /path/to/model.q4_k_m.gguf \
       -p "Giải bài toán sau từng bước: 12 + 35 bằng bao nhiêu?" \
       -n 512 \
       --temp 0.7

3. Với Ollama (khuyến nghị tạo Modelfile)

Tạo file Modelfile cùng thư mục với GGUF:

FROM ./model.q4_k_m.gguf
TEMPLATE """{{ .Prompt }}"""
PARAMETER temperature 0.7
PARAMETER num_predict 512

Sau đó tạo và chạy:

ollama create spark-vibethinker-vn -f Modelfile
ollama run spark-vibethinker-vn

📚 Trích dẫn (BibTeX)

Model này

@misc{spark_x25_17b_vibethinker_vn,
  title        = {Spark-X2.5-1.7B-VibeThinker-VN: Sequence-Level Knowledge Distillation from VibeThinker-3B to Spark-X2.5-1.7B-Base},
  author       = {Nguyen Quang Minh},
  year         = {2026},
  howpublished = {\url{https://huggingface.co/N14QM/Spark-X2.5-1.7B-VibeThinker-VN}},
  note         = {Apache-2.0 License}
}

Teacher: VibeThinker-3B

@misc{vibethinker_3b,
  title        = {VibeThinker-3B},
  author       = {WeiboAI},
  year         = {2025},
  howpublished = {\url{https://huggingface.co/WeiboAI/VibeThinker-3B}},
  note         = {MIT License}
}

Student: Spark-X2.5-1.7B-Base

@misc{spark_x25_17b_base,
  title        = {Spark-X2.5-1.7B-Base},
  author       = {XHToken},
  year         = {2025},
  howpublished = {\url{https://huggingface.co/XHToken/Spark-X2.5-1.7B-Base}},
  note         = {Apache-2.0 License}
}

Phương pháp tham khảo

@article{kim2016sequence,
  title   = {Sequence-Level Knowledge Distillation},
  author  = {Kim, Yoon and Rush, Alexander M.},
  journal = {Proceedings of EMNLP},
  year    = {2016}
}

@article{hu2021lora,
  title   = {LoRA: Low-Rank Adaptation of Large Language Models},
  author  = {Hu, Edward J. and Shen, Yelong and Wallis, Phillip and others},
  journal = {arXiv preprint arXiv:2106.09685},
  year    = {2021}
}

🙏 Lời cảm ơn

  • WeiboAI — vì đã phát hành VibeThinker-3B dưới giấy phép MIT, cho phép cộng đồng nghiên cứu và phái sinh.
  • XHToken — vì đã phát hành Spark-X2.5-1.7B-Base và fork llama.cpp hỗ trợ kiến trúc Spark.
  • Google Colab — vì đã cung cấp GPU Tesla T4 16GB miễn phí, giúp toàn bộ pipeline chưng cất có thể chạy được.
  • Cộng đồng Hugging Face — vì hạ tầng transformers, peft, datasets, huggingface_hub và nhiều thư viện mã nguồn mở khác.

Model card được viết cho Spark-X2.5-1.7B-VibeThinker-VN. Mọi số liệu trong tài liệu này phản ánh đúng kết quả huấn luyện thực tế. Các ô benchmark được để trống có chủ đích — vui lòng điền số thực tế sau khi đánh giá.

Downloads last month
89
GGUF
Model size
2B params
Architecture
spark2_5
Hardware compatibility
Log In to add your hardware

4-bit

16-bit

Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for N14QM/Spark-X2.5-1.7B-VibeThinker-VN

Base model

Qwen/Qwen2.5-3B
Adapter
(10)
this model

Paper for N14QM/Spark-X2.5-1.7B-VibeThinker-VN