--- license: apache-2.0 library_name: transformers pipeline_tag: text-generation base_model: - Qwen/Qwen3-8B tags: - memsft - memory-decoder - biology - biology-instructions - qwen3 --- # MemSFT-Qwen3-Bio-Memory-8B
📄 Paper • 💻 GitHub • 🤗 HF Collection
## Introduction MemSFT specializes modern large language models with an external parametric memory. This checkpoint contains the Qwen3-8B memory trained on Biology-Instructions. The memory learns to approximate retrieval-based teacher distributions over domain SFT data. At each decoding step, a learned token-level router combines the next-token distributions of the frozen base model and memory. This checkpoint is an auxiliary memory, not a standalone chat model. Its key advantages are: - **Plug-and-Play:** Attaches to a frozen backbone without modifying its parameters or architecture. - **Strong Specialization:** Improves domain performance with negligible degradation in general capabilities. - **Cross-Scale Reuse:** Works with Qwen3 backbones from 8B to 235B-A22B without retraining the memory for each backbone. ## Quick Start The 14B + 8B example is intended for a CUDA GPU with sufficient memory to load both models in BF16. ### 1. Install ```bash git clone https://github.com/LUMIA-Group/MemSFT.git cd MemSFT conda create -n memsft-generate python=3.10 pip -y conda activate memsft-generate python -m pip install -e . python -m pip install \ "torch>=2.4,<2.7" \ "transformers==4.51.3" \ "huggingface-hub==0.35.3" \ "accelerate>=0.34,<2" ``` ### 2. Load the base, memory, and router ```python from pathlib import Path import torch from huggingface_hub import snapshot_download from transformers import AutoModelForCausalLM, AutoTokenizer from memsft.router.adaptive_memdec import AdaptiveMemoryDecoder device = torch.device("cuda:0") base_id = "Qwen/Qwen3-14B" memory_id = "Jiarui-Wang/MemSFT-Qwen3-Bio-Memory-8B" router_repo = "Jiarui-Wang/MemSFT-Qwen3-Routers" router_subdir = "Qwen3-14B-Bio-M8B-Router" router_root = snapshot_download( repo_id=router_repo, revision="v1.0.0", allow_patterns=[f"{router_subdir}/*"], ) router_path = str(Path(router_root) / router_subdir) tokenizer = AutoTokenizer.from_pretrained( base_id, revision="40c069824f4251a91eefaf281ebe4c544efd3e18", ) base = AutoModelForCausalLM.from_pretrained( base_id, revision="40c069824f4251a91eefaf281ebe4c544efd3e18", torch_dtype=torch.bfloat16, low_cpu_mem_usage=True, ).to(device).eval() memory = AutoModelForCausalLM.from_pretrained( memory_id, revision="v1.0.0", torch_dtype=torch.bfloat16, low_cpu_mem_usage=True, ).to(device).eval() vocab_size = len(tokenizer) base.resize_token_embeddings(vocab_size) memory.resize_token_embeddings(vocab_size) base.requires_grad_(False) memory.requires_grad_(False) model = AdaptiveMemoryDecoder( base_lm=base, knn_generator=memory, router_path=router_path, router_device=device, ).eval() model.set_tokenizer(tokenizer) ``` ### 3. Generate ```python sequence = ( "MKSILIEKPNQLAIVEREIPTPSAGEVRVKVKLAGICGSDSHIYRGHNPFAKYPRVIGHEFFGVIDAV" "GEGVESARVGERVAVDPVVSCGHCYPCSIGKPNVCTTLAVLGVHADGGFSEYAVVPAKNAWKIPEAVA" "DQYAVMIEPFTIAANVTGHGQPTENDTVLVYGAGPIGLTIVQVLKGVYNVKNVIVADRIDERLEKAKE" "SGADWAINNSQTPLGEIFTEKGIKPTLIIDAACHPSILKEAVTLASPAARIVLMGFSSEPSEVIQQGI" "TGKELSIFSSRLNANKFPIVIDWLSKGLIKPEKLITHTFDFQHVADAISLFEQDQKHCCKVLLTFSE" ) prompt = ( r"