153 lines
6.7 KiB
Markdown
153 lines
6.7 KiB
Markdown
|
|
---
|
|||
|
|
license: apache-2.0
|
|||
|
|
base_model: unsloth/gemma-3-270m-it
|
|||
|
|
tags:
|
|||
|
|
- text-generation
|
|||
|
|
- lora
|
|||
|
|
- qlora
|
|||
|
|
- gguf
|
|||
|
|
- transaction-parser
|
|||
|
|
language:
|
|||
|
|
- en
|
|||
|
|
- hi
|
|||
|
|
library_name: peft
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# txn-parser / gemma-3-270m
|
|||
|
|
|
|||
|
|
QLoRA fine-tune of [`unsloth/gemma-3-270m-it`](https://huggingface.co/unsloth/gemma-3-270m-it) for
|
|||
|
|
extracting structured transaction data (amount, currency, item, category,
|
|||
|
|
type) from free-form Indian-English / code-switched speech and text.
|
|||
|
|
|
|||
|
|
This model lives in subfolder **`gemma-3-270m/`** of the
|
|||
|
|
[`kartikey31/txn-parser`](https://huggingface.co/kartikey31/txn-parser) repo, alongside
|
|||
|
|
sibling fine-tunes of other base models trained on the same data.
|
|||
|
|
|
|||
|
|
## What's in here
|
|||
|
|
|
|||
|
|
- `gemma-3-270m/adapters/` — PEFT LoRA adapter (rank 32). Load on top of the base model
|
|||
|
|
with `peft.PeftModel.from_pretrained(base, "kartikey31/txn-parser", subfolder="gemma-3-270m/adapters")`.
|
|||
|
|
- `gemma-3-270m/gguf/` — merged GGUF builds at multiple quantization levels
|
|||
|
|
(file names follow `txn-parser-gemma-3-270m-<QUANT>.gguf`):
|
|||
|
|
- [`gemma-3-270m/gguf/txn-parser-gemma-3-270m-F16.gguf`](https://huggingface.co/kartikey31/txn-parser/resolve/main/gemma-3-270m/gguf/txn-parser-gemma-3-270m-F16.gguf) (542.8 MB)
|
|||
|
|
- [`gemma-3-270m/gguf/txn-parser-gemma-3-270m-Q4_K_M.gguf`](https://huggingface.co/kartikey31/txn-parser/resolve/main/gemma-3-270m/gguf/txn-parser-gemma-3-270m-Q4_K_M.gguf) (253.1 MB)
|
|||
|
|
- [`gemma-3-270m/gguf/txn-parser-gemma-3-270m-Q5_K_M.gguf`](https://huggingface.co/kartikey31/txn-parser/resolve/main/gemma-3-270m/gguf/txn-parser-gemma-3-270m-Q5_K_M.gguf) (260.0 MB)
|
|||
|
|
- [`gemma-3-270m/gguf/txn-parser-gemma-3-270m-Q6_K.gguf`](https://huggingface.co/kartikey31/txn-parser/resolve/main/gemma-3-270m/gguf/txn-parser-gemma-3-270m-Q6_K.gguf) (283.0 MB)
|
|||
|
|
- [`gemma-3-270m/gguf/txn-parser-gemma-3-270m-Q8_0.gguf`](https://huggingface.co/kartikey31/txn-parser/resolve/main/gemma-3-270m/gguf/txn-parser-gemma-3-270m-Q8_0.gguf) (291.5 MB)
|
|||
|
|
|
|||
|
|
## Training data
|
|||
|
|
|
|||
|
|
- 93,348 teacher-labeled examples (`data/distill/train.jsonl`)
|
|||
|
|
- 300 held-out eval examples (`data/distill/eval.jsonl`)
|
|||
|
|
- Validator-gated: every row's `output` passes the project's grammar +
|
|||
|
|
amount-parser semantic validator.
|
|||
|
|
|
|||
|
|
## Training config
|
|||
|
|
|
|||
|
|
| Knob | Value |
|
|||
|
|
|---|---|
|
|||
|
|
| Base model | `unsloth/gemma-3-270m-it` |
|
|||
|
|
| Method | QLoRA (4-bit) via Unsloth |
|
|||
|
|
| LoRA rank | 32 (alpha 64, dropout 0.0) |
|
|||
|
|
| Epochs | 2 |
|
|||
|
|
| Batch size (train) | 64 |
|
|||
|
|
| Grad accumulation | 1 |
|
|||
|
|
| Eval batch size | 4 |
|
|||
|
|
| Max seq length | 1024 |
|
|||
|
|
| Learning rate | 2e-4 (warmup 3%) |
|
|||
|
|
| Started | |
|
|||
|
|
| Finished | |
|
|||
|
|
|
|||
|
|
## System prompt (use this EXACTLY)
|
|||
|
|
|
|||
|
|
The model was trained with one specific system prompt and Gemma/Smol/Qwen
|
|||
|
|
chat template. If you paraphrase the prompt or skip the chat template,
|
|||
|
|
quality degrades quickly. Copy-paste this verbatim into your inference
|
|||
|
|
client (no leading/trailing whitespace, no edits):
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
You convert voice-transcribed transaction descriptions into structured JSON.
|
|||
|
|
|
|||
|
|
Output ONLY a JSON object with this schema, no other text:
|
|||
|
|
{"transactions":[{"amount":<number>,"currency":"INR"|"USD","item":"<lowercase singular noun phrase>","category":"<enum>","type":"expense"|"income"}]}
|
|||
|
|
|
|||
|
|
Categories: Food, Drinks, Groceries, Transport, Shopping, Entertainment, Bills, Health, Education, Personal, Gifts, Income, Other.
|
|||
|
|
|
|||
|
|
Rules:
|
|||
|
|
- Currency defaults to INR. Use USD only when the input explicitly says "dollars" or contains "$".
|
|||
|
|
- Amounts: "k" = ×1000, "hazaar" = ×1000, "sau" = ×100, "lakh" = ×100000. Convert number-words ("five hundred") to digits.
|
|||
|
|
- type is "expense" by default; "income" only for explicit salary, cashback, refund, gift received, payment received.
|
|||
|
|
- For disfluencies and corrections ("500 wait no 600"), output the CORRECTED amount only.
|
|||
|
|
- For ambiguous items ("that thing", "stuff"), use item "unspecified" and category "Other".
|
|||
|
|
- Item field: lowercase singular noun phrase ("uber ride", "beer", "chai" — not "Beers" or "Uber").
|
|||
|
|
- Multi-transaction inputs become multiple array entries in spoken order.
|
|||
|
|
- Category heuristics: uber/ola/auto/petrol/bus/metro → Transport; beer/wine/chai/coffee/juice → Drinks; rent/electricity/wifi/recharge/gas → Bills; movie/netflix/concert → Entertainment; doctor/medicine/hospital → Health.
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Source of truth: [`scripts/_lib.py`](https://github.com/kartikeychoudhary/txn-parser/blob/main/scripts/_lib.py)
|
|||
|
|
constant `SYSTEM_PROMPT`. Don't retype it — pull from `_lib.py` or this README.
|
|||
|
|
|
|||
|
|
## Download a single GGUF
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
huggingface-cli download kartikey31/txn-parser \
|
|||
|
|
gemma-3-270m/gguf/txn-parser-gemma-3-270m-Q4_K_M.gguf \
|
|||
|
|
--local-dir .
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Inference (Python, llama-cpp-python)
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
from llama_cpp import Llama
|
|||
|
|
|
|||
|
|
SYSTEM_PROMPT = '''You convert voice-transcribed transaction descriptions into structured JSON.
|
|||
|
|
|
|||
|
|
Output ONLY a JSON object with this schema, no other text:
|
|||
|
|
{"transactions":[{"amount":<number>,"currency":"INR"|"USD","item":"<lowercase singular noun phrase>","category":"<enum>","type":"expense"|"income"}]}
|
|||
|
|
|
|||
|
|
Categories: Food, Drinks, Groceries, Transport, Shopping, Entertainment, Bills, Health, Education, Personal, Gifts, Income, Other.
|
|||
|
|
|
|||
|
|
Rules:
|
|||
|
|
- Currency defaults to INR. Use USD only when the input explicitly says "dollars" or contains "$".
|
|||
|
|
- Amounts: "k" = ×1000, "hazaar" = ×1000, "sau" = ×100, "lakh" = ×100000. Convert number-words ("five hundred") to digits.
|
|||
|
|
- type is "expense" by default; "income" only for explicit salary, cashback, refund, gift received, payment received.
|
|||
|
|
- For disfluencies and corrections ("500 wait no 600"), output the CORRECTED amount only.
|
|||
|
|
- For ambiguous items ("that thing", "stuff"), use item "unspecified" and category "Other".
|
|||
|
|
- Item field: lowercase singular noun phrase ("uber ride", "beer", "chai" — not "Beers" or "Uber").
|
|||
|
|
- Multi-transaction inputs become multiple array entries in spoken order.
|
|||
|
|
- Category heuristics: uber/ola/auto/petrol/bus/metro → Transport; beer/wine/chai/coffee/juice → Drinks; rent/electricity/wifi/recharge/gas → Bills; movie/netflix/concert → Entertainment; doctor/medicine/hospital → Health.'''
|
|||
|
|
|
|||
|
|
llm = Llama(
|
|||
|
|
model_path="txn-parser-gemma-3-270m-Q4_K_M.gguf",
|
|||
|
|
n_gpu_layers=-1, n_ctx=2048,
|
|||
|
|
)
|
|||
|
|
out = llm.create_chat_completion(
|
|||
|
|
messages=[
|
|||
|
|
{"role": "system", "content": SYSTEM_PROMPT},
|
|||
|
|
{"role": "user", "content": "200 ka samosa"},
|
|||
|
|
],
|
|||
|
|
temperature=0.0,
|
|||
|
|
)
|
|||
|
|
print(out["choices"][0]["message"]["content"])
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Inference (CLI, llama.cpp)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
./llama-cli -m txn-parser-gemma-3-270m-Q4_K_M.gguf \
|
|||
|
|
--grammar-file scripts/grammar.gbnf \
|
|||
|
|
--system-prompt "$(cat system_prompt.txt)" \
|
|||
|
|
-p "200 ka samosa" -n 256
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Reproduce
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git clone https://github.com/kartikeychoudhary/txn-parser.git
|
|||
|
|
cd txn-parser && bash setup.sh
|
|||
|
|
python scripts/train_and_publish.py --only gemma-3-270m
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
*Auto-published by `scripts/train_and_publish.py` on 2026-05-22T21:33:31.274220+00:00.*
|