Aller au contenu
ModelVérifiéExterne
Télécharger

Ec SFT Qwen25 7b LoRA

This repository contains a PEFT LoRA adapter for Qwen/Qwen2.5-7B-Instruct. It was trained as the v0.5.0 Stage-1 dense-recall adapter for Bengali and Banglish Bangladesh Election Commission (EC) and National ID (NID)...

TypeLoRAModèle de baseQwen/Qwen2.5-7B-InstructVersionRevision d2968a9Éditeur@ehzawadCClasse

Source du modèle

Type
LoRA
Taille du fichier
616 MB
Modèle de base
Qwen/Qwen2.5-7B-Instruct
Version
vRevision d2968a9
Mis à jour
3 oct. 2026
Éditeur
@ehzawad
Téléchargements
13
Paramètres
7B
Tâches
Génération de texte
Source
Hugging Face

Description de la source

EC/NID Bengali-Banglish Assistant LoRA v0.5.0

This repository contains a PEFT LoRA adapter for Qwen/Qwen2.5-7B-Instruct. It was trained as the v0.5.0 Stage-1 dense-recall adapter for Bengali and Banglish Bangladesh Election Commission (EC) and National ID (NID) procedural questions.

This is an adapter-only repository. It does not include the Qwen2.5 base model weights.

Intended Use

The adapter is intended for citizen-facing EC/NID assistance: NID correction, new voter registration, lost/re-issued cards, voter-area transfer, selected overseas mission questions, and stable election-procedure explanations.

For production use, pair it with retrieval over official sources such as services.nidw.gov.bd, ecs.gov.bd, and the 105 helpline. Static SFT weights should not be treated as authoritative for time-sensitive facts.

Out of Scope

  • Current officeholders, current voter counts, election schedules, deadlines, live fees, or other time-bound facts without retrieval.
  • Non-EC/NID civic services such as passport, tax, health, or banking.
  • Political persuasion, party/candidate endorsement, or voter targeting.
  • Identity decisions about real people.

Training Summary

  • Base model: Qwen/Qwen2.5-7B-Instruct
  • Method: BF16 LoRA, no quantization
  • LoRA: r=64, alpha=128, dropout 0.05
  • Target modules: q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj
  • Dataset version: v0.5.0-stage1
  • Rows: 32,502
  • Max sequence length: 8192
  • Effective batch size: 16
  • Final adapter source: checkpoint/final step 2032

See dataset_manifest.json, DATASET_CARD.md, and system_prompt.txt in this repository for the pinned data and policy metadata.

Google Colab

Paste this whole cell into a Colab GPU runtime (L4 or A100; T4 is too tight for 7B bf16). It downloads the adapter from the Hub, attaches it to Qwen/Qwen2.5-7B-Instruct, and drops you into an interactive multi-turn chat loop with token-by-token streaming. Commands: /reset clears history, /exit quits, /tokens N caps output length. Re-running the cell reuses the loaded model unless you set FORCE_RELOAD = True.

!pip -q install -U transformers peft accelerate huggingface_hub

# Colab L4/A100 often ship torchvision/bitsandbytes/torchao in a broken CUDA state.
# This adapter is bf16 LoRA inference; we do not need any of them. Removing them
# keeps the optional accelerator probes off the from_pretrained load path.
!pip -q uninstall -y torchvision bitsandbytes torchao

import inspect, json, os, sys
from pathlib import Path
from threading import Thread

import torch
from huggingface_hub import snapshot_download

ADAPTER_ID = os.environ.get("ADAPTER_ID", "ehzawad/ec-SFT-qwen25-7b-lora")
ADAPTER_REV = os.environ.get("ADAPTER_REVISION")  # optional pin
ADAPTER_DIR = Path(os.environ.get("ADAPTER_DIR", "/content/adapter"))
ADAPTER_DIR.mkdir(parents=True, exist_ok=True)
snapshot_download(repo_id=ADAPTER_ID, revision=ADAPTER_REV, local_dir=str(ADAPTER_DIR))

