Qwen2.5-7B Legal ID — GRPO (reasoning)
An Indonesian labour-law model that
reasons out loud before it answers, trained with
GRPO (Group Relative Policy Optimization) on top of
haikal1623/qwen2.5-7b-legal-id-sft.
It emits its reasoning inside visible think tags and then gives the answer in Bahasa
Indonesia — so a reader can see why it reached a conclusion, which matters a lot more for
legal questions than a bare answer does.
Stage 2 of 3. Stage 1 is the SFT model above; stage 3 is a retrieval layer over the actual
regulation texts.
Trained end to end on a single 8 GB RTX 4060 Ti plus free Kaggle GPU sessions.
What makes this one different
Most GRPO work rewards correctness alone. Here the reward is shaped by four separate
functions, because a legal answer can be right and still unusable:
| Reward | What it pushes the model toward |
|---|
| Format compliance | Keeping reasoning inside think tags so it can be parsed and shown separately |
| Reasoning length | Actually working through the problem instead of jumping to a verdict |
| ROUGE-L correctness | Staying close to the reference answer |
| Language purity | Answering in Bahasa Indonesia without drifting into English mid-sentence |
That last one is the practical problem with most multilingual fine-tunes for Indonesian:
the model starts in Bahasa and finishes in English. Rewarding language purity directly
turned out to matter more than expected.
Intended use
Indonesian labour-law Q&A where the user needs to see the reasoning, not just the answer.
Not legal advice. The visible reasoning makes the model easier to audit — it does not
make it correct. In the system this came from, answers are grounded against retrieved
regulation text before a user ever sees them. Used bare, it can reason fluently to a wrong
conclusion.
Training
| |
|---|
| Starting point | haikal1623/qwen2.5-7b-legal-id-sft |
| Method | GRPO via Unsloth + TRL |
| Reward design | Four custom functions (table above) |
| Domain | Indonesian labour-law regulations |
| Hardware | RTX 4060 Ti 8 GB; heavier runs on free Kaggle GPU sessions |
Usage
1from transformers import AutoTokenizer, AutoModelForCausalLM
2
3model_id = "haikal1623/qwen2.5-7b-legal-id-grpo"
4tokenizer = AutoTokenizer.from_pretrained(model_id)
5model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto")
6
7messages = [
8 {"role": "user", "content": "Apakah perusahaan boleh memutus kontrak PKWT sebelum masa berakhir?"},
9]
10inputs = tokenizer.apply_chat_template(
11 messages, add_generation_prompt=True, tokenize=True,
12 return_dict=True, return_tensors="pt",
13).to(model.device)
14
15outputs = model.generate(**inputs, max_new_tokens=1024)
16print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:], skip_special_tokens=True))
The response contains a reasoning block followed by the answer. Parse out the think
section if you only want to show users the conclusion.
Running it on a small GPU
The full three-stage pipeline was built under an 8 GB VRAM ceiling. Two decisions made
that work:
- Embedding and reranking stay on CPU. The GPU is reserved entirely for the LLM.
Slower per query, but it means the whole thing fits.
- The heavy stages ran on free Kaggle GPU sessions — fine-tuning and reasoning RL —
while everything else ran locally.
If you are trying to do reasoning RL on consumer hardware, those two choices are most of
the answer.
Limitations
- Visible reasoning is not verified reasoning. It can be confidently and fluently wrong.
- Bounded to the Indonesian labour-law material it was trained on; no post-training
amendments.
- Longer outputs than the SFT model by design — budget for the extra tokens.
- No formal legal-accuracy benchmark has been run.
Citation and contact
Built by Haikal Fairuzi Maulana — Banda Aceh, Indonesia.
Open to contract and retainer work on LLM fine-tuning, RAG systems, and full-stack delivery.