Downloads · 30 days
0
hatheemr/margent-planner-qwen2.5-3b-lora
margent-planner-qwen2.5-3b-lora is a machine learning model from hatheemr. Use it for the machine learning task on the model card, and read the license before you ship it in a product. It is set up for transformers. The card lists the license as apache-2.0.
- Developed by: hatheemr - License: apache-2.0 - Finetuned from model : unsloth/Qwen2.5-3B-Instruct-bnb-4bit
Downloads · 30 days
0
Access
Public
Updated Aug 28, 2026
Repo size
131 MB
Likes
0
Public
Click a slice to open those files.
.safetensors120 MB · 91%
From the Hugging Face model README
A LoRA adapter that replaces the planner node of MARGENT (Lanka Market
Scout), a LangGraph multi-agent system that researches business ideas for the
Sri Lankan market.
Given a business idea and the user's prior-analysis history, it emits a strict
ResearchPlan JSON object: a restated idea, 3–4 market questions, 2–3 pricing
questions, and 3–5 competitor seeds — all specific enough to be fed directly to
a web search tool.
The fine-tuning was prominently initiated to improve model to derive plans specifically for Sri Lanka.
The adapter was trained to replace gpt-4o-mini at this one node, so the
pipeline can run a locally-hosted model where the task is narrow and
schema-constrained, while keeping a frontier model for open-ended writing.
Evaluated on 40 held-out examples, greedy decoding, compared against the untuned base model on the identical prompt.
| Metric | Base Qwen2.5-3B | Fine-tuned | Δ |
|---|---|---|---|
| Valid JSON parsed | 100.0% | 100.0% | +0.0 pp |
| Correct schema keys | 100.0% | 100.0% | +0.0 pp |
| List counts in range | 100.0% | 100.0% | +0.0 pp |
| No generic competitor seeds | 100.0% | 100.0% | +0.0 pp |
| Questions locality-anchored | 35.0% | 100.0% | +65.0 pp |
| All checks pass | 35.0% | 100.0% | +65.0 pp |
| Mean latency (T4, 4-bit) | 11.63 s | 14.29 s | +2.65 s |
The base model was already reliable at format: it produced valid JSON with the right keys and list lengths on every single example. Fine-tuning changed something else — grounding.
Untuned, the model wrote generic market-research questions ("what are current consumer trends in this sector") that return nothing useful when passed to a search tool. After fine-tuning, questions consistently name the market, a city, a currency or a year ("coffee consumption trends Sri Lanka 2024", "average monthly rent for retail space in Nugegoda LKR"). Since every downstream node in MARGENT depends on these questions being searchable, this is the difference between a working pipeline and a pipeline that retrieves noise.
Latency increased because the tuned model produces fuller, more specific plans rather than terse generic ones — an accepted trade for usable output.
from unsloth import FastLanguageModel
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "USERNAME/margent-planner-qwen2.5-3b-lora",
max_seq_length = 2048,
load_in_4bit = True,
)
FastLanguageModel.for_inference(model)
SYSTEM_PROMPT = (
"You are planning market research for the SRI LANKAN market specifically.\n"
"Create a research plan for the given business idea.\n"
"Questions must be concrete and searchable "
"(good: 'coffee consumption trends Sri Lanka 2024', "
"bad: 'what is the market like'). "
"Competitor seeds should be real Sri Lankan or regional companies where "
"you know of any, otherwise specific categories to search for.\n"
"Respond with ONLY a JSON object with these keys: "
"product_idea (string, one-sentence restatement), "
"market_questions (3-4 strings), "
"pricing_questions (2-3 strings), "
"competitor_seeds (3-5 strings)."
)
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": (
"Business idea: a mobile bicycle repair service for office workers in Colombo\n\n"
"Context from this user's history (use it to avoid repeating work and to "
"personalize):\nNo previous analyses for this user."
)},
]
text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
enc = tokenizer(text, return_tensors="pt").to("cuda")
out = model.generate(**enc, max_new_tokens=512, do_sample=False)
print(tokenizer.decode(out[0][enc["input_ids"].shape[1]:], skip_special_tokens=True))
The prompt format is not optional. The adapter was trained on this exact system message with the idea and history in the user turn. Changing the wording degrades output quality, often silently.
IDEA: a mobile bicycle repair service for office workers in Colombo
{
"product_idea": "A mobile bicycle repair service for office workers in Colombo.",
"market_questions": [
"bicycle ownership statistics in Colombo 2024",
"office worker commuting habits in Colombo",
"demand for mobile services among office workers in Sri Lanka"
],
"pricing_questions": [
"average cost of bicycle repairs in Colombo",
"willingness to pay for mobile bike repair services in Sri Lanka"
],
"competitor_seeds": [
"Bike Fix Sri Lanka",
"Colombo Bike Rentals",
"Sri Lanka Bicycle Tours",
"Ceylon Cycle Rental"
]
}
| Base model | Qwen/Qwen2.5-3B-Instruct (4-bit, via unsloth/Qwen2.5-3B-Instruct-bnb-4bit) |
| Method | QLoRA (parameter-efficient; base weights frozen) |
| LoRA config | r=16, alpha=16, dropout=0 |
| Target modules | q, k, v, o, gate, up, down projections |
| Learning rate | 2e-4, linear schedule, 5% warmup |
| Epochs | 2 (210 steps) |
| Batch | 1 × 8 grad accumulation (effective 8) |
| Optimizer | adamw_8bit |
| Max sequence length | 2048 |
| Hardware | 1 × NVIDIA T4 (Google Colab) |
| Framework | Unsloth + TRL SFTTrainer |
Loss was masked to the assistant turn only (train_on_responses_only), so the
model is graded solely on producing the JSON, not on reconstructing the prompt.
Loss curve: train 0.571 → 0.310, validation 0.529 → 0.369. Validation decreased monotonically at every checkpoint and flattened over the final 10 steps (0.3699 → 0.3694), with a final train/validation gap of 0.06 — converged, with no sign of overfitting.
Approximately 840 training and 56 validation examples, generated synthetically and distilled from a stronger teacher model using MARGENT's production planner prompt.
Input diversity was forced by rotating a grid of 28 sectors × 19 regions × 8 business scales × 9 phrasing styles, rather than sampling ideas from a single prompt (which collapses toward one archetype). Phrasing styles deliberately included terse fragments, phone-typed lowercase with misspellings, and English mixed with Sinhala/Tamil terms, so the model handles the messy input real users produce. Roughly 45% of examples carry a synthetic user-history block matching the format MARGENT's intake node emits.
Every generated sample was filtered programmatically before training:
The dataset is not released.
The base model, Qwen2.5-3B-Instruct, is released under the Qwen Research
License — unlike most other Qwen2.5 sizes, which are Apache-2.0. This adapter
inherits those terms. Review the license before any commercial use.
@misc{margent_planner_lora,
title = {MARGENT Planner: a LoRA adapter for structured market-research planning},
author = {YOUR NAME},
year = {2026},
url = {https://huggingface.co/USERNAME/margent-planner-qwen2.5-3b-lora}
}
Trained with Unsloth and Hugging Face TRL.