Downloads · 30 days
9
13% of all-time downloads
jmorenas/text-to-mongo-qlora
text-to-mongo-qlora is a text generation model from jmorenas. Use it when you need the model to write or continue text. It is set up for peft. The card lists the license as mit.
LoRA adapter that translates natural language questions into MongoDB find and aggregate queries.
Downloads · 30 days
9
13% of all-time downloads
All-time downloads
70
Public
Repo size
133 MB
Likes
0
Public
Click a slice to open those files.
.safetensors60.6 MB · 84%
From the Hugging Face model README
LoRA adapter that translates natural language questions into MongoDB find and aggregate queries.
Given a collection schema, allowed operators, and a plain-English intent, the model produces a valid MongoDB query as JSON — running locally on a single GPU with ~1 second inference latency.
Try it on Google Colab | Dataset | GitHub
| Model | Split | Syntax | Operators | Fields | Overall |
|---|---|---|---|---|---|
| Qwen 7B baseline (zero-shot) | eval (171) | 51.0% | 51.0% | 40.0% | 40.0% |
| Qwen 7B baseline (zero-shot) | held-out (423) | 53.8% | 53.5% | 39.9% | 39.9% |
| Qwen 7B + LoRA r=8 | eval (171) | 98.8% | 98.8% | 98.8% | 98.8% |
| Qwen 7B + LoRA r=8 | held-out (423) | 98.6% | 98.6% | 98.6% | 98.6% |
The held-out set uses 3 collection schemas the model never saw during training, testing generalization to unseen domains.
Each generated query is validated through four layers applied sequentially:
find needs filter, aggregate needs pipeline)$-operator used is in the allowed list, no unsafe operators ($where, $merge, $out)from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
base_model = "Qwen/Qwen2.5-Coder-7B-Instruct"
adapter = "jmorenas/text-to-mongo-qlora"
tokenizer = AutoTokenizer.from_pretrained(base_model)
model = AutoModelForCausalLM.from_pretrained(
base_model,
load_in_4bit=True,
device_map="auto",
)
model = PeftModel.from_pretrained(model, adapter)
schema = """Collection: orders (ecommerce)
Fields:
- order_id: string [identifier] — Order ID
- total: double [measure] — Order total
- status: string [enum] — Order status (pending, shipped, delivered)
- created_at: date [timestamp] — Creation date"""
allowed_ops = """Stage: $match, $group, $sort, $limit, $project
Expression: $sum, $avg, $gt, $gte, $lt, $lte, $in, $eq"""
intent = "Find all pending orders over $100"
messages = [
{"role": "system", "content": f"You are a MongoDB query generator.\n\nSchema:\n{schema}\n\nAllowed operators:\n{allowed_ops}"},
{"role": "user", "content": intent},
]
text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = tokenizer(text, return_tensors="pt").to(model.device)
output = model.generate(**inputs, max_new_tokens=256)
print(tokenizer.decode(output[0][inputs.input_ids.shape[1]:], skip_special_tokens=True))
Output:
{"type": "find", "filter": {"status": "pending", "total": {"$gt": 100}}}
User: "Find orders over $100 shipped last month"
│
▼
┌─────────────────────────────────┐
│ Schema: orders collection │
│ Fields: order_id, total, │
│ status, created_at │
│ Allowed ops: $match, $gte... │
└─────────────────────────────────┘
│
▼
┌─────────────────────────────────┐
│ Qwen 7B + LoRA adapter │
│ (4-bit quantized, ~5GB VRAM) │
└─────────────────────────────────┘
│
▼
{
"type": "find",
"filter": {
"total": {"$gt": 100},
"status": "shipped",
"created_at": {"$gte": {"$date": "2025-01-01T00:00:00Z"}}
}
}
The model reads the schema (field names, types, roles, enum values) and the allowed operators, then composes a query that respects both. It generalizes to schemas it has never seen.
| Parameter | Value |
|---|---|
| Base model | Qwen/Qwen2.5-Coder-7B-Instruct |
| Quantization | 4-bit NF4 + double quantization |
| LoRA rank | 8 (alpha=16) |
| LoRA targets | q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj |
| LoRA dropout | 0.05 |
| Epochs | 3 |
| Effective batch size | 16 (batch=4, grad_accum=4) |
| Learning rate | 2e-4 (cosine schedule, 5% warmup) |
| Max sequence length | 512 |
| Optimizer | paged_adamw_8bit |
| Framework | trl SFTTrainer (prompt-completion format) |
| Loss | Completion-only (prompt tokens masked) |
| Training time | ~11 minutes on RTX 5090 |
| VRAM usage | ~5 GB |
| Train loss | 0.013 |
jmorenas/text-to-mongo-dataset-qlora — 1,544 train / 171 eval / 423 held-out examples across 19 collection schemas (16 train + 3 held-out).
The dataset is fully synthetic — generated deterministically from hand-crafted schemas and intent patterns. 12 generator patterns produce query types including filters, aggregations, projections, time ranges, top-N, counts, exists checks, enum filters, and date bucketing. Augmentation strategies (field name shuffling, date variation, operator subsetting, negatives) multiply the base examples ~7x.
find and aggregate queries only — does not generate update, delete, or insertOnemerge_and_unload() produces garbage) — must be used as a PeftModel wrapperMIT