import gradio as gr import sqlite3 import secrets import string import torch from transformers import AutoModelForCausalLM, AutoTokenizer # --- CONFIGURATION DU MODÈLE --- MODEL_ID = "Finisha-F-scratch/Charlotte-amity" tokenizer = AutoTokenizer.from_pretrained(MODEL_ID) model = AutoModelForCausalLM.from_pretrained( MODEL_ID, torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32, device_map="auto" ) # --- GESTION DE LA BASE DE DONNÉES (SQLITE) --- DB_NAME = "charlotte_api.db" def init_db(): conn = sqlite3.connect(DB_NAME) c = conn.cursor() # Table pour stocker les clés et le nombre de requêtes c.execute('''CREATE TABLE IF NOT EXISTS api_keys (key TEXT PRIMARY KEY, requests_count INTEGER)''') conn.commit() conn.close() init_db() def create_key(): """Génère une clé tn-xxxx0000 et l'enregistre""" letters = ''.join(secrets.choice(string.ascii_lowercase) for _ in range(4)) digits = ''.join(secrets.choice(string.digits) for _ in range(4)) new_key = f"tn-{letters}{digits}" conn = sqlite3.connect(DB_NAME) c = conn.cursor() try: c.execute("INSERT INTO api_keys (key, requests_count) VALUES (?, ?)", (new_key, 0)) conn.commit() return new_key except: return "Erreur lors de la génération. Réessayez." finally: conn.close() def validate_and_log(key): """Vérifie la clé et incrémente le compteur""" conn = sqlite3.connect(DB_NAME) c = conn.cursor() c.execute("SELECT requests_count FROM api_keys WHERE key=?", (key,)) result = c.fetchone() if result is not None: c.execute("UPDATE api_keys SET requests_count = requests_count + 1 WHERE key=?", (key,)) conn.commit() conn.close() return True conn.close() return False # --- FONCTION D'INFÉRENCE (L'API) --- def charlotte_api(api_key, message): """ Point d'entrée principal pour les appels externes. """ if not validate_and_log(api_key): return "❌ Erreur : Clé API 'tn-' invalide ou non trouvée." # Limitation stricte au contexte de 128 tokens inputs = tokenizer(message, return_tensors="pt", truncation=True, max_length=128).to(model.device) with torch.no_grad(): outputs = model.generate( **inputs, max_new_tokens=100, do_sample=True, temperature=0.8, pad_token_id=tokenizer.eos_token_id ) full_text = tokenizer.decode(outputs[0], skip_special_tokens=True) # On renvoie uniquement la réponse générée response = full_text[len(message):].strip() return response # --- INTERFACE GRADIO --- with gr.Blocks(theme=gr.themes.Monochrome()) as demo: gr.Markdown("# 🌸 Charlotte-Amity : Système API Personnel") with gr.Tab("🔑 Gérer mes clés"): gr.Markdown("Cliquez ci-dessous pour générer une clé d'accès unique.") key_output = gr.Textbox(label="Votre nouvelle clé API", interactive=False) generate_btn = gr.Button("Générer ma clé tn-") generate_btn.click(create_key, outputs=key_output) gr.Info("Note: Gardez précieusement votre clé pour vos appels externes.") with gr.Tab("💬 Test Rapide"): api_input = gr.Textbox(label="Clé API (tn-...)") msg_input = gr.Textbox(label="Votre message") text_output = gr.Textbox(label="Réponse de Charlotte") run_btn = gr.Button("Envoyer") run_btn.click(charlotte_api, inputs=[api_input, msg_input], outputs=text_output) # L'EXPOSITION DE L'API POUR L'EXTÉRIEUR # Cette ligne permet d'appeler la fonction via l'URL du Space api_interface = gr.Interface( fn=charlotte_api, inputs=[gr.Textbox(label="api_key"), gr.Textbox(label="message")], outputs="text", api_name="chat" # C'est le nom à utiliser dans le client Python ) if __name__ == "__main__": demo.launch()