required = ["adapter_config.json", "adapter_model.safetensors", "system_prompt.txt",
            "tokenizer.json", "tokenizer_config.json"]
missing = [f for f in required if not (ADAPTER_DIR / f).is_file()]
assert not missing, f"adapter dir {ADAPTER_DIR} missing files: {missing}"

# Idempotent: skip the expensive load if model, tokenizer, SYSTEM_PROMPT already in globals.
# Set FORCE_RELOAD=True to refresh (e.g. after changing the adapter).
FORCE_RELOAD = False
if (not FORCE_RELOAD) and all(n in globals() for n in ("model", "tokenizer", "SYSTEM_PROMPT")):
    print("OK reusing already-loaded model (set FORCE_RELOAD=True to refresh)")
else:
    # Disable optional accelerator probes BEFORE the first transformers/peft from_pretrained call,
    # otherwise a half-broken torchao C-extension on Colab can leave model params on the meta device.
    import transformers.utils.import_utils as _iu
    _iu.is_torchvision_available = _iu.is_torchvision_v2_available = (lambda: False)
    if hasattr(_iu, "is_torchao_available"):
        _iu.is_torchao_available = (lambda: False)
    import peft.import_utils as _piu
    for _n in ("is_bnb_available", "is_bnb_4bit_available", "is_torchao_available"):
        if hasattr(_piu, _n): setattr(_piu, _n, lambda *a, **k: False)
    for _m in list(sys.modules.values()):
        if getattr(_m, "__name__", "").startswith("peft."):
            for _n in ("is_bnb_available", "is_bnb_4bit_available", "is_torchao_available"):
                if hasattr(_m, _n): setattr(_m, _n, lambda *a, **k: False)

    from peft import PeftModel
    from transformers import AutoModelForCausalLM, AutoTokenizer

    assert torch.cuda.is_available(), "No GPU found. In Colab: Runtime > Change runtime type > GPU."
    print("GPU:", torch.cuda.get_device_name(0))

    BASE_MODEL = (
        json.loads((ADAPTER_DIR / "training_args.json").read_text()).get("base_model", "Qwen/Qwen2.5-7B-Instruct")
        if (ADAPTER_DIR / "training_args.json").is_file() else "Qwen/Qwen2.5-7B-Instruct"
    )
    DTYPE = torch.bfloat16 if torch.cuda.is_bf16_supported() else torch.float16

    tokenizer = AutoTokenizer.from_pretrained(str(ADAPTER_DIR))
    if tokenizer.pad_token is None: tokenizer.pad_token = tokenizer.eos_token
    assert tokenizer.vocab_size > 100000, (
        f"tokenizer load looks degenerate (vocab_size={tokenizer.vocab_size}); "
        f"tokenizer.json should ship in the adapter repo")
    assert tokenizer.chat_template, "no chat_template loaded; expected chat_template.jinja in adapter dir"

    # Transformers renamed torch_dtype -> dtype in 4.49; accept either.
    _dtype_kw = "dtype" if "dtype" in inspect.signature(AutoModelForCausalLM.from_pretrained).parameters else "torch_dtype"
    base = AutoModelForCausalLM.from_pretrained(BASE_MODEL, **{_dtype_kw: DTYPE},
                                                device_map={"": 0}, attn_implementation="sdpa")
    model = PeftModel.from_pretrained(base, str(ADAPTER_DIR)).eval()
    model.config.use_cache = True

    SYSTEM_PROMPT = (ADAPTER_DIR / "system_prompt.txt").read_text(encoding="utf-8")

from transformers import TextIteratorStreamer

