Views
No views yet
logs/eval_v2.json of the GitHub repo)| Metric | v1 (reward-hacked) | v2 (this adapter) |
|---|---|---|
| Detection rate | 100.0% | 99.3% |
| False positive rate | 36.0% | 6.7% (5× better) |
| F1 | 0.96 | 0.99 |
| Bench size | 135 | 174 evaluated (175 total, 1 skipped) |
| Difficulty | n | Detection |
|---|---|---|
| Easy | 26 | 100% |
| Medium | 66 | 100% |
| Hard | 18 | 100% |
| Novel | 34 | 97% |
novel (post-2024 attack patterns) is the small honest crack that confirms the model is not collapsing to "always flag."detection=100% / FPR=36% — a textbook reward-hacking fingerprint. The model had learned to flag everything and then defend the over-flagging with plausible-sounding reasoning. The reward components were:β = 0.08 → 0.15) so the model can't drift far from the base distribution under the new reward shape.1from transformers import AutoTokenizer, AutoModelForCausalLM
2from peft import PeftModel
3import torch
4
5base_model_id = "Qwen/Qwen2.5-7B-Instruct"
6adapter_id = "ujjwalpardeshi/chakravyuh-analyzer-lora-v2"
7
8tokenizer = AutoTokenizer.from_pretrained(base_model_id)
9base = AutoModelForCausalLM.from_pretrained(
10 base_model_id,
11 torch_dtype=torch.bfloat16,
12 device_map="auto",
13)
14model = PeftModel.from_pretrained(base, adapter_id)
15model.eval()
16
17system_prompt = (
18 "You are Chakravyuh's Behavioral Analyzer, a fraud detection AI deployed "
19 "on-device to monitor real-time chat for Indian UPI scam patterns. "
20 "Output strict JSON with `score` in [0,1], `signals` from the taxonomy, "
21 "and `explanation`."
22)
23
24user_prompt = (
25 "Scammer messages:\n"
26 "Urgent! Your bank account will be frozen. Share OTP to verify identity.\n\n"
27 "Analyze these messages. Return strict JSON only."
28)
29
30messages = [
31 {"role": "system", "content": system_prompt},
32 {"role": "user", "content": user_prompt},
33]
34prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
35inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
36
37with torch.no_grad():
38 out = model.generate(
39 **inputs,
40 max_new_tokens=160,
41 do_sample=False,
42 temperature=0.0,
43 pad_token_id=tokenizer.eos_token_id,
44 )
45response = tokenizer.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True)
46print(response)1{
2 "score": 0.95,
3 "signals": ["urgency", "info_request", "impersonation"],
4 "explanation": "Asks for OTP with urgency pressure from a self-claimed bank agent; matches OTP-theft scam pattern."
5}training/grpo_analyzer.py:_filter_soft_leakage)trainer_state.json (full training trajectory) is at logs/v2_trainer_state.json in the source repo.1@software{pardeshi2026chakravyuh,
2 title = {Chakravyuh: A Multi-Agent RL Environment for Indian UPI Fraud Detection},
3 author = {Pardeshi, Ujjwal},
4 year = {2026},
5 url = {https://github.com/UjjwalPardeshi/Chakravyuh}
6}