OmniCoder-2-9B 是 OmniCoder-9B 的彻底重构版本,而非简单续作。我们重新设计了整个训练流水线,以解决用户反馈的第一代模型核心问题:
</think> 块常常内容冗余、逻辑循环。第二代模型生成的推理链更加精炼,能更快切入核心,因为它只学习了实际的推理过程,而非周围的框架性内容。总结: OmniCoder-2-9B 解决了第一代模型存在的重复和不稳定问题。模型权重和架构不变,但训练方法截然不同。
| 基准测试 | OmniCoder-2-9B | OmniCoder-9B | Qwen3.5-9B | GPT-OSS-120B | GLM 4.7 | Claude Haiku 4.5 |
|---|---|---|---|---|---|---|
| AIME 2025(pass@5) | 90 | 90 | 91.6 | |||
| GPQA Diamond(pass@1) | 83 | 83.8 | 81.7 | 71.5 | 73 | |
| GPQA Diamond(pass@3) | 86 | 86.4 | ||||
| Terminal-Bench 2.0 | 25.8 | 23.6 | 14.6 | 33.4 | 27 |
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "Tesslate/OmniCoder-2-9B"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype="auto", device_map="auto")
messages = [
{"role": "system", "content": "You are a helpful coding assistant."},
{"role": "user", "content": "Write a Python function to find the longest common subsequence of two strings."},
]
text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = tokenizer([text], return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_new_tokens=2048, temperature=0.6, top_p=0.95, top_k=20)
print(tokenizer.decode(outputs[0][inputs.input_ids.shape[-1]:], skip_special_tokens=True))vllm serve Tesslate/OmniCoder-2-9B --tensor-parallel-size 1 --max-model-len 65536from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="token")
response = client.chat.completions.create(
model="Tesslate/OmniCoder-2-9B",
messages=[{"role": "user", "content": "Explain the difference between a mutex and a semaphore."}],
temperature=0.6,
)
print(response.choices[0].message.content)llama-cli --hf-repo Tesslate/OmniCoder-2-9B-GGUF --hf-file omnicoder-2-9b-q4_k_m.gguf -p "Your prompt" -c 8192| OmniCoder-9B (v1) | OmniCoder-2-9B (v2) | |
|---|---|---|
| 计算损失的对象 | 所有 tokens(系统、用户、工具、助手) | 仅助手 tokens |
| 学习率调度 | 余弦调度(衰减至零过早) | 带预热的恒定学习率 |
| EOS 训练方式 | 全局 | 按轮次 (train_on_eos: turn) |
| 思考块 | 被标准模板剥离 | 在所有轮次中保留(自定义 Jinja2) |
| 重复问题 | 生成中频繁出现循环 | 几乎为零 |
| 收敛情况 | 学习率在第 60 步终止了学习 | 在第 80-100 步平稳收敛 |
| 基础模型 | Qwen3.5-9B |
| 方法 | LoRA SFT(r=64,alpha=32,包含所有层及 MLP) |
| 数据集 | 来自 5 个来源的 425K 智能体轨迹 |
| 损失 | 仅助手 tokens(roles_to_train: [assistant]) |
| 序列长度 | 65,536 tokens(样本打包) |
| 学习率调度 | 带预热的恒定学习率(2e-4,10 步预热) |
| 硬件 | 4x NVIDIA H200(DDP) |
| 框架 | Axolotl |
| 精度 | bf16 |
| 优化器 | AdamW(权重衰减=0.001) |
| 有效批次大小 | 32 |
| 步数 | 350(约为一个 epoch 的 10%) |
| 来源 | 样本数 | 描述 |
|---|---|---|
| NVIDIA Nemotron-Terminal-Corpus | 226K | 终端智能体轨迹 |
| CoderForge-Preview(奖励 >= 0.5) | 155K | SWE-bench 风格的编码轨迹 |
| Nemotron Skill-Based | 24K | 基于技能的编码任务 |
| Scale-SWE | 20K | 真实 GitHub 问题补丁(合成轨迹) |
| Opus Reasoning | 2.3K | 思维链推理 |
v1 在 80 步内采用余弦学习率调度。学习率在第 60 步衰减至零,在模型收敛前终止了学习。损失看似稳定在 0.45,但实际上仍在下降。
v2 遵循 Schulman 等人的研究发现:
OmniCoder-2 继承了 Qwen3.5-9B 的混合架构:
Qwen3_5ForConditionalGeneration 构建。| 参数 | 值 |
|---|---|
| Temperature | 0.6 |
| Top-P | 0.95 |
| Top-K | 20 |
| Presence Penalty | 0.0 |
对于智能体/工具调用任务,可考虑降低 temperature(0.2-0.4)以获得更具确定性的行为。
特别感谢 Axolotl 团队以及 axolotl#3453 中的讨论,他们帮助实现了 Qwen3.5 的打包支持。
@misc{omnicoder2_2025,
title={OmniCoder-2-9B: A Frontier Open Coding Agent},
author={Tesslate},
year={2025},
url={https://huggingface.co/Tesslate/OmniCoder-2-9B}
}由 Tesslate 打造