def answer(question: str, max_new_tokens: int = 1024) -> str:
    messages = [{"role": "system", "content": SYSTEM_PROMPT},
                {"role": "user", "content": question}]
    rendered = tokenizer.apply_chat_template(messages, add_generation_prompt=True,
                                             tokenize=True, return_tensors="pt")
    input_ids = rendered.input_ids if hasattr(rendered, "input_ids") else rendered
    input_ids = input_ids.to(next(model.parameters()).device)

    streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True, timeout=300.0)
    gen_kwargs = dict(
        input_ids=input_ids, attention_mask=torch.ones_like(input_ids),
        max_new_tokens=max_new_tokens, do_sample=False,
        eos_token_id=tokenizer.eos_token_id,
        pad_token_id=tokenizer.pad_token_id or tokenizer.eos_token_id,
        use_cache=True, streamer=streamer,
    )
    gen_error = {}
    def _gen():
        try:
            with torch.inference_mode():
                model.generate(**gen_kwargs)
        except BaseException as e:
            gen_error["exc"] = e
    th = Thread(target=_gen); th.start()

    chunks = []
    for chunk in streamer:
        print(chunk, end="", flush=True)
        chunks.append(chunk)
    th.join()
    if gen_error:
        e = gen_error["exc"]
        print(f"\n[generation thread raised {type(e).__name__}: {e}]")
    reply = "".join(chunks).strip()
    if not reply:
        print("[WARN: 0 chars generated — check tokenizer vocab_size and chat template]")
    return reply

# Interactive multi-turn chat with token-by-token streaming.
# Commands: /reset (clear history), /exit (quit), /tokens N (cap output at N tokens).
MAX_POS = getattr(model.config, "max_position_embeddings", 32768)
max_new_tokens = 1024
history = []

def _to_ids(enc):
    if hasattr(enc, "input_ids"): enc = enc.input_ids
    if isinstance(enc, list):
        enc = torch.tensor([enc] if not enc or isinstance(enc[0], int) else enc, dtype=torch.long)
    if enc.dim() == 1: enc = enc.unsqueeze(0)
    return enc

while True:
    try:
        q = input("USER> ").strip()
    except (EOFError, KeyboardInterrupt):
        print(); break
    if not q: continue
    if q in ("/exit", "/quit"): break
    if q == "/reset": history.clear(); print("[cleared]"); continue
    if q.startswith("/tokens"):
        parts = q.split()
        if len(parts) == 2 and parts[1].isdigit():
            max_new_tokens = int(parts[1])
            print(f"[max_new_tokens={max_new_tokens}]")
        else:
            print("[usage: /tokens 1024]")
        continue

    messages = [{"role": "system", "content": SYSTEM_PROMPT}] + history + [{"role": "user", "content": q}]
    ids = _to_ids(tokenizer.apply_chat_template(messages, add_generation_prompt=True, tokenize=True, return_tensors="pt"))
    ids = ids.to(next(model.parameters()).device)
    cap = min(max_new_tokens, max(64, MAX_POS - ids.shape[1] - 32))

    streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True, timeout=300.0)
    gen_kwargs = dict(
        input_ids=ids, attention_mask=torch.ones_like(ids),
        max_new_tokens=cap, do_sample=False,
        eos_token_id=tokenizer.eos_token_id, pad_token_id=tokenizer.pad_token_id,
        use_cache=True, streamer=streamer,
    )
    gen_error = {}
    def _gen():
        try:
            with torch.inference_mode():
                model.generate(**gen_kwargs)
        except BaseException as e:
            gen_error["exc"] = e
    thread = Thread(target=_gen)
    thread.start()

    print("BOT > ", end="", flush=True)
    chunks = []
    try:
        for chunk in streamer:
            print(chunk, end="", flush=True)
            chunks.append(chunk)
    except Exception as e:
        print(f"\n[streamer error: {type(e).__name__}: {e}]")
    thread.join()
    print()
    if gen_error:
        e = gen_error["exc"]
        print(f"[generation thread raised {type(e).__name__}: {e}]")
    reply = "".join(chunks).strip()
    if not reply:
        print("[WARN: 0 chars generated — check tokenizer vocab_size and chat template]")
    history += [{"role": "user", "content": q}, {"role": "assistant", "content": reply}]

