Text Generation
Transformers
TensorBoard
Safetensors
biology
genomics
rna
sequence-generation
regression
reinforcement-learning
git-lfs
Instructions to use JoyXiangLab/rnaseek-full with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use JoyXiangLab/rnaseek-full with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="JoyXiangLab/rnaseek-full")# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("JoyXiangLab/rnaseek-full", device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use JoyXiangLab/rnaseek-full with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "JoyXiangLab/rnaseek-full" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "JoyXiangLab/rnaseek-full", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/JoyXiangLab/rnaseek-full
- SGLang
How to use JoyXiangLab/rnaseek-full with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "JoyXiangLab/rnaseek-full" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "JoyXiangLab/rnaseek-full", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "JoyXiangLab/rnaseek-full" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "JoyXiangLab/rnaseek-full", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use JoyXiangLab/rnaseek-full with Docker Model Runner:
docker model run hf.co/JoyXiangLab/rnaseek-full
| #!/usr/bin/env python3 | |
| import os | |
| import json | |
| import random | |
| from pathlib import Path | |
| from typing import Dict | |
| import numpy as np | |
| import torch | |
| from torch import nn | |
| from torch.nn import functional as F | |
| from torch.utils.tensorboard import SummaryWriter | |
| from datasets import Dataset | |
| from sklearn.metrics import mean_squared_error, r2_score | |
| from scipy.stats import pearsonr | |
| from transformers import ( | |
| AutoTokenizer, | |
| AutoConfig, | |
| AutoModel, | |
| TrainingArguments, | |
| Trainer, | |
| PreTrainedModel, | |
| set_seed, | |
| ) | |
| from transformers.data.data_collator import DataCollatorWithPadding | |
| # Drop-in replacement (cleaned + "what the model sees" showcase BEFORE training): | |
| # - keeps your model class definitions unchanged | |
| # - aligns training behavior to the sweep script: | |
| # * dynamic padding (pad_to_multiple_of=8) | |
| # * tokenizer.pad_token handling | |
| # * robust dropout setting + post-load dropout patching | |
| # * fused AdamW | |
| # * scheduler: cosine + num_cycles=4 | |
| # | |
| # ----------------------------- | |
| # User knobs | |
| # ----------------------------- | |
| logDir = "clean_cosine_restart_besthp_preview_fixed-wd-0.8_reproduce" | |
| base_model_path = "./checkpoint-388560" | |
| tokenizer_path = "../regression_efficiency/checkpoint-5956" | |
| train_json = "evenBetterDataFolded-tr.json" | |
| valid_json = "evenBetterDataFolded-vl.json" | |
| seed = 42 | |
| preview_n_texts = 4 # how many raw examples to preview | |
| preview_tok_trunc = 200 # how many tokens to print per example (for readability) | |
| preview_batch_size = 4 # for collator preview | |
| set_seed(seed) | |
| random.seed(seed) | |
| np.random.seed(seed) | |
| torch.manual_seed(seed) | |
| writer = SummaryWriter(log_dir=f"tensorboard/{logDir}") | |
| class LastTokenPooling(nn.Module): | |
| """ | |
| Pool using the last non-padded token. Supports left- or right-padding. | |
| """ | |
| def __init__(self): | |
| super().__init__() | |
| def forward(self, hidden_states, attention_mask=None): | |
| # hidden_states: [B, T, H], attention_mask: [B, T] | |
| if attention_mask is None: | |
| return hidden_states[:, -1, :] | |
| B, T, H = hidden_states.size() | |
| # detect left-padding | |
| if attention_mask[:, -1].sum().item() == B: | |
| return hidden_states[:, -1, :] | |
| # right-padding / variable lengths | |
| seq_lens = attention_mask.sum(dim=1).long() - 1 # [B] | |
| idx = seq_lens.view(B, 1, 1).expand(-1, 1, H) # [B,1,H] | |
| return hidden_states.gather(1, idx).squeeze(1) # [B,H] | |
| class OneLayerRegressionHead(nn.Module): | |
| """ | |
| Exactly one layernorm+linear, no residual-GELU block. | |
| """ | |
| def __init__(self, hidden_size): | |
| super().__init__() | |
| self.net = nn.Sequential( | |
| nn.LayerNorm(hidden_size), | |
| nn.Linear(hidden_size, 1), | |
| ) | |
| def forward(self, x): | |
| # x: [B, hidden_size] | |
| return self.net(x).squeeze(-1) # [B] | |
| class QwenForRegression(PreTrainedModel): | |
| """ | |
| A regression model that uses only the base transformer (no LM head) and last-token pooling. | |
| """ | |
| config_class = AutoConfig | |
| base_model_prefix = "backbone" | |
| def __init__(self, config, writer: SummaryWriter = None): | |
| super().__init__(config) | |
| # use base model without LM head to avoid unused lm_head parameters | |
| self.backbone = AutoModel.from_config(config) | |
| if getattr(config, "gradient_checkpointing", False): | |
| self.backbone.gradient_checkpointing_enable() | |
| hidden_size = config.hidden_size | |
| self.pooler = LastTokenPooling() | |
| self.regression_head = OneLayerRegressionHead(hidden_size) | |
| self.writer = writer | |
| self.step = 0 | |
| def supports_gradient_checkpointing(self) -> bool: | |
| return True | |
| def gradient_checkpointing_enable(self, **kwargs): | |
| self.backbone.gradient_checkpointing_enable(**kwargs) | |
| def gradient_checkpointing_disable(self, **kwargs): | |
| self.backbone.gradient_checkpointing_disable(**kwargs) | |
| def forward(self, input_ids=None, attention_mask=None, labels=None, **kwargs): | |
| outputs = self.backbone( | |
| input_ids=input_ids, | |
| attention_mask=attention_mask, | |
| return_dict=True, | |
| output_hidden_states=False, | |
| ) | |
| hidden_states = outputs.last_hidden_state # [B,T,H] | |
| pooled = self.pooler(hidden_states, attention_mask) # [B,H] | |
| if self.writer is not None: | |
| self.writer.add_scalar("pooled/mean", pooled.mean().item(), self.step) | |
| self.writer.add_scalar("pooled/std", pooled.std().item(), self.step) | |
| self.step += 1 | |
| logits = self.regression_head(pooled) | |
| if labels is not None: | |
| loss = F.mse_loss(logits, labels) | |
| return {"loss": loss, "logits": logits} | |
| return {"logits": logits} | |
| def save_pretrained( | |
| self, | |
| save_directory: str, | |
| state_dict=None, | |
| accelerator=None, | |
| **kwargs | |
| ): | |
| model_to_save = self | |
| if accelerator is not None: | |
| model_to_save = accelerator.unwrap_model(self) | |
| os.makedirs(save_directory, exist_ok=True) | |
| model_to_save.config.save_pretrained(save_directory) | |
| model_to_save.backbone.save_pretrained( | |
| save_directory, state_dict=state_dict, **kwargs | |
| ) | |
| head_sd = model_to_save.regression_head.state_dict() | |
| for idx, layer in enumerate(model_to_save.regression_head.net): | |
| if isinstance(layer, nn.Linear): | |
| w_key = f"net.{idx}.weight" | |
| if w_key in head_sd: | |
| w = head_sd[w_key] | |
| out_f, in_f = layer.out_features, layer.in_features | |
| if w.dim() == 1 and w.numel() == out_f * in_f: | |
| head_sd[w_key] = w.view(out_f, in_f) | |
| torch.save(head_sd, os.path.join(save_directory, "regression_head.pt")) | |
| def from_pretrained(cls, model_path, device="cpu", config=None, writer=None): | |
| model_dir = Path(model_path) | |
| config = config or AutoConfig.from_pretrained(model_dir) | |
| fsdp_file = model_dir / "pytorch_model_fsdp.bin" | |
| backbone_sd, head_sd = {}, {} | |
| if fsdp_file.exists(): | |
| fsdp_sd = torch.load(fsdp_file, map_location=device) | |
| # — strip the exact "backbone." prefix — | |
| for k, v in fsdp_sd.items(): | |
| if k.startswith("backbone."): | |
| new_k = k[len("backbone."):] | |
| backbone_sd[new_k] = v | |
| elif k.startswith("regression_head."): | |
| new_k = k[len("regression_head."):] | |
| head_sd[new_k] = v | |
| # instantiate backbone from config | |
| backbone = AutoModel.from_config(config) | |
| # strict load: will now match | |
| missing_b, unexpected_b = backbone.load_state_dict(backbone_sd, strict=True) | |
| if missing_b or unexpected_b: | |
| raise RuntimeError( | |
| f"Backbone load mismatch.\n missing: {missing_b}\n unexpected: {unexpected_b}" | |
| ) | |
| else: | |
| # fallback to HF sharded .safetensors | |
| backbone = AutoModel.from_pretrained(model_dir, device_map=None,config=config) | |
| #head_sd = torch.load(model_dir / "regression_head.pt", map_location=device) | |
| # build your full model | |
| model = cls(config, writer=writer) | |
| model.backbone = backbone.to(device) | |
| if hasattr(model.config, "use_cache"): | |
| model.config.use_cache = False | |
| if hasattr(model.backbone, "config") and hasattr(model.backbone.config, "use_cache"): | |
| model.backbone.config.use_cache = False | |
| # load regression head strictly, too | |
| missing_h, unexpected_h = model.regression_head.load_state_dict(head_sd, strict=False) | |
| # if missing_h or unexpected_h: | |
| # raise RuntimeError( | |
| # f"Head load mismatch.\n missing: {missing_h}\n unexpected: {unexpected_h}" | |
| # ) | |
| return model.to(device).eval() | |
| # ========================= | |
| # Sweep-alignment utilities (APPLY CHANGES HERE) | |
| # ========================= | |
| def robust_set_dropout(config, p_hidden: float, p_attn: float, layerdrop: float): | |
| """ | |
| Mirror the sweep script: set all plausible dropout fields if present. | |
| """ | |
| hidden_fields = [ | |
| "hidden_dropout_prob", "hidden_dropout", "dropout", | |
| "emb_dropout", "resid_pdrop", "classifier_dropout", | |
| ] | |
| attn_fields = [ | |
| "attention_probs_dropout_prob", "attention_dropout", | |
| "attn_dropout", "attn_pdrop", | |
| ] | |
| for f in hidden_fields: | |
| if hasattr(config, f): | |
| setattr(config, f, float(p_hidden)) | |
| for f in attn_fields: | |
| if hasattr(config, f): | |
| setattr(config, f, float(p_attn)) | |
| if hasattr(config, "layerdrop"): | |
| setattr(config, "layerdrop", float(layerdrop)) | |
| def patch_all_dropout_modules(model: nn.Module, p_hidden: float): | |
| """ | |
| Post-load patch: in your from_pretrained else-branch, | |
| backbone is loaded via AutoModel.from_pretrained(model_dir, device_map=None) | |
| which may ignore our modified config. | |
| We therefore patch nn.Dropout modules in-place to match hidden dropout. | |
| """ | |
| for m in model.modules(): | |
| if isinstance(m, nn.Dropout): | |
| m.p = float(p_hidden) | |
| def install_head_dropout(model: QwenForRegression, head_dropout: float): | |
| """ | |
| head_dropout without changing class definition: | |
| swap net to LN -> Dropout -> Linear | |
| """ | |
| hs = model.config.hidden_size | |
| model.regression_head.net = nn.Sequential( | |
| nn.LayerNorm(hs), | |
| nn.Dropout(p=float(head_dropout)), | |
| nn.Linear(hs, 1), | |
| ) | |
| # ========================= | |
| # Load tokenizer | |
| # ========================= | |
| tokenizer = AutoTokenizer.from_pretrained(tokenizer_path, use_fast=True) | |
| tokenizer.pad_token = tokenizer.eos_token | |
| # ========================= | |
| # Load data | |
| # ========================= | |
| with open(train_json, "r", encoding="utf-8") as f: | |
| trainData = json.load(f) | |
| with open(valid_json, "r", encoding="utf-8") as f: | |
| validData = json.load(f) | |
| train_texts = list(trainData.keys()) | |
| train_labels = [float(trainData[k]) for k in train_texts] | |
| valid_texts = list(validData.keys()) | |
| valid_labels = [float(validData[k]) for k in valid_texts] | |
| os.makedirs(f"tensorboard/{logDir}", exist_ok=True) | |
| with open(f"tensorboard/{logDir}/train.json", "w", encoding="utf-8") as jf: | |
| json.dump(trainData, jf, indent=2) | |
| with open(f"tensorboard/{logDir}/valid.json", "w", encoding="utf-8") as jf: | |
| json.dump(validData, jf, indent=2) | |
| print("Train examples:", train_texts[:2], train_labels[:2]) | |
| print("Valid examples:", valid_texts[:2], valid_labels[:2]) | |
| # ========================= | |
| # Tokenize (dynamic padding later) | |
| # ========================= | |
| train_raw = Dataset.from_dict({"text": train_texts, "label": train_labels}) | |
| valid_raw = Dataset.from_dict({"text": valid_texts, "label": valid_labels}) | |
| def tok_fn(batch): | |
| return tokenizer(batch["text"], truncation=True, add_special_tokens=True) | |
| train_dataset = train_raw.map(tok_fn, batched=True, remove_columns=["text"]) | |
| valid_dataset = valid_raw.map(tok_fn, batched=True, remove_columns=["text"]) | |
| train_dataset = train_dataset.rename_column("label", "labels") | |
| valid_dataset = valid_dataset.rename_column("label", "labels") | |
| train_dataset.set_format(type="torch") | |
| valid_dataset.set_format(type="torch") | |
| data_collator = DataCollatorWithPadding( | |
| tokenizer=tokenizer, | |
| pad_to_multiple_of=8, | |
| return_tensors="pt", | |
| ) | |
| # ========================= | |
| # "What the model sees" preview (unchanged) | |
| # ========================= | |
| def preview_tokenization_examples(texts, labels, tok, n=3, tok_trunc=200): | |
| print("\n==============================") | |
| print("PREVIEW: what the model sees") | |
| print("==============================") | |
| print("Tokenizer special_tokens_map:", tok.special_tokens_map) | |
| if getattr(tok, "additional_special_tokens", None): | |
| print("Tokenizer additional_special_tokens (count):", len(tok.additional_special_tokens)) | |
| print("First few additional specials:", tok.additional_special_tokens[:10]) | |
| idxs = list(range(min(n, len(texts)))) | |
| for i in idxs: | |
| text = texts[i] | |
| y = labels[i] | |
| enc = tok(text, add_special_tokens=True) | |
| ids = enc["input_ids"] | |
| toks = tok.convert_ids_to_tokens(ids) | |
| print("\n--- Example", i, "---") | |
| print("Label:", y) | |
| print("Raw text (first 300 chars):") | |
| print(text[:300] + ("..." if len(text) > 300 else "")) | |
| print("\nToken IDs (truncated):") | |
| print(ids[:tok_trunc], "...(len=%d)" % len(ids) if len(ids) > tok_trunc else "(len=%d)" % len(ids)) | |
| print("\nTokens (truncated):") | |
| print(toks[:tok_trunc], "...(len=%d)" % len(toks) if len(toks) > tok_trunc else "(len=%d)" % len(toks)) | |
| decoded = tok.decode(ids, skip_special_tokens=False) | |
| print("\nDecoded (skip_special_tokens=False) first 400 chars:") | |
| print(decoded[:400] + ("..." if len(decoded) > 400 else "")) | |
| def preview_collated_batch(ds, tok, collator, batch_size=4, tok_trunc=120): | |
| print("\n==============================") | |
| print("PREVIEW: collated batch (dynamic padding)") | |
| print("==============================") | |
| batch_items = [ds[i] for i in range(min(batch_size, len(ds)))] | |
| batch = collator(batch_items) | |
| input_ids = batch["input_ids"] | |
| attn = batch["attention_mask"] | |
| labels = batch["labels"] | |
| print("Batch shapes:", | |
| "input_ids", tuple(input_ids.shape), | |
| "attention_mask", tuple(attn.shape), | |
| "labels", tuple(labels.shape)) | |
| pad_id = tok.pad_token_id | |
| for r in range(min(2, input_ids.shape[0])): | |
| ids = input_ids[r].tolist() | |
| toks = tok.convert_ids_to_tokens(ids) | |
| visible_len = int((np.array(ids) != pad_id).sum()) if pad_id is not None else int(attn[r].sum().item()) | |
| print(f"\n--- Batch row {r} ---") | |
| print("Label:", float(labels[r].item())) | |
| print("Non-pad token length:", visible_len) | |
| print("IDs (truncated):") | |
| print(ids[:tok_trunc], "...") | |
| print("Tokens (truncated):") | |
| print(toks[:tok_trunc], "...") | |
| decoded = tok.decode(ids, skip_special_tokens=False) | |
| print("Decoded (skip_special_tokens=False) first 400 chars:") | |
| print(decoded[:400] + ("..." if len(decoded) > 400 else "")) | |
| preview_tokenization_examples(train_texts, train_labels, tokenizer, n=preview_n_texts, tok_trunc=preview_tok_trunc) | |
| preview_collated_batch(train_dataset, tokenizer, data_collator, batch_size=preview_batch_size, tok_trunc=preview_tok_trunc) | |
| # ========================= | |
| # Metrics (keep) | |
| # ========================= | |
| def compute_metrics(eval_pred): | |
| preds, labels = eval_pred | |
| if isinstance(preds, (tuple, list)): | |
| preds = preds[0] | |
| preds = np.asarray(preds).reshape(-1) | |
| labels = np.asarray(labels).reshape(-1) | |
| mse = mean_squared_error(labels, preds) | |
| r2 = r2_score(labels, preds) | |
| if np.std(preds) > 1e-8 and np.std(labels) > 1e-8: | |
| pr, _ = pearsonr(preds, labels) | |
| else: | |
| pr = 0.0 | |
| return {"mse": float(mse), "r2": float(r2), "pearson_r": float(pr)} | |
| # ========================= | |
| # Best hparams you provided | |
| # ========================= | |
| HP = dict( | |
| learning_rate=5e-5, | |
| weight_decay=0.8, | |
| hidden_dropout=0.3, | |
| attn_dropout=0.3, | |
| layerdrop=0.05, | |
| head_dropout=0.2, | |
| max_grad_norm=2, | |
| warmup_ratio=0.1, | |
| lr_scheduler_type="cosine", # <-- IMPORTANT: match your best hp | |
| num_cycles=40, | |
| ) | |
| # ========================= | |
| # Build config (robust) + load model | |
| # ========================= | |
| config = AutoConfig.from_pretrained(base_model_path) | |
| robust_set_dropout(config, HP["hidden_dropout"], HP["attn_dropout"], HP["layerdrop"]) | |
| model = QwenForRegression.from_pretrained( | |
| base_model_path, | |
| device="cuda", | |
| writer=writer, | |
| config=config, | |
| ) | |
| # Patch dropout after load to avoid config-ignored behavior | |
| patch_all_dropout_modules(model, p_hidden=HP["hidden_dropout"]) | |
| # Head dropout without changing model class | |
| install_head_dropout(model, head_dropout=HP["head_dropout"]) | |
| # Disable cache (saves VRAM) - keep | |
| if hasattr(model.config, "use_cache"): | |
| model.config.use_cache = False | |
| if hasattr(model.backbone, "config") and hasattr(model.backbone.config, "use_cache"): | |
| model.backbone.config.use_cache = False | |
| def print_trainable_summary(m): | |
| total = 0 | |
| trainable = 0 | |
| for _, p in m.named_parameters(): | |
| n = p.numel() | |
| total += n | |
| if p.requires_grad: | |
| trainable += n | |
| print(f"\nTotal parameters: {total:,}") | |
| print(f"Trainable parameters: {trainable:,}") | |
| print(f"Frozen parameters: {total-trainable:,}") | |
| print_trainable_summary(model) | |
| # ========================= | |
| # TrainingArguments (apply changes) | |
| # ========================= | |
| USE_BF16 = torch.cuda.is_available() | |
| training_args = TrainingArguments( | |
| output_dir=f"./qwen_regression_ckpt/{logDir}", | |
| per_device_train_batch_size=24, # match sweep default unless you intentionally want 16 | |
| per_device_eval_batch_size=24, | |
| gradient_accumulation_steps=1, | |
| num_train_epochs=1000, | |
| learning_rate=HP["learning_rate"], | |
| weight_decay=HP["weight_decay"], | |
| max_grad_norm=HP["max_grad_norm"], | |
| warmup_steps=21600, | |
| lr_scheduler_type=HP["lr_scheduler_type"], # cosine | |
| lr_scheduler_kwargs={"num_cycles": HP["num_cycles"]}, | |
| bf16=USE_BF16, | |
| logging_dir=f"tensorboard/{logDir}", | |
| logging_steps=10, | |
| report_to="tensorboard", | |
| optim="adamw_torch_fused", # match sweep | |
| eval_strategy="epoch", # HF-standard spelling | |
| save_strategy="epoch", | |
| save_total_limit=2, | |
| load_best_model_at_end=True, | |
| metric_for_best_model="mse", | |
| greater_is_better=False, | |
| gradient_checkpointing=True, | |
| gradient_checkpointing_kwargs={"use_reentrant": False}, | |
| dataloader_pin_memory=True, | |
| remove_unused_columns=False, | |
| seed=seed, | |
| data_seed=seed, | |
| ) | |
| trainer = Trainer( | |
| model=model, | |
| args=training_args, | |
| train_dataset=train_dataset, | |
| eval_dataset=valid_dataset, | |
| data_collator=data_collator, | |
| compute_metrics=compute_metrics, | |
| tokenizer=tokenizer, | |
| ) | |
| print('dropout') | |
| # show a few dropout modules | |
| cnt = 0 | |
| for n, m in model.named_modules(): | |
| if isinstance(m, nn.Dropout): | |
| print("dropout:", n, "p=", m.p) | |
| cnt += 1 | |
| if cnt >= 8: | |
| break | |
| print(model.backbone.config) | |
| trainer.train() | |