Generate portable task-specific LoRA adapters across language models
Project description
PorTAL: Portable Task Adapters for LLMs
Alpha research release announced by Ramp Labs. APIs and artifact schemas may evolve before the first stable release.
PorTAL learns a base-agnostic task latent and a light per-base decoder that generates ordinary per-layer LoRA weights. A task can be trained once, adapted to supported frozen base models, and exported as a standard Hugging Face PEFT adapter.
portallib is an alpha Python library for loading, training, saving, publishing, and exporting
PorTAL artifacts with standard PyTorch and Hugging Face interfaces.
The included pinned recipes reproduce the PorTAL source-training, target-refitting, and evaluation method described by Ramp Labs. Reported results should be generated from the released artifacts and their recorded evaluation configuration rather than treated as fixed package guarantees.
During source training, PorTAL jointly learns the task-latent table, one shared canonical core, and one alignment for each source base. To port the learned tasks, it freezes the latent table and core and refits only a fresh alignment for the target base. The resulting task adapter is exportable as an ordinary PEFT LoRA adapter.
Install
Install the inference library from PyPI:
pip install portallib
Install the optional Hugging Face model and dataset dependencies for training:
pip install 'portallib[training]'
Python 3.11 and 3.12 are supported. Install a CUDA-compatible PyTorch build for GPU training before installing the training extra when your platform requires a specific CUDA wheel.
Load and export
Load a native PorTAL artifact, select a trained task, and obtain a normal PEFT model:
from transformers import AutoModelForCausalLM
from portallib import PortalModel
base = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen3-4B",
revision="1cfa9a7208912126459214e8b04321603b3df60c",
)
portal = PortalModel.from_pretrained(
"RampPublic/portal-qwen3-4b",
revision="v0.1.0",
base_model=base,
)
model = portal.get_peft_model("rte")
model.save_pretrained("./portal-rte-qwen3-4b")
A task can also be exported without loading the base LLM:
portal.export_peft("rte", "./portal-rte-qwen3-4b")
The exported directory is an ordinary PEFT adapter and reloads with
PeftModel.from_pretrained.
Published artifacts
| Artifact | Role |
|---|---|
RampPublic/portal-qwen3-1.7b |
Jointly trained shared weights plus the 1.7B alignment |
RampPublic/portal-qwen3-4b |
Jointly trained shared weights plus the 4B alignment |
RampPublic/portal-qwen3-8b |
1,000-example-per-task refit |
RampPublic/portal-gemma-3-4b |
1,000-example-per-task cross-family refit |
The recipes load the v0.1.0 artifact revisions. Each repository contains one base-specific native
PorTAL artifact; task-specific standard PEFT adapters can be generated from it as needed.
Examples
examples/train_example.py is thin orchestration around the public
canonical trainer APIs. It freezes each base model, jointly learns shared task latents and a canonical
core with one thin alignment per source base, evaluates epoch zero and every training epoch, restores
the best held-out epoch, and writes one native artifact per source base. Its only model downloads are
the raw Hugging Face bases selected for source training.
The complete pinned recipe is a short, editable block near the top of the file. It selects the
dataset, exact model revisions, output directory, source bases, and PortalTrainingConfig:
python examples/train_example.py
examples/refit_example.py loads either source artifact as a carrier
for the task vectors and canonical core learned jointly from Qwen3-1.7B and Qwen3-4B. It downloads
only the new raw target base, freezes the shared components, and trains a fresh target alignment:
python examples/refit_example.py
The checked-in recipe reads the shared weights from RampPublic/portal-qwen3-4b; this does not make
the refit 4B-only—the 1.7B and 4B source artifacts contain identical jointly trained task latents and
canonical core weights. The default target is Qwen3-8B with at most 1,000 training examples per task.
The adjacent Gemma 3 recipe uses the same shared components and its exact text-decoder layer path.
examples/evaluate_example.py loads a trained PorTAL artifact and
its matching raw base, then reports the base floor, adapted per-task metrics, macro metrics, and
accuracy lift:
python examples/evaluate_example.py
The checked-in evaluation recipe uses RampPublic/portal-qwen3-8b; change the artifact and matching
base recipe together to evaluate one of the other published source or refit artifacts.
The examples are repository assets rather than installed console commands. Clone the repository to run them, then install the released training package:
git clone https://github.com/ramp-public/portallib
cd portallib
pip install 'portallib[training]==0.1.0'
python examples/train_example.py
REPRODUCING.md records pinned dataset and model revisions, the complete training
configuration, checkpoint selection, and source/Qwen/Gemma recipes.
COMPUTE.md shows how to run any example locally with Docker or remotely through
Modal. The compute wrapper provisions the runtime and persistent storage; the training and evaluation
behavior comes from the installed portallib release and selected recipe.
Model compatibility
PorTAL supports Qwen3 and cross-family refitting to Gemma 3. Qwen3 exposes decoder layers at
model.layers; Gemma 3 exposes its text decoder at
model.language_model.layers. The default projection paths cover the usual query, key, value,
attention-output, and gated-MLP linear modules used by those families.
Other causal language-model families are expected to work when they expose uniform linear
projections across decoder layers. Pass their exact layer and projection paths through PortalBase;
PorTAL validates every configured path and dimension before training. Automatic architecture
adapters and models with non-uniform per-layer projection dimensions are not yet part of the
supported v0.1 compatibility surface. Contributions that add exact, tested architecture mappings
are welcome.
For another model family, set its exact BaseRecipe.layer_path; paths are explicit rather than
inferred from module-name patterns, so an incompatible model fails before training.
The checked-in modules=("q", "v") setting generates LoRA for query/value projections. Set it to
("q", "k", "v", "o", "gate", "up", "down") to include the attention output and MLP
projections. In both cases, the base model parameters remain frozen.
Artifact format
Native artifacts use the standard Hugging Face layout:
config.jsoncontains the schema version, base model and revision, task names, LoRA settings, exact layer/module paths, and projection dimensions.model.safetensorscontainstask_latents, the canonicalcore, and one base-specificalignment, withportallibformat metadata.README.mdis the generated model card.
PortalModel inherits ModelHubMixin, so save_pretrained, from_pretrained, and push_to_hub
follow standard Hugging Face Hub behavior:
portal.push_to_hub("your-namespace/portal-qwen3-4b", private=True)
Configured layers and projections are resolved deterministically. Missing modules, incompatible dimensions, unknown schema versions, and inconsistent target declarations fail explicitly.
Public API
PortalConfigvalidates artifacts and builds exact configurations from supported base models.PortalCoreTrainerjointly trains shared latents/core and one alignment per source base using balanced per-task updates, EMA loss normalization, and per-base latent-gradient balancing.PortalAdapterRefitterfreezes a source artifact's latents/core and trains only a target alignment.PortalTrainingConfig.from_portal_configpreserves an artifact's architecture while selecting a new optimization recipe for refitting.PortalEvaluatorbatches candidate continuations while reporting character-normalized multiple-choice accuracy and token-mean gold NLL.EvaluationResult.to_dictreturns the canonical JSON-ready evaluation representation.PortalDecodercombines a canonical core and one base-specific alignment to generate LoRA factors.PortalModelloads, saves, publishes, materializes, and exports trained artifacts.ChoiceDatasetloads and saves the normalized local/Hub task schema and supports explicit Hub upload.collate_gold_batchprovides the causal-LM batch format used by the training APIs.
Development
uv run ruff check src tests examples scripts
uv run pytest -q
uv run python -m build
PorTAL is licensed under Apache-2.0.
Citation
If you use PorTAL, cite the software metadata in
CITATION.cff.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file portallib-0.1.0.tar.gz.
File metadata
- Download URL: portallib-0.1.0.tar.gz
- Upload date:
- Size: 44.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b698258471a78979e2ee29807514bff928915d4e2a5efd163e4e874aac9c80ef
|
|
| MD5 |
9b7c726bf388d32bd16af700ebfe7041
|
|
| BLAKE2b-256 |
bca05c8280f72fa2976d112415c039df2d9795c54adc7d359e8f6f61ad10cf2b
|
Provenance
The following attestation bundles were made for portallib-0.1.0.tar.gz:
Publisher:
publish.yml on ramp-public/portallib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
portallib-0.1.0.tar.gz -
Subject digest:
b698258471a78979e2ee29807514bff928915d4e2a5efd163e4e874aac9c80ef - Sigstore transparency entry: 2175838569
- Sigstore integration time:
-
Permalink:
ramp-public/portallib@8a99e0c72879af296c4835cfe68d34006e21209e -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ramp-public
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8a99e0c72879af296c4835cfe68d34006e21209e -
Trigger Event:
release
-
Statement type:
File details
Details for the file portallib-0.1.0-py3-none-any.whl.
File metadata
- Download URL: portallib-0.1.0-py3-none-any.whl
- Upload date:
- Size: 30.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d513cbaf407a09b60459831cea1eb1a61cf2ee314ad7b772b3d5b610bd05a197
|
|
| MD5 |
ba37fac479cf010397345c23accf822e
|
|
| BLAKE2b-256 |
df83658f368f5d8e60ada784b7c79dbca4c104be94e4b404277d004ea89798f7
|
Provenance
The following attestation bundles were made for portallib-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on ramp-public/portallib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
portallib-0.1.0-py3-none-any.whl -
Subject digest:
d513cbaf407a09b60459831cea1eb1a61cf2ee314ad7b772b3d5b610bd05a197 - Sigstore transparency entry: 2175838576
- Sigstore integration time:
-
Permalink:
ramp-public/portallib@8a99e0c72879af296c4835cfe68d34006e21209e -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ramp-public
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8a99e0c72879af296c4835cfe68d34006e21209e -
Trigger Event:
release
-
Statement type: