beyoru commited on
Commit
c793531
·
verified ·
1 Parent(s): 7b6bceb

Model card: quickstart (vLLM + OpenAI client + transformers), serving gotchas, training details, limitations

Browse files
Files changed (1) hide show
  1. README.md +182 -11
README.md CHANGED
@@ -1,28 +1,199 @@
1
  ---
2
  license: apache-2.0
3
  base_model: Qwen/Qwen3.6-27B
 
 
 
 
 
 
4
  tags:
5
  - function-calling
6
  - tool-use
 
7
  - agent
 
 
8
  - grpo
 
9
  - intuitor
10
  - self-certainty
11
- - qwen3_5
12
- pipeline_tag: text-generation
13
- library_name: transformers
 
14
  ---
15
 
16
- # Opera
 
 
 
 
 
 
 
 
 
17
 
18
- RL fine-tune of **Qwen3.6-27B** for agentic tool-calling, trained with GRPO + LoRA
19
- and a composite reward: rule-based (function name + argument-subset partial credit),
20
- structural tool-call validity, and **Intuitor self-certainty** (arXiv:2505.19590),
21
- rule and self-certainty weighted 1.0 each (normalized separately, then combined).
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
- ## Serve (vLLM >= 0.25, no --trust-remote-code)
25
  ```bash
26
- vllm serve beyoru/Opera --served-model-name opera -tp 4 --max-model-len 16384 \
 
27
  --enable-auto-tool-choice --tool-call-parser qwen3_coder --reasoning-parser qwen3
28
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  license: apache-2.0
3
  base_model: Qwen/Qwen3.6-27B
4
+ base_model_relation: finetune
5
+ pipeline_tag: text-generation
6
+ library_name: transformers
7
+ language:
8
+ - en
9
+ - vi
10
  tags:
11
  - function-calling
12
  - tool-use
13
+ - tool-calling
14
  - agent
15
+ - agentic
16
+ - rl
17
  - grpo
18
+ - lora
19
  - intuitor
20
  - self-certainty
21
+ - vllm
22
+ - qwen3
23
+ - vietnamese
24
+ - enterprise-automation
25
  ---
26
 
27
+ # Opera — a 27B agent tuned for multi-turn tool calling
28
+
29
+ **Opera** is an RL fine-tune of **Qwen3.6-27B** for *agentic* tool-calling: multi-turn
30
+ episodes where the model has to look up a policy, read messy free-text input, compute an
31
+ exact number, and then call the right tool with the right arguments — not just emit one
32
+ well-formed function call.
33
+
34
+ It was trained with **GRPO + LoRA** and a composite reward, including
35
+ [Intuitor self-certainty](https://arxiv.org/abs/2505.19590) as an intrinsic signal
36
+ alongside rule-based correctness.
37
 
38
+ **Use it if you need:** an open-weight agent backend for business automation
39
+ (accounting, HR, operations) that holds up over long tool-use episodes, and that works on
40
+ Vietnamese input out of the box.
 
41
 
42
+ | | |
43
+ |---|---|
44
+ | Base | `Qwen/Qwen3.6-27B` (dense, VL architecture) |
45
+ | Method | GRPO + LoRA (r32 / α64), merged into full weights |
46
+ | Precision / size | bf16, 11 shards (~54 GB) |
47
+ | Context | 16K validated (base supports more) |
48
+ | Reasoning | thinking **on** — this is how it was trained and evaluated |
49
+ | Tool-call format | Qwen3.5-style XML (`<function=...>`), **not** JSON — see gotchas |
50
+ | License | Apache-2.0 |
51
+
52
+ ---
53
+
54
+ ## Quickstart
55
+
56
+ ### Serve with vLLM (recommended)
57
 
 
58
  ```bash
59
+ vllm serve beyoru/Opera --served-model-name opera \
60
+ -tp 4 --max-model-len 16384 \
61
  --enable-auto-tool-choice --tool-call-parser qwen3_coder --reasoning-parser qwen3
