skip to content

Usage

Adapter support

copy markdown

Poros trains frozen-base adapters only. At prepare() time it inspects the model (pure inspection, no torch import needed) and classifies the adapter; the status decides which guarantee you can get.

Status matrix

StatusAdapterGuarantee impact
validatedPEFT LoRA / QLoRA on a frozen baseeligible for validated_bitwise (with positively detected NF4 + validated arch)
compatibleDoRA, RSLoRA, LoRA with small explicit modules_to_savetrains fine, but the exact topology has no committed parity evidence, so the label caps at smoke_only
experimentalPoros native LoRA, other PEFT types (IA3, LoHa/LoKr, prompt/prefix tuning, ...)refused under guarantee="validated"; otherwise runs with no parity claim
unsupportedno trainable adapter params, or full fine-tuneraises before training (see below)

Detection is authoritative: prepare(adapter=...) hints are advisory, except adapter="unsafe_any_trainable", the explicit full-finetune opt-out.

The two errors and the fix

  • PorosFullFinetuneDetectedError — trainable parameters that are not adapter parameters (the message reports the trainable fraction). Fix: freeze the base and attach a PEFT LoRA:

    from peft import LoraConfig, get_peft_model
    model = get_peft_model(model, LoraConfig(r=16, lora_alpha=32))
    model = poros.prepare(model)

    Escape hatch: unsafe_allow_full_trainable=True — runs, but the guarantee label drops to none (no claims).

  • PorosAdapterUnsupportedError — an experimental adapter while guarantee="validated" was requested. Fix: use a validated adapter, or accept the weaker label via guarantee="best_effort" / unsafe_allow_unvalidated_adapter=True.

What counts as an adapter parameter

Parameter names matching the LoRA family: lora_A/lora_B (and lowercase), lora_embedding_A/B, lora_magnitude (DoRA). Non-adapter trainable parameters count toward the full-finetune gate, which trips only when they exceed 2% of all parameters (FULL_FINETUNE_FRACTION_THRESHOLD). Below that threshold Poros warns rather than raising — and those parameters receive no gradients in offloaded blocks, so unfreezing norms or embeddings alongside LoRA silently trains the adapters only.

Saving

With the PEFT backend (the default), PorosTrainer.save() and standard PEFT save_pretrained() both work — Poros changes residency, not the adapter format — and saved adapters load with vanilla PEFT; nothing Poros-specific is needed at inference time (see examples/inference.py).

The experimental native backend saves a Poros-specific adapter_weights.pt instead: it is NOT vanilla-PEFT loadable and cannot be merged by poros export. Use adapter_backend="peft" for anything you intend to share or deploy.

Full prepare() semantics: auto.md.