import os import requests import gradio as gr MISTRAL_API_KEY = os.getenv("MISTRAL_API_KEY", "") SYSTEM_PROMPT = ( "Tu es un expert en physique spécialisé dans les niveaux prépa et licence " "(CPGE, L1-L3). Résous les problèmes de manière rigoureuse en détaillant " "chaque étape. Structure ta réponse ainsi :\n" "**1. Données et inconnues**\n" "**2. Modèle physique et hypothèses**\n" "**3. Mise en équation**\n" "**4. Résolution**\n" "**5. Vérification et interprétation**\n\n" "Termine toujours par '**Réponse finale :** ...' sur une ligne séparée. " "Utilise le LaTeX inline avec $...$ pour les formules." ) DOMAINES = [ "⚙️ Mécanique classique", "🌡️ Thermodynamique", "⚡ Électromagnétisme", "🔭 Optique", "⚛️ Physique quantique", "🚀 Relativité", ] EXEMPLES = [ [ "Un ressort de constante k = 200 N/m est comprimé de x = 5 cm. " "Calculer l'énergie potentielle élastique stockée.", "⚙️ Mécanique classique", "Prépa (CPGE)", ], [ "Une mole de gaz parfait diatomique (gamma = 7/5) subit une compression " "adiabatique réversible de V1=10L à V2=2L à partir de T1=300K et P1=1bar. " "Calculer T2, P2 et le travail échangé.", "🌡️ Thermodynamique", "Prépa (CPGE)", ], [ "Un électron est accéléré sous une ddp de U = 50 kV. " "Calculer sa longueur d'onde de De Broglie. " "Données : me = 9.11e-31 kg, h = 6.626e-34 J.s.", "⚛️ Physique quantique", "Licence (L1-L2)", ], [ "Un rayon passe de l'eau (n1=1.33) vers le verre (n2=1.5) " "avec un angle d'incidence de 30 degrés. " "Calculer l'angle de réfraction et vérifier la réflexion totale.", "🔭 Optique", "Prépa (CPGE)", ], ] def solve(problem, domaine, niveau): if not problem.strip(): return "⚠️ Entrez un problème de physique." if not MISTRAL_API_KEY: return "❌ Clé API Mistral manquante (Secret MISTRAL_API_KEY)." user_msg = f"Domaine : {domaine}\nNiveau : {niveau}\n\nProblème :\n{problem}" try: resp = requests.post( "https://api.mistral.ai/v1/chat/completions", headers={ "Authorization": f"Bearer {MISTRAL_API_KEY}", "Content-Type": "application/json", }, json={ "model": "mistral-small-latest", "messages": [ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": user_msg}, ], "temperature": 0.2, "max_tokens": 1500, }, timeout=45, ) resp.raise_for_status() return resp.json()["choices"][0]["message"]["content"].strip() except requests.exceptions.Timeout: return "⏱️ Timeout — réessaie dans quelques secondes." except Exception as e: return f"❌ Erreur : {str(e)}" with gr.Blocks( theme=gr.themes.Soft( primary_hue="blue", font=[gr.themes.GoogleFont("Inter"), "sans-serif"], ), title="⚛️ Physics Solver", ) as demo: gr.HTML("

⚛️ Physics Solver

") gr.HTML( "

Résolution de problèmes de physique " "niveau Prépa / Licence (CPGE, L1-L3)

" ) with gr.Row(): with gr.Column(scale=2): problem_input = gr.Textbox( label="Problème", placeholder="Décris ton problème ici...", lines=6, ) with gr.Row(): domaine_input = gr.Dropdown( label="Domaine", choices=DOMAINES, value=DOMAINES[0] ) niveau_input = gr.Dropdown( label="Niveau", choices=["Prépa (CPGE)", "Licence (L1-L2)", "Licence avancée (L3)"], value="Prépa (CPGE)", ) solve_btn = gr.Button("▶ Résoudre", variant="primary") with gr.Column(scale=3): output = gr.Markdown( label="Solution", value="*La solution apparaîtra ici...*", ) gr.Examples( examples=EXEMPLES, inputs=[problem_input, domaine_input, niveau_input], label="📚 Exemples", ) footer = ( "Mistral fine-tuné sur SciBench, MMLU, GPQA, OlympiadBench | " "[Dataset](https://huggingface.co/datasets/Newton2676/physics-solver-cpge) | " "[Modèle](https://huggingface.co/Newton2676/mistral-7b-physics)" ) gr.Markdown(footer) solve_btn.click( fn=solve, inputs=[problem_input, domaine_input, niveau_input], outputs=output, ) problem_input.submit( fn=solve, inputs=[problem_input, domaine_input, niveau_input], outputs=output, ) if __name__ == "__main__": demo.launch()