62
+ ```
63
+
64
+ Do **not** pass `--trust-remote-code`: vLLM registers its own `Qwen3_5MoeConfig`/`qwen3_5`
65
+ config class only when remote code is off. With the flag on you get
66
+ `Invalid type of HuggingFace config`.
67
+
68
+ Fits on 1×H200, or 2×A100-80G / 4×A100-40G with `-tp`.
69
+
70
+ ### Call it like any OpenAI-compatible endpoint
71
+
72
+ ```python
73
+ from openai import OpenAI
74
+
75
+ client = OpenAI(base_url="http://localhost:8000/v1", api_key="EMPTY")
76
+
77
+ tools = [{
78
+ "type": "function",
79
+ "function": {
80
+ "name": "create_penalty_voucher",
81
+ "description": "Lập chứng từ lãi phạt chậm thanh toán cho một hóa đơn.",
82
+ "parameters": {
83
+ "type": "object",
84
+ "properties": {
85
+ "invoice_no": {"type": "string"},
86
+ "amount": {"type": "integer", "description": "Số tiền lãi phạt (VND)"},
87
+ },
88
+ "required": ["invoice_no", "amount"],
89
+ },
90
+ },
91
+ }]
92
+
93
+ resp = client.chat.completions.create(
94
+ model="opera",
95
+ messages=[{"role": "user", "content":
96
+ "Hóa đơn HD-1042 của Cty TNHH An Phát: dư nợ 120 triệu, quá hạn 45 ngày. "
97
+ "Tra chính sách rồi lập chứng từ lãi phạt."}],
98
+ tools=tools,
99
+ temperature=0.7,
100
+ max_tokens=4096,
101
+ )
102
+ print(resp.choices[0].message.tool_calls)
103
+ ```
104
+
105
+ ### Transformers
106
+
107
+ ```python
108
+ from transformers import AutoModelForCausalLM, AutoTokenizer
109
+
110
+ tok = AutoTokenizer.from_pretrained("beyoru/Opera")
111
+ model = AutoModelForCausalLM.from_pretrained("beyoru/Opera", dtype="auto", device_map="auto")
112
+
113
+ msgs = [{"role": "user", "content": "Tính lãi phạt cho hóa đơn quá hạn 45 ngày, dư nợ 120 triệu."}]
114
+ ids = tok.apply_chat_template(msgs, tools=tools, add_generation_prompt=True, return_tensors="pt")
115
+ out = model.generate(ids.to(model.device), max_new_tokens=1024)
116
+ print(tok.decode(out[0][ids.shape[-1]:], skip_special_tokens=True))
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Results
122
+
123
+ Held-out validation: the 48 hardest multi-turn tool-calling episodes from a private
124
+ business-workflow set, scored every 5 steps during training.
125
+
126
+ | step | score |
127
+ |---|---|
128
+ | 0 (base) | 0.564 |
129
+ | 5 | 0.570 |
130
+ | 10 | 0.567 |
131
+ | 15 | **0.600** (peak, not checkpointed) |
132
+ | **20 (this checkpoint)** | 0.574 |
133
+
134
+ Only the final checkpoint was saved, so the released weights are **not** the peak of that
135
+ curve, and the measured gain of this checkpoint over the base on that set is small
136
+ (+0.010). Treat this as a targeted nudge on top of an already strong base — the value
137
+ here is a merged, ready-to-serve agentic checkpoint plus the serving recipe below, not a
138
+ large capability jump.
139
+
140
+ ---
141
+
142
+ ## Gotchas worth knowing
143
+
144
+ These cost real debugging time. They apply to the whole Qwen3.5/3.6 family, not just Opera.
145
+
146
+ 1. **Tool calls are XML, not JSON.** The model emits
147
+ `<tool_call><function=NAME><parameter=KEY>VALUE</parameter></function></tool_call>`.
148
+ A Hermes/JSON parser silently returns *zero* tool calls — which looks exactly like a
149
+ broken environment or a model that refuses to act. Use `--tool-call-parser qwen3_coder`,
150
+ or parse the XML yourself.
151
+ 2. **No `--trust-remote-code`** when serving with vLLM (see above).
152
+ 3. **Keep thinking on.** Training and evaluation both ran with reasoning enabled;
153
+ disabling it costs the most on exact-sequence style metrics.
154
+ 4. **Vision is inherited, untouched, untested.** The checkpoint keeps the base VL
155
+ architecture and vision tower. RL training was text-only and the multimodal path was
156
+ never evaluated here.
157
+
158
+ ---
159
+
160
+ ## Training details
161
+
162
+ | | |
163
+ |---|---|
164
+ | Algorithm | GRPO, 20 steps × batch 32 (640 prompts), 4 rollouts/prompt |
165
+ | Adapter | LoRA r32 / α64, lr 5e-6, merged into base at export |
166
+ | Data | xLAM + APIGen-MT function-calling traces, pre-filtered to ≤8192 tokens |
167
+ | Reward | rule-based (function name + argument-subset partial credit) + tool-call structural validity + Intuitor self-certainty, rule and self-certainty z-normalized separately then weighted 1.0 / 1.0, applied at EOS |
168
+ | Framework | verl |
169
+
170
+ Self-certainty is computed over full-vocabulary logits. At 27B that has to be **chunked**
171
+ (2048-token chunks, mirroring entropy chunking) or the run hangs during log-prob
172
+ recomputation with the GPU at 0% and no OOM message.
173
+
174
+ Training data is English function-calling; **Vietnamese ability comes from the base
175
+ model** — it is not something this RL stage taught.
176
+
177
+ ## Limitations
178
+
179
+ - Short RL run (20 steps). This is a targeted nudge on top of a strong base, not a
180
+ from-scratch agent.
181
+ - Validation set is small (n=48) and private, so differences of a few points are within
182
+ noise and cannot be independently reproduced. No public-leaderboard numbers are claimed.
183
+ - Released checkpoint is step 20, not the step-15 peak.
184
+ - Not evaluated on: long-context (>16K), multimodal input, non-agentic chat quality,
185
+ safety. Assume base-model behaviour on all of those.
186
+
187
+ ## Citation
188
+
189
+ ```bibtex
190
+ @misc{opera2026,
191
+ title = {Opera: GRPO + self-certainty RL for agentic tool-calling},
192
+ author = {beyoru},
193
+ year = {2026},
194
+ url = {https://huggingface.co/beyoru/Opera}
195
+ }
196
+ ```
197
+
198
+ Built on [Qwen3.6-27B](https://huggingface.co/Qwen/Qwen3.6-27B).
199
+ Self-certainty reward from [Intuitor](https://arxiv.org/abs/2505.19590).