153 lines
5.8 KiB
Markdown
153 lines
5.8 KiB
Markdown
|
|
---
|
|||
|
|
license: apache-2.0
|
|||
|
|
base_model: Qwen/Qwen2.5-Coder-1.5B-Instruct
|
|||
|
|
language:
|
|||
|
|
- en
|
|||
|
|
pipeline_tag: text-generation
|
|||
|
|
tags:
|
|||
|
|
- router
|
|||
|
|
- prompt-router
|
|||
|
|
- structured-output
|
|||
|
|
- json
|
|||
|
|
- code
|
|||
|
|
- qwen2.5-coder
|
|||
|
|
- gguf
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# DevRouter-1.5B
|
|||
|
|
|
|||
|
|
**A tiny, fast router that turns a raw developer prompt into a single structured JSON decision.**
|
|||
|
|
|
|||
|
|
DevRouter-1.5B reads a raw coding prompt and returns one JSON object that (1) rewrites the prompt
|
|||
|
|
into a cleaner version, (2) classifies its **intent**, **complexity**, and a suggested **route**
|
|||
|
|
(which model tier to send it to), and (3) flags **missing context** the developer should have
|
|||
|
|
included. It is meant to sit *in front of* your expensive models and make a cheap, deterministic
|
|||
|
|
triage call in ~1–3 seconds on a single consumer GPU.
|
|||
|
|
|
|||
|
|
It is a fine-tune of **Qwen2.5-Coder-1.5B-Instruct** (Apache 2.0), distilled on a dataset of
|
|||
|
|
developer prompts labelled by a stronger teacher model.
|
|||
|
|
|
|||
|
|
## Output schema
|
|||
|
|
|
|||
|
|
Every response is a single JSON object with exactly these five fields:
|
|||
|
|
|
|||
|
|
| field | type | values |
|
|||
|
|
|---|---|---|
|
|||
|
|
| `rewrite` | string | a clearer version of the prompt, preserving the original intent |
|
|||
|
|
| `intent` | enum | `debug` · `refactor` · `feature` · `explain` · `documentation` · `boilerplate` · `architecture` · `review` · `optimize` · `other` |
|
|||
|
|
| `complexity` | enum | `low` · `medium` · `high` |
|
|||
|
|
| `route` | enum | `small_local` · `medium_api` · `large_api` |
|
|||
|
|
| `missing` | array of strings | context the prompt should have included (empty if nothing) |
|
|||
|
|
|
|||
|
|
### Example
|
|||
|
|
|
|||
|
|
**Input (user message):**
|
|||
|
|
> My Flask app 500s on POST /upload with RequestEntityTooLarge, how do I fix it?
|
|||
|
|
|
|||
|
|
**Output:**
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"rewrite": "I'm encountering a 500 Internal Server Error on my Flask app when handling POST /upload. The error is 'RequestEntityTooLarge'. How can I resolve this issue?",
|
|||
|
|
"intent": "debug",
|
|||
|
|
"complexity": "low",
|
|||
|
|
"route": "small_local",
|
|||
|
|
"missing": ["Flask version", "Python version"]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Quick start
|
|||
|
|
|
|||
|
|
The router system prompt is **baked into the model's chat template**, so you do not need to supply a
|
|||
|
|
system prompt — just send the raw developer prompt as the user message.
|
|||
|
|
|
|||
|
|
### Ollama
|
|||
|
|
```bash
|
|||
|
|
# from the -GGUF repo (Modelfile + DevRouter-1.5B-Q8_0.gguf)
|
|||
|
|
ollama create devrouter -f Modelfile
|
|||
|
|
ollama run devrouter "refactor this giant function into smaller ones"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### llama.cpp
|
|||
|
|
```bash
|
|||
|
|
llama-server -m DevRouter-1.5B-Q8_0.gguf -c 8192 -ngl 99 --parallel 1
|
|||
|
|
# then POST to /v1/chat/completions with just a user message, temperature 0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Transformers
|
|||
|
|
```python
|
|||
|
|
from transformers import AutoModelForCausalLM, AutoTokenizer
|
|||
|
|
tok = AutoTokenizer.from_pretrained("aipster/DevRouter-1.5B")
|
|||
|
|
model = AutoModelForCausalLM.from_pretrained("aipster/DevRouter-1.5B")
|
|||
|
|
msgs = [{"role": "user", "content": "write a FastAPI POST /items endpoint with a Pydantic model"}]
|
|||
|
|
inputs = tok.apply_chat_template(msgs, add_generation_prompt=True, return_tensors="pt")
|
|||
|
|
out = model.generate(inputs, max_new_tokens=1408, do_sample=False)
|
|||
|
|
print(tok.decode(out[0][inputs.shape[1]:], skip_special_tokens=True))
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Use **greedy decoding (`temperature=0`)** for stable, parseable JSON.
|
|||
|
|
|
|||
|
|
## Evaluation
|
|||
|
|
|
|||
|
|
Evaluated on a held-out, intent-stratified validation split (`val`, in-distribution) and an
|
|||
|
|
out-of-distribution split (`holdout`, no GitHub-issue sources). Metrics: rate of valid JSON
|
|||
|
|
(strict schema parse) and accuracy of `intent` / `route` / `complexity` against the teacher labels.
|
|||
|
|
|
|||
|
|
| metric | fp16 (val / holdout) | Q8_0 GGUF (val / holdout) |
|
|||
|
|
|---|---|---|
|
|||
|
|
| JSON validity | 0.973 / 0.955 | 0.965 / 0.946 |
|
|||
|
|
| intent accuracy | 0.708 / 0.613 | 0.665 / 0.586 |
|
|||
|
|
| route accuracy | 0.739 / 0.604 | 0.719 / 0.631 |
|
|||
|
|
| complexity accuracy | 0.719 / 0.685 | 0.708 / 0.676 |
|
|||
|
|
|
|||
|
|
Per-intent accuracy (Q8_0, val):
|
|||
|
|
|
|||
|
|
| intent | acc | intent | acc |
|
|||
|
|
|---|---|---|---|
|
|||
|
|
| debug | 0.82 | architecture | 0.72 |
|
|||
|
|
| refactor | 0.72 | documentation | 0.56 |
|
|||
|
|
| explain | 0.73 | boilerplate | 0.64 |
|
|||
|
|
| feature | 0.58 | review | 0.43 |
|
|||
|
|
| optimize | 0.50 | | |
|
|||
|
|
|
|||
|
|
## Performance
|
|||
|
|
|
|||
|
|
Single RTX 3090, Q8_0 GGUF via llama.cpp (single stream):
|
|||
|
|
|
|||
|
|
- **Generation: ~280 tokens/s** (~3.6 ms/token, constant across output lengths)
|
|||
|
|
- **Prompt eval (prefill): ~10,000–13,000 tokens/s**
|
|||
|
|
- **Latency per routing call: ~1–3 s** (up to ~5 s for the longest outputs)
|
|||
|
|
|
|||
|
|
Throughput scales further with batching/concurrency.
|
|||
|
|
|
|||
|
|
## Limitations
|
|||
|
|
|
|||
|
|
- **No PII detection.** An earlier schema included a PII flag; it was removed from v1.1 because the
|
|||
|
|
training data had too few PII-positive examples (~2.4%) to learn it reliably. Do **not** use this
|
|||
|
|
model for privacy/safety filtering. (Planned for a future data-focused release.)
|
|||
|
|
- **Weaker on rare intents.** `review` and `documentation` are under-represented and noisier in the
|
|||
|
|
training data, and accuracy on them is lower.
|
|||
|
|
- **Source bias / OOD gap.** Training prompts skew heavily toward GitHub-issue-style text, so intent
|
|||
|
|
accuracy drops ~10 points on out-of-distribution prompts. Treat `route`/`complexity` as advisory.
|
|||
|
|
- **Quantization sensitivity.** This is a small model doing strict structured output. **Q6_K and
|
|||
|
|
below break the JSON** (validity collapses); ship **Q8_0** or **F16** only. Always validate a
|
|||
|
|
quant before relying on it.
|
|||
|
|
|
|||
|
|
## Training
|
|||
|
|
|
|||
|
|
- **Base:** Qwen2.5-Coder-1.5B-Instruct (Apache 2.0)
|
|||
|
|
- **Method:** QLoRA (4-bit), rank 16, 2 epochs, effective batch 16, `train_on_responses_only`
|
|||
|
|
- **Data:** ~2.6k developer prompts, each labelled by a stronger teacher model into the 5-field
|
|||
|
|
schema, filtered by a judge model and capped per intent. Distillation sources permit training and
|
|||
|
|
open release of derived weights.
|
|||
|
|
|
|||
|
|
## Intended use
|
|||
|
|
|
|||
|
|
Pre-routing / triage of developer prompts in an LLM application: rewriting, intent/complexity
|
|||
|
|
classification, and model-tier selection. **Not** intended for safety filtering, PII detection, or
|
|||
|
|
as a general assistant.
|
|||
|
|
|
|||
|
|
## License
|
|||
|
|
|
|||
|
|
Apache 2.0, inherited from the base model. You are free to use, modify, and redistribute, including
|
|||
|
|
commercially.
|