The answer() helper above remains available for programmatic single-shot calls if you'd rather skip the input loop. The companion notebook Stage1_v5_Inference_HF_Colab.ipynb in the source repo separates the load and chat steps into their own cells.

Caveats

This v0.5.0 adapter was intentionally trained for dense exact-answer recall. That improves recall for stable procedural answers, but it can also increase wrong-canonical answers on near-miss prompts and stale static facts unless retrieval/live lookup is used for dynamic information.

Sources

1 source
Hugging FacePrincipalVersion d2968a9e7c3e115becfe50a851dd9689b4e5349e
huggingface.co/ehzawad/ec-SFT-qwen25-7b-lora/tree/d2968a9e7c3e115becfe50a851dd9689b4e5349e

Vérifié 3 oct.

Artefacts du modèle

1 artefact

adapter_model.safetensors

safetensors · 616 MB · SHA-256 c4e003bea990…ec8f · Hugging Face

Télécharger

Extraits de sources

3 extraits

--- license: mit base_model: Qwen/Qwen2.5-7B-Instruct library_name: peft pipeline_tag: text-generation language: - bn - en tags: - peft - lora - qwen2.5 - bengali - banglish - bangladesh - election-commission - nid --- # EC/NID Bengali-Banglish Assistant LoRA v0.5.0 This repository contains a PEFT LoRA adapter for `Qwen/Qwen2.5-7B-Instruct`. It was trained as the v0.5.0 Stage-1 dense-recall adapter for Bengali and Banglish Bangladesh Election Commission (EC) and National ID (NID) procedural questions. This is an adapter-only repository. It does not include the Qwen2.5 base model weights. ## Intended Use The adapter is intended for citizen-facing EC/NID assistance: NID correction, new voter registration, lost/re-issued cards, voter-area transfer, selected overseas mission questions, and stable election-procedure explanations. For production use, pair it with retrieval over official sources such as `services.nidw.gov.bd`, `ecs.gov.bd`, and the 105 helpline. Static SFT weights should not be treated as authoritative for time-sensitive facts. ## Out of Scope - Current officeholders, current voter counts, election schedules, deadlines, live fees, or other time-bound facts without retrieval. - Non-EC/NID civic services such as passport, tax, health, or banking. - Political persuasion, party/candidate endorsement, or voter targeting. - Identity decisions about real people. ## Training Summary - Base model: `Qwen/Qwen2.5-7B-Instruct` - Method: BF16 LoRA, no quantization - LoRA: `r=64`, `alpha=128`, dropout `0.05` - Target modules: `q_proj`, `k_proj`, `v_proj`, `o_proj`, `gate_proj`, `up_proj`, `down_proj` - Dataset version: `v0.5.0-stage1` - Rows: 32,502 - Max sequence length: 8192 - Effective batch size: 16 - Final adapter source: checkpoint/final step 2032 See `dataset_manifest.json`, `DATASET_CARD.md`, and `system_prompt.txt` in this repository for the pinned data and policy metadata. ## Google Colab Paste this whole cell into a Colab GPU runtime (L4 or A100; T4 is too tight for 7B bf16). It downloads the adapter from the Hub, attaches it to `Qwen/Qwen2.5-7B-Instruct`, and drops you into an interactive multi-turn chat loop with token-by-token streaming. Commands: `/reset` clears history, `/exit` quits, `/tokens N` caps output length. Re-running the cell reuses the loaded model unless you set `FORCE_RELOAD = True`. ```python !pip -q install -U tr...

Source context: 13 downloads · 0 likes · Pipeline text-generation · Library peft · Repo ehzawad/ec-SFT-qwen25-7b-lora

Source context: 12 downloads · 0 likes · Pipeline text-generation · Library peft · Repo ehzawad/ec-SFT-qwen25-7b-lora