Bi-directional Cross-Attention Enrichment Preprocessor — a PEFT adapter for HuggingFace transformers.
Project description
BiCEP — Bi-directional Cross-Attention Enrichment Preprocessor
BiCEP is a PEFT adapter that enriches prompt embeddings with a small trainable bidirectional transformer before they reach a frozen causal LLM. Unlike LoRA (which modifies the LLM's weights) or prompt tuning (which prepends virtual tokens), BiCEP transforms the input embedding sequence in place — same length, no tokens added or removed — then feeds the result to the frozen model.
It behaves like a native PEFT adapter: get_peft_model, save_pretrained, from_pretrained,
push_to_hub, and generate all work without special-casing.
⚠️ Experimental. BiCEP is an architectural hypothesis whose efficacy has not yet been empirically validated. The API is usable and stable, but there is no published evidence yet that the enricher improves downstream performance. I plan to train and release checkpoints to gather empirical data in the near-to-mid future — and anyone is more than welcome to do so independently in the meantime. Until then, treat results as unproven and expect the project to stay on
0.x.
Install
pip install bicep # also needs torch>=2.1, transformers>=5.0,<6, peft>=0.19.1,<0.20
Configuration — three fields
| Field | Default | Meaning |
|---|---|---|
base_model_name_or_path |
required | HF model id / local path of the frozen base LLM |
num_blocks |
3 |
Number of (bidirectional self-attention + FFN) enrichment blocks |
d_head |
64 |
Attention head dimension. Must divide the base model's hidden_size |
d_model, n_heads, and vocab_size are derived automatically from the base model — you never set them.
Train
import bicep # registers the BICEP PEFT type on import
from bicep import BiCEPConfig, BiCEPDataCollator
from peft import get_peft_model
from transformers import (AutoModelForCausalLM, AutoTokenizer,
Trainer, TrainingArguments)
name = "meta-llama/Llama-3.1-8B"
base = AutoModelForCausalLM.from_pretrained(name)
tok = AutoTokenizer.from_pretrained(name)
model = get_peft_model(base, BiCEPConfig(base_model_name_or_path=name))
collator = BiCEPDataCollator(tokenizer=tok) # MANDATORY — see below
trainer = Trainer(
model=model,
args=TrainingArguments(
output_dir="out",
remove_unused_columns=False, # REQUIRED with BiCEPDataCollator (see note)
),
train_dataset=dataset, # see "Data formats"
data_collator=collator,
)
trainer.train()
model.push_to_hub("you/bicep-llama3")
Only the adapter is trained — all base-model weights stay frozen, and save_pretrained /
push_to_hub store only the adapter weights.
Publish with a model card
BiCEP is a third-party PEFT method, so anyone loading your checkpoint must
import bicep first (see below). Ship a model card that says so — render_model_card
produces a Hub-ready README.md (with library_name: peft front matter):
from pathlib import Path
from bicep import render_model_card
save_dir = "out/bicep-llama3"
model.save_pretrained(save_dir)
card = render_model_card(model.peft_config["default"], repo_id="you/bicep-llama3")
Path(save_dir, "README.md").write_text(card, encoding="utf-8")
model.push_to_hub("you/bicep-llama3") # README.md rides along
Load & generate
import bicep
from peft import PeftModel
from transformers import AutoModelForCausalLM
base = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.1-8B")
model = PeftModel.from_pretrained(base, "you/bicep-llama3")
model.generate(input_ids=...) # no BiCEP-specific arguments
The collator is mandatory — causal integrity
BiCEP's enricher is bidirectional, so a prompt token's enriched embedding can encode later
prompt tokens. To keep this from leaking into the loss, two things must hold, and
BiCEPDataCollator enforces both:
- Loss masking — prompt token positions get
labels = -100, so loss is computed on response tokens only. - Prompt-only enrichment — the collator emits a
bicep_prompt_maskthat tells the model to enrich prompt positions only; response/generated tokens pass through as raw embeddings.
Using BiCEPDataCollator is not optional. Skipping it (or hand-rolling labels) silently
breaks the causal structure and produces a model that cannot generalize.
Data formats
BiCEPDataCollator accepts either:
{"prompt": "Translate to French: Hello", "response": "Bonjour"}
{"text": "The cat sat on the mat ...", "prompt_length": 42} # prompt_length in tokens
A record with no response tokens (empty response, or prompt_length ≥ the token count) raises
ValueError.
Why remove_unused_columns=False?
Trainer drops dataset columns not in the model's forward signature before collation — which
would remove the collator's raw prompt/response/text inputs. Set
TrainingArguments(remove_unused_columns=False) so the collator receives them.
Scope (v1)
- Single-GPU training. Multi-GPU (DataParallel/FSDP/DeepSpeed) is out of scope.
- You load and manage the base model (dtype, quantization, device); BiCEP does not.
- Composing BiCEP with another PEFT adapter simultaneously is undefined.
Development
python -m venv .venv && . .venv/Scripts/activate # or source .venv/bin/activate
pip install -e ".[dev]"
pytest # CPU-only, uses tiny HF test models
License
BiCEP is licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later). See LICENSE for the full text.
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 bicep-0.1.0.tar.gz.
File metadata
- Download URL: bicep-0.1.0.tar.gz
- Upload date:
- Size: 30.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5976fcba0971fe863e682687fa3e275e6c56accbb38608825e42b4108d9fd6a
|
|
| MD5 |
d95b7d7aaa974936c92b3bee1a40bdf3
|
|
| BLAKE2b-256 |
88faea836a78608b65e3236a3dc440582e157721eed2cbea12a47bf648b30afd
|
Provenance
The following attestation bundles were made for bicep-0.1.0.tar.gz:
Publisher:
publish.yml on victorfrowello/BiCEP
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bicep-0.1.0.tar.gz -
Subject digest:
f5976fcba0971fe863e682687fa3e275e6c56accbb38608825e42b4108d9fd6a - Sigstore transparency entry: 1818488355
- Sigstore integration time:
-
Permalink:
victorfrowello/BiCEP@9172ead81b520d70db1b36310b1256a95de0e1f9 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/victorfrowello
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9172ead81b520d70db1b36310b1256a95de0e1f9 -
Trigger Event:
release
-
Statement type:
File details
Details for the file bicep-0.1.0-py3-none-any.whl.
File metadata
- Download URL: bicep-0.1.0-py3-none-any.whl
- Upload date:
- Size: 32.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3dc8f3029448b16adddd54ccf5be57b57a1176f19910340be63f53a2f931ad31
|
|
| MD5 |
834394374f6174e69e463c70a7468a81
|
|
| BLAKE2b-256 |
72b521dd6d95ab951f0fff7c34c5a05aca3e40dae5709c536f1cce2c8079c91c
|
Provenance
The following attestation bundles were made for bicep-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on victorfrowello/BiCEP
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bicep-0.1.0-py3-none-any.whl -
Subject digest:
3dc8f3029448b16adddd54ccf5be57b57a1176f19910340be63f53a2f931ad31 - Sigstore transparency entry: 1818488362
- Sigstore integration time:
-
Permalink:
victorfrowello/BiCEP@9172ead81b520d70db1b36310b1256a95de0e1f9 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/victorfrowello
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9172ead81b520d70db1b36310b1256a95de0e1f9 -
Trigger Event:
release
-
Statement type: