-
Stage 1: Accuracy-focused training (V3)
- Trained from Qwen3-1.7B base
- Dataset: ~40K samples (stage2.parquet)
- Reward: Correctness (1.0) + Format (0.1) + Efficiency (0.3) + Refusal (0.3)
- Config: max_steps=5000, LR=5e-7, temp=1.2
- Best checkpoint: step 100 (early stopping, highest accuracy)
-
Stage 2: Efficiency optimization (V4)
- Loaded from Stage 1 checkpoint-100
- Focus: Reduce verbosity, discourage
<think> tags
- Reward weights: Efficiency=1.0, Correctness=0.5, Format=0.1, Refusal=0.3
- Config: max_steps=3000, LR=2e-7
- Selected checkpoint: step 1100
- Result: 36% reduction in response tokens
1# Combined Reward Formula
2total_reward = (
3 format_weight * format_reward + # Valid <tool_call> JSON (0.0-1.0)
4 correct_weight * correctness_reward + # Tool name + arguments match (0.0-1.0)
5 refusal_weight * refusal_reward + # +1.0 correct refusal, -1.0 hallucination
6 efficiency_weight * efficiency_reward # Penalty for verbose <think>
7)
8
9# Stage 1 Weights (Accuracy Focus)
10STAGE1_WEIGHTS = {
11 'format': 0.2,
12 'correctness': 1.0, # Main focus
13 'efficiency': 0.2,
14 'refusal': 0.3,
15}
16
17# Stage 2 Weights (Efficiency Focus)
18STAGE2_WEIGHTS = {
19 'format': 0.1,
20 'correctness': 0.5, # Reduced - already accurate from Stage 1
21 'efficiency': 1.0, # Main focus - penalize <think> tags
22 'refusal': 0.3,
23}
1import torch
2from transformers import AutoTokenizer, AutoModelForCausalLM
3
4model_name = "contextboxai/Qwen3-1.7B-FC"
5tokenizer = AutoTokenizer.from_pretrained(model_name)
6model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.bfloat16, device_map="auto")
7
8# Define tools
9tools = [{
10 "name": "get_weather",
11 "description": "Get weather for a location",
12 "parameters": {
13 "type": "object",
14 "properties": {
15 "location": {"type": "string", "description": "City name"}
16 },
17 "required": ["location"]
18 }
19}]
20
21messages = [{"role": "user", "content": "What's the weather in Tokyo?"}]
22
23prompt = tokenizer.apply_chat_template(
24 messages,
25 tools=tools,
26 add_generation_prompt=True,
27 tokenize=False,
28 enable_thinking=False # Disable thinking for efficiency
29)
30
31inputs = tokenizer(prompt, return_tensors="pt")
32outputs = model.generate(**inputs, max_new_tokens=256)
33response = tokenizer.decode(outputs[0], skip_special_tokens=True)
34print(response)
1<tool_call>
2{"name": "get_weather", "arguments": {"location": "Tokyo"}}
3</tool_call>
1from vllm import LLM, SamplingParams
2
3llm = LLM(model="contextboxai/Qwen3-1.7B-FC")
4sampling_params = SamplingParams(temperature=0, max_tokens=256)
5
6# Generate with same prompt format as above
7outputs = llm.generate([prompt], sampling_params)
1# Example: Customer asks about their order
2tools = [
3 {"name": "lookup_order", "parameters": {"order_id": "string"}},
4 {"name": "create_ticket", "parameters": {"issue": "string", "priority": "string"}},
5 {"name": "get_faq", "parameters": {"topic": "string"}}
6]
7
8# User: "Đơn hàng #12345 của tôi ở đâu rồi?"
9# Model output:
10# <tool_call>
11# {"name": "lookup_order", "arguments": {"order_id": "12345"}}
12# </tool_call>
13
14# User: "Tôi muốn đổi trả sản phẩm"
15# Model output:
16# <tool_call>
17# {"name": "create_ticket", "arguments": {"issue": "product_return", "priority": "normal"}}
18# </tool_call>
1@misc{qwen3-fc,
2 title={Qwen3-1.7B-FC: Efficient Function Calling via GRPO Fine-tuning},
3 author={ContextboxAI},
4 year={2024},
5 howpublished={\url{https://huggingface.co/contextboxai/Qwen3-1.7B-FC}},
6}