import json, re, unicodedatafrom transformers import AutoModelForCausalLM, AutoTokenizerfrom peft import PeftModel BASE = "Qwen/Qwen3.5-4B"tok = AutoTokenizer.from_pretrained(BASE)model = AutoModelForCausalLM.from_pretrained(BASE, torch_dtype="bfloat16", device_map="auto")model = PeftModel.from_pretrained(model, "rntc/qwen3.5-4b-lymphome-ecrf-lora").eval() # applique le LoRA SYS = ("Tu es un assistant d'extraction d'information clinique. À partir du compte-rendu, " "extrais les valeurs des champs demandés. Réponds UNIQUEMENT en JSON. Recopie la " "valeur EXACTEMENT depuis le texte (verbatim), n'invente rien, ne normalise pas. " "Si un champ est absent, renvoie une liste vide [].") def extract_section(text, section, fields, max_new_tokens=512): champs = chr(10).join('- "%s"' % f for f in fields) user = ("COMPTE-RENDU:\n%s\n\nCHAMPS À EXTRAIRE (section « %s ») :\n%s\n\n" "Réponds en JSON : clés = labels ci-dessus, valeurs = listes d'extraits verbatim ([] si absent)." % (text, section, champs)) msgs = [{"role": "system", "content": SYS}, {"role": "user", "content": user}] prompt = tok.apply_chat_template(msgs, tokenize=False, add_generation_prompt=True) ids = tok(prompt, return_tensors="pt").to(model.device) gen = model.generate(**ids, max_new_tokens=max_new_tokens, do_sample=False) out = tok.decode(gen[0][ids.input_ids.shape[1]:], skip_special_tokens=True) try: return json.loads(out) except Exception: m = re.search(r"\{.*\}", out, re.S) # tolère du texte autour du JSON return json.loads(m.group(0)) if m else {} # --- exemple ---text = ("Compte-rendu d'hématologie. Patiente née le 12/05/1941, sexe féminin. " "Diagnostic le 03/2023 : lymphome B diffus à grandes cellules.")out = extract_section(text, "demographie", ["date de naissance", "sexe", "diagnostic du lymphome"])print(out) # {'date de naissance': ['... 12/05/1941'], 'sexe': ['féminin'], ...} # --- localisation des spans (value -> offsets caractères) ---def locate(text, value): i = text.find(value) return (i, i + len(value)) if i >= 0 else (-1, -1)for field, vals in out.items(): for v in vals: print(field, repr(v), locate(text, v))