boccaccioAI / scripts /chat_distill.py
lollix91's picture
Upload folder using huggingface_hub
187a491 verified
Raw History Blame Contribute Delete
4.1 kB
"""Test del modello distillato con prompt personalizzati da riga di comando."""
from __future__ import annotations
import os
import sys
# Add project root to path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
import torch
from tokenizers import Tokenizer
from src.model.config import BoccaccioConfig
from src.model.transformer import BoccaccioForCausalLM
def load_model(path: str, config: BoccaccioConfig) -> BoccaccioForCausalLM:
model = BoccaccioForCausalLM(config).to("cuda")
sd = torch.load(path, map_location="cuda", weights_only=True)
if isinstance(sd, dict) and "state_dict" in sd:
sd = sd["state_dict"]
cleaned = {}
for k, v in sd.items():
nk = k
# Strip torch.compile prefix
if nk.startswith("_orig_mod."):
nk = nk[len("_orig_mod."):]
# For Lightning .ckpt: strip outer "model." (LightningModule.model -> BoccaccioForCausalLM)
# but only if double "model.model." (not model.pt which has single "model.")
elif nk.startswith("model.model."):
nk = nk[len("model."):]
cleaned[nk] = v
missing, unexpected = model.load_state_dict(cleaned, strict=False)
if missing:
print(f"WARNING: {len(missing)} missing keys")
if unexpected:
print(f"WARNING: {len(unexpected)} unexpected keys")
model.eval()
return model
def generate(model, tokenizer, prompt, max_new=300, temp=0.3, rep=1.2):
ids = tokenizer.encode(prompt).ids
x = torch.tensor([ids], device="cuda")
with torch.no_grad():
for _ in range(max_new):
out = model(x)
logits = out["logits"][0, -1, :]
for tid in set(x[0].tolist()):
logits[tid] /= rep
if temp > 0:
logits = logits / temp
v, _ = torch.topk(logits, 40)
logits[logits < v[-1]] = float("-inf")
probs = torch.softmax(logits, dim=-1)
tid = torch.multinomial(probs, num_samples=1).item()
else:
tid = torch.argmax(logits).item()
if tid == 2:
break
x = torch.cat([x, torch.tensor([[tid]], device="cuda")], dim=1)
new = x[0].cpu().tolist()[len(ids):]
return tokenizer.decode(new).strip()
def main():
config = BoccaccioConfig.from_yaml("configs/model.yaml", variant="model")
tok = Tokenizer.from_file("tokenizer/boccaccio-32k.json")
import os
ckpt_dir = "checkpoints/finetune_distill"
# Prefer model.pt (pure weights), fall back to .ckpt
model_pt = os.path.join(ckpt_dir, "model.pt")
if os.path.exists(model_pt):
ckpt_path = model_pt
else:
ckpts = sorted([f for f in os.listdir(ckpt_dir) if f.endswith(".ckpt")])
if not ckpts:
print("Nessun checkpoint trovato in checkpoints/finetune_distill/")
return
ckpt_path = os.path.join(ckpt_dir, ckpts[-1])
print(f"Using: {ckpt_path}\n", flush=True)
model = load_model(ckpt_path, config)
print("Modalita' chat. Digita 'quit' per uscire, 'ctx' per aggiungere contesto.\n")
context = ""
while True:
try:
user_input = input("Tu> ").strip()
except (EOFError, KeyboardInterrupt):
break
if not user_input:
continue
if user_input.lower() == "quit":
break
if user_input.lower().startswith("ctx "):
context = user_input[4:].strip()
print(f"[Contesto impostato: {context[:80]}...]\n")
continue
if user_input.lower() == "ctx":
context = ""
print("[Contesto cancellato]\n")
continue
if context:
prompt = f"### Contesto: {context}\n\n### Utente: {user_input}\n### Assistente:"
else:
prompt = f"### Utente: {user_input}\n### Assistente:"
resp = generate(model, tok, prompt)
print(f"\nAssistente: {resp}\n")
if __name__ == "__main__":
main()