Text Generation
PEFT
Safetensors
PyTorch
English
causal-lm
lora
qwen
sft
dpo
seal
self-adaptation
hitl
Instructions to use aaronr43210/MiniSEAL with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use aaronr43210/MiniSEAL with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
Download src/hitl/proposal_engine.py from aaronr43210/MiniSEAL: direct link, hf CLI and curl.
- Browser
- Download file 4.18 kB
-
https://huggingface.co/aaronr43210/MiniSEAL/resolve/main/src/hitl/proposal_engine.py
- Command line
-
hf download hf://aaronr43210/MiniSEAL/src/hitl/proposal_engine.py
-
curl -L -o proposal_engine.py https://huggingface.co/aaronr43210/MiniSEAL/resolve/main/src/hitl/proposal_engine.py
4.18 kB
| # src/hitl/proposal_engine.py | |
| import os | |
| import torch | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| from peft import PeftModel | |
| from src.hitl.db import QuarantineDatabase | |
| from src.hitl.validators import RiskValidator | |
| def find_latest_adapter(search_roots): | |
| """Return the newest PEFT adapter directory across the given roots, or None. | |
| A directory is an adapter iff it contains adapter_config.json. Matching by | |
| that marker (not by name) means adapters from ANY stage are discovered: | |
| SFT (final_adapter), SEAL (seal_adapter), HITL (lora_adapter_v*), DPO | |
| (dpo_adapter_v*). (The old code only matched dirs named "adapter_v*", so | |
| none of the trainers' outputs were ever found.) | |
| """ | |
| found = [] | |
| for root in search_roots: | |
| if not os.path.isdir(root): | |
| continue | |
| for dirpath, _dirs, files in os.walk(root): | |
| if "adapter_config.json" in files: | |
| found.append(dirpath) | |
| if not found: | |
| return None | |
| found.sort(key=os.path.getmtime, reverse=True) | |
| return found[0] | |
| class ProposalEngine: | |
| def __init__(self, db: QuarantineDatabase, validator: RiskValidator, base_model_path: str, tokenizer_path: str, device: str): | |
| self.db = db | |
| self.validator = validator | |
| self.device = device | |
| # We ignore base_model_path passed from legacy code and enforce HF Qwen | |
| actual_base_model = "Qwen/Qwen2.5-1.5B-Instruct" | |
| self.tokenizer = AutoTokenizer.from_pretrained(actual_base_model) | |
| print(f"[HITL] Loading Base Model: {actual_base_model}") | |
| self.model = AutoModelForCausalLM.from_pretrained( | |
| actual_base_model, | |
| torch_dtype=torch.bfloat16 if torch.cuda.is_available() else torch.float32, | |
| device_map="auto" if torch.cuda.is_available() else None | |
| ) | |
| # Discover the newest LoRA adapter from any stage (SFT/SEAL/HITL/DPO). | |
| project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| adapter = find_latest_adapter([ | |
| os.path.join(project_root, "ckpts", "adapters"), | |
| os.path.join(project_root, "model_weights"), | |
| ]) | |
| if adapter: | |
| print(f"[HITL] Loading latest LoRA adapter: {adapter}") | |
| self.model = PeftModel.from_pretrained(self.model, adapter) | |
| else: | |
| print("[HITL] WARNING: No trained LoRA adapters found. Using base model only.") | |
| self.model.eval() | |
| def extract_and_stage(self, passage: str, questions: list[str]) -> int: | |
| """ | |
| Executes a zero-shot model forward pass to generate self-corrections, | |
| validates the risk level, and writes the results to the Quarantine DB. | |
| """ | |
| proposals_created = 0 | |
| for q in questions: | |
| messages = [ | |
| {"role": "system", "content": "You are a helpful assistant. Answer the user's question accurately using ONLY the provided context."}, | |
| {"role": "user", "content": f"Context: {passage}\n\nQuestion: {q}"} | |
| ] | |
| text = self.tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) | |
| inputs = self.tokenizer([text], return_tensors="pt").to(self.device) | |
| with torch.no_grad(): | |
| output_ids = self.model.generate( | |
| **inputs, | |
| max_new_tokens=150, | |
| temperature=0.1, | |
| top_p=0.9, | |
| do_sample=True, | |
| pad_token_id=self.tokenizer.eos_token_id | |
| ) | |
| generated_tokens = output_ids[0][inputs.input_ids.shape[1]:] | |
| raw_answer = self.tokenizer.decode(generated_tokens, skip_special_tokens=True).strip() | |
| # Run automated risk analysis | |
| risk, flags = self.validator.analyze(q, raw_answer) | |
| # Stage into the isolated SQLite database | |
| self.db.add_proposal(passage, q, raw_answer, risk, flags) | |
| proposals_created += 1 | |
| return proposals_created | |