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
from transformers import AutoTokenizer, AutoModelForCausalLM
model_id = "haikal1623/qwen2.5-7b-legal-id-grpo"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto")
messages = [
{"role": "user", "content": "Apakah perusahaan boleh memutus kontrak PKWT sebelum masa berakhir?"},
]
inputs = tokenizer.apply_chat_template(
messages, add_generation_prompt=True, tokenize=True,
return_dict=True, return_tensors="pt",
).to(model.device)
outputs = model.generate(**inputs, max_new_tokens=1024)
print(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.
- GitHub: haikalmol
- LinkedIn: haikal-fairuzi-maulana
- Web: creagen.co
Open to contract and retainer work on LLM fine-tuning, RAG systems, and full-stack delivery.