File size: 3,341 Bytes
ac4e16e
3f982f9
3974991
3f982f9
 
3974991
3f982f9
 
 
ac4e16e
3f982f9
ac4e16e
3f982f9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ac4e16e
 
3f982f9
ac4e16e
3f982f9
 
 
 
 
 
 
 
 
 
010ed8f
 
ac4e16e
010ed8f
3f982f9
 
ac4e16e
3f982f9
 
 
 
 
 
 
 
 
af742a6
3f982f9
af742a6
3f982f9
 
 
010ed8f
3f982f9
 
ac4e16e
3f982f9
 
 
 
 
 
 
ac4e16e
3f982f9
 
010ed8f
3f982f9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
import gradio as gr
import re
from pathlib import Path

# ====== CONFIGURATION ======
MODEL_NAME = "microsoft/phi-3-mini-4k-instruct"
SYSTEM_PROMPT_FILE = "infos_medical.txt"  # ton fichier .txt

# ====== CHARGEMENT DU MODÈLE ET TOKENIZER ======
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
model = AutoModelForCausalLM.from_pretrained(
    MODEL_NAME,
    torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
    device_map="auto"
)
print(f"✅ Modèle '{MODEL_NAME}' chargé avec succès.")

# ====== CHARGEMENT DU CONTEXTE MÉDICAL ======
try:
    context_text = Path(SYSTEM_PROMPT_FILE).read_text(encoding="utf-8").strip()
except FileNotFoundError:
    context_text = "Aucune donnée médicale fournie."
    print("⚠️ Fichier infos_medical.txt introuvable — le chatbot fonctionnera sans contexte.")

# Nettoyage du texte
context_text = context_text.replace("\n", " ")
context_text = re.sub(r"\s+", " ", context_text)
context_text = context_text[:3000]  # limite la longueur pour garder de la mémoire

# ====== INSTRUCTION SYSTÈME ======
system_instruction = (
    "Tu es un assistant médical virtuel. "
    "Tu réponds en français, poliment et de façon factuelle. "
    "Tu fournis uniquement des informations générales de santé. "
    "Tu ne poses pas de diagnostic et ne prescris pas de traitement. "
    "Si la demande est trop spécifique, réponds : "
    "\"Je ne sais pas — consultez un professionnel de santé.\""
)

# ====== CONSTRUCTION DU PROMPT ======
def build_prompt(history, user_message):
    """
    Construit un prompt propre : instruction + contexte + historique + message utilisateur.
    """
    lines = [
        f"System: {system_instruction}",
        "",
        f"Contexte médical de référence : {context_text}",
        "",
    ]
    for user, bot in history:
        lines.append(f"User: {user}")
        if bot:
            lines.append(f"Bot: {bot}")
    lines.append(f"User: {user_message}")
    lines.append("Bot:")
    return "\n".join(lines)

# ====== FONCTION DE RÉPONSE ======
def chat(user_message, history):
    prompt = build_prompt(history, user_message)
    inputs = tokenizer(prompt, return_tensors="pt", truncation=True).to(model.device)

    outputs = model.generate(
        **inputs,
        max_new_tokens=300,
        temperature=0.6,
        top_p=0.9,
        do_sample=True,
        pad_token_id=tokenizer.eos_token_id
    )
    reply = tokenizer.decode(outputs[0], skip_special_tokens=True)

    # Récupération du texte après le dernier "Bot:"
    if "Bot:" in reply:
        reply = reply.split("Bot:")[-1].strip()

    history.append((user_message, reply))
    return history, history

# ====== INTERFACE GRADIO ======
with gr.Blocks(theme=gr.themes.Soft(primary_hue="green")) as demo:
    gr.Markdown("## 🩺 Chatbot Médical — Assistant virtuel de santé")
    gr.Markdown(f"📘 **Contexte chargé :** {len(context_text.split())} mots de référence médicale.")
    chatbot = gr.Chatbot(height=400)
    msg = gr.Textbox(label="Posez une question médicale…")
    clear = gr.Button("🧹 Effacer la conversation")

    msg.submit(chat, [msg, chatbot], [chatbot, chatbot])
    clear.click(lambda: None, None, chatbot, queue=False)

demo.launch()