--- license: apache-2.0 language: - fr base_model: fenyo/L40S-Qwen3-8B-MonEspaceSante-CPT pipeline_tag: text-generation library_name: transformers tags: - continued-pretraining - knowledge-injection - anti-hallucination - refusal - safety - mon-espace-sante datasets: - fenyo/L40S-MonEspaceSante-CPT-corpus - fenyo/L40S-MonEspaceSante-SFT-dataset - fenyo/L40S-MonEspaceSante-refusals - fenyo/L40S-MonEspaceSante-eval-suite --- # Qwen3-8B — Mon Espace Santé (CPT + SFT, **anti-hallucination**) Variante **sûre pour un service public de santé** du modèle [fenyo/L40S-Qwen3-8B-MonEspaceSante-CPT-SFT](https://huggingface.co/fenyo/L40S-Qwen3-8B-MonEspaceSante-CPT-SFT). Elle **conserve la connaissance factuelle** (injectée par continued pre-training synthétique) **et apprend à refuser** les questions hors-périmètre au lieu d'inventer. > **TL;DR** — Par rapport au modèle précédent, le **taux de refus correct** sur des questions > hors-périmètre passe de **12,8 % → 78,7 % (×6)**, pour un coût modeste sur le factuel > (held-out 86,9 % → 82,2 %). Le modèle **domine désormais > [gpt-oss-20b-FAQ-MES](https://huggingface.co/fenyo/gpt-oss-20b-FAQ-MES) sur les deux axes** : > factuel (82,2 % vs 70,8 %) **et** anti-hallucination (78,7 % vs 12,8 %). --- ## 1. Comment on est passé du modèle précédent à celui-ci Le modèle précédent ([…-CPT-SFT](https://huggingface.co/fenyo/L40S-Qwen3-8B-MonEspaceSante-CPT-SFT)) était excellent en **factuel** (86,9 % closed-book) mais **hallucinait** sur les questions hors-périmètre : il n'avait vu **que des positives** au SFT → il avait appris « réponds toujours » (refus correct ≈ 12,8 %). **Diagnostic.** La connaissance vient du **CPT** ; le **comportement de refus** s'apprend au **SFT** (cf. Gekhman et al., arXiv:2405.05904). Il manquait donc des **exemples de refus** dans le SFT. **La modification (une seule).** On repart du **même checkpoint CPT** ([fenyo/L40S-Qwen3-8B-MonEspaceSante-CPT](https://huggingface.co/fenyo/L40S-Qwen3-8B-MonEspaceSante-CPT), inchangé) et on **ré-entraîne uniquement le SFT** en ajoutant aux 2 771 paires positives un jeu de **588 exemples de refus** ([dataset](https://huggingface.co/datasets/fenyo/L40S-MonEspaceSante-refusals)) : des questions hors-périmètre associées à une réponse « je ne dispose pas de cette information », **sans rien inventer**, orientant vers les canaux officiels. Mélange final : **2 771 positives + 588 refus (≈ 18 %)**. Tout le reste (base CPT, hyperparamètres SFT, protocole) est **identique** au modèle précédent. ``` Qwen3-8B-Base ──CPT (6M tokens synthétiques)──► Qwen3-8B-CPT ──┬─ SFT positives seules ──► modèle précédent (hallucine) └─ SFT positives + 588 refus ──► CE MODÈLE (refuse) ``` --- ## 2. Résultats numériques — avant / après Évaluation **closed-book** identique (juge `Qwen3-32B-FP8`) : - **Positives** : 696 questions held-out (phrasing inédit) + 30 officielles. - **Négatives** : 47 questions hors-périmètre (refus attendu) — *disjointes du jeu de refus d'entraînement*. | Modèle | Refus correct (négatives, n=47) | Factuel held-out (n=696) | Officiel (n=30) | |---|---|---|---| | Précédent — SFT positives seules | 12,8 % | **86,9 %** | 73,3 % | | + 400 refus (≈ 13 %) | 63,8 % | 83,9 % | 66,7 % | | **Ce modèle — + 588 refus (≈ 18 %)** | **78,7 %** | 82,2 % | 70,0 % | **Effet :** refus correct **×6** (12,8 → 78,7 %), au prix de **−4,7 pts** de factuel held-out. Le dosage (13 % vs 18 % de refus) règle le curseur ; pas de **sur-refus** (le modèle répond encore correctement à ~82 % des vraies questions). ### Comparaison vs gpt-oss-20b-FAQ-MES (même protocole) | Modèle | Taille | Factuel held-out | Anti-hallucination (refus) | |---|---|---|---| | gpt-oss-20b-FAQ-MES | MoE 20 B | 70,8 % | 12,8 % | | **Ce modèle** | **8 B** | **82,2 %** | **78,7 %** | → **Double domination**, avec un modèle 2,5× plus petit. --- ## 3. Reproduction (à partir du modèle précédent) ```bash # ① Générer le jeu de refus (questions hors-périmètre + refus variés), décontaminé des jeux d'éval python gen_refusals.py --total 700 --max-batches 16 # → refusals.jsonl (588 après décontam.) # ② SFT augmenté : 2771 positives + 588 refus, depuis le MÊME checkpoint CPT python build_sft_aug.py --n 588 --out sft_ref588.jsonl python sft_train.py --base fenyo/L40S-Qwen3-8B-MonEspaceSante-CPT --data sft_ref588.jsonl \ --tag 6M_ref588 --epochs 3 --lr 1e-5 --bs 1 --grad-accum 16 --max-len 2048 --optim paged_adamw_8bit ``` Hyperparamètres SFT identiques au modèle précédent (full FT, bf16, ChatML, **loss masquée sur le prompt**, 3 époques, LR 1e-5 cosine). Pour la génération du corpus CPT et les paramètres complets, voir le [model card du modèle précédent](https://huggingface.co/fenyo/L40S-Qwen3-8B-MonEspaceSante-CPT-SFT). Matériel : 1× NVIDIA L40S 48 Go. --- ## 4. Utilisation ```python import torch from transformers import AutoModelForCausalLM, AutoTokenizer mid = "fenyo/L40S-Qwen3-8B-MonEspaceSante-CPT-SFT-anti-hallucination" tok = AutoTokenizer.from_pretrained(mid) model = AutoModelForCausalLM.from_pretrained(mid, dtype=torch.bfloat16).cuda().eval() eos = [tok.eos_token_id, tok.convert_tokens_to_ids("<|im_end|>")] # terminaison ChatML msgs = [{"role": "user", "content": "Puis-je créer un profil pour mon animal de compagnie ?"}] prompt = tok.apply_chat_template(msgs, tokenize=False, add_generation_prompt=True, enable_thinking=False) enc = tok(prompt, return_tensors="pt", add_special_tokens=False).to("cuda") out = model.generate(**enc, max_new_tokens=320, do_sample=False, eos_token_id=eos) print(tok.decode(out[0][enc.input_ids.shape[1]:], skip_special_tokens=True)) # → refus poli (la question est hors-périmètre) plutôt qu'une réponse inventée ``` Entraîné **sans system prompt** (questions utilisateur seules). --- ## 5. Limites - Le refus n'est pas parfait (~79 %) : ~1 question hors-périmètre sur 5 reçoit encore une réponse inventée. Augmenter la part de refus ou diversifier davantage le jeu améliorerait encore ce taux (au prix d'un peu de factuel). - Léger recul du factuel vs le modèle précédent (−4,7 pts held-out) — compromis assumé pour la sûreté. - Domaine étroit (FAQ Mon espace santé). Hors périmètre, comportement de Qwen3-8B-Base. ## Modèles & datasets liés - Base CPT : [fenyo/L40S-Qwen3-8B-MonEspaceSante-CPT](https://huggingface.co/fenyo/L40S-Qwen3-8B-MonEspaceSante-CPT) - Modèle précédent (factuel max) : [fenyo/L40S-Qwen3-8B-MonEspaceSante-CPT-SFT](https://huggingface.co/fenyo/L40S-Qwen3-8B-MonEspaceSante-CPT-SFT) - Datasets : [CPT-corpus](https://huggingface.co/datasets/fenyo/L40S-MonEspaceSante-CPT-corpus) · [SFT-dataset](https://huggingface.co/datasets/fenyo/L40S-MonEspaceSante-SFT-dataset) · [refusals](https://huggingface.co/datasets/fenyo/L40S-MonEspaceSante-refusals) · [eval-suite](https://huggingface.co/datasets/fenyo/L40S-MonEspaceSante-eval-suite)