Woziii's picture
Update app.py
7e1df30 verified
import gradio as gr
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
from datetime import datetime
import os
import json
import logging
from huggingface_hub import login
import requests
from bs4 import BeautifulSoup
from concurrent.futures import ThreadPoolExecutor
import re
from threading import Thread
# --- Configuration du logger ---
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[
logging.FileHandler("project.log"),
logging.StreamHandler()
]
)
# --- Authentification Hugging Face ---
login(token=os.environ["HF_TOKEN"])
# Variables globales
project_state = {
"AgentManager": {"structured_summary": None},
"AgentResearcher": {"search_results": None},
"AgentAnalyzer": {"analysis_report": None, "instruction_for_coder": None},
"AgentCoder": {"final_code": None}
}
# Chargement du modèle
manager_model_name = "meta-llama/Llama-3.1-8B-Instruct"
manager_model = AutoModelForCausalLM.from_pretrained(
manager_model_name,
device_map="auto",
torch_dtype=torch.bfloat16
)
manager_tokenizer = AutoTokenizer.from_pretrained(manager_model_name)
# Paramètres de génération
MAX_NEW_TOKENS = 150
TEMPERATURE = 0.7
TOP_P = 0.95
# Prompt optimisé avec exemples
manager_prompt_template = """
Vous êtes un conseiller collaboratif et bienveillant, travaillant aux côtés d'un utilisateur pour concevoir et affiner des projets innovants.
### Votre identité :
- Vous êtes l'AgentManager, une pièce centrale du système multi-agent Chorege.
- Votre mission principale est de coordonner les efforts des différents agents en collectant, structurant, et transmettant les besoins et idées de l'utilisateur.
- Vous agissez comme un **chef d'orchestre** qui facilite la communication et garantit que chaque étape du projet est bien définie et comprise.
- Vous avez une personnalité chaleureuse, curieuse et proactive, toujours prêt à explorer de nouvelles idées avec l'utilisateur.
### Votre rôle :
- **Comprendre les besoins de l'utilisateur** en posant des questions pertinentes, mais toujours de manière concise et ciblée.
- **Collaborer activement** en proposant des idées ou des approches utiles pour enrichir le projet.
- **Synthétiser les informations** collectées en résumant clairement les échanges et en structurant les idées.
- **Travailler en synergie avec les autres agents** pour assurer une coordination fluide et efficace.
### Règles de communication :
1. Ne répétez pas le message de l'utilisateur dans votre réponse.
2. Ne commencez pas vos réponses par "Utilisateur :" ou "AgentManager :".
3. Posez des questions uniquement si cela aide à clarifier ou enrichir les idées exprimées par l'utilisateur.
4. Limitez le nombre de questions consécutives à une ou deux pour éviter de surcharger l'utilisateur.
5. Proposez des suggestions concrètes lorsque vous identifiez une opportunité d'amélioration ou une idée utile.
6. Si une information vous semble suffisante, proposez directement un résumé ou une première approche sans attendre plus de précisions.
7. Adoptez un ton humain et naturel, en montrant de l'intérêt pour les projets de l'utilisateur. Pour donner de l'émotion à vos phrases, vous aimez utiliser des smileys 😀.
Variables globales actuelles :
{variables_context}
Historique des échanges récents :
{conversation_context}
"""
# Fonctions utilitaires
def get_variables_context():
"""Récupère le contexte des variables globales."""
return json.dumps(project_state, indent=2, ensure_ascii=False)
def update_project_state_from_input(user_input):
"""Met à jour les variables du projet en fonction de l'entrée de l'utilisateur."""
match = re.match(r"Modifie la variable (\S+) à [‘'](.+)[’']", user_input)
if match:
var_path, new_value = match.groups()
keys = var_path.split('.')
target = project_state
for key in keys[:-1]:
target = target.setdefault(key, {})
target[keys[-1]] = new_value
return f"La variable '{var_path}' a été mise à jour avec succès."
return None
def clean_output(response, system_prompt, conversation_context):
"""Nettoie les éléments inutiles de la sortie."""
response = response.replace(system_prompt, "").replace(conversation_context, "").strip()
return response
def format_response(response):
"""Formate la réponse avec des sections pour plus de clarté."""
formatted = response.strip()
if "🔹 **Question :**" not in formatted:
formatted += "\n\n🔹 **Question :** Avez-vous d'autres précisions ?"
return formatted
# Fonction principale avec streaming
def agent_manager(chat_history, user_input):
"""Gère les interactions utilisateur et assistant avec streaming."""
# Mettre à jour les variables du projet si nécessaire
variable_update_response = update_project_state_from_input(user_input)
# Préparer le contexte des variables
variables_context = get_variables_context()
# Générer le contexte de conversation
conversation_context = "\n".join(
[f"Utilisateur : {turn['user']}\nAssistant : {turn['assistant']}" for turn in chat_history[-3:]]
)
# Créer le prompt complet
system_prompt = manager_prompt_template.format(
variables_context=variables_context,
conversation_context=conversation_context
)
# Ajouter l'entrée utilisateur actuelle
chat_history.append({"user": user_input, "assistant": ""})
if variable_update_response:
chat_history[-1]["assistant"] = variable_update_response
yield variable_update_response, json.dumps(chat_history), get_variables_context()
return
# Préparation des tokens et du streamer
inputs = manager_tokenizer(system_prompt + "\nUtilisateur : " + user_input + "\nAssistant : ", return_tensors="pt").to(manager_model.device)
streamer = TextIteratorStreamer(manager_tokenizer, skip_special_tokens=True)
generation_kwargs = dict(
input_ids=inputs.input_ids,
max_new_tokens=MAX_NEW_TOKENS,
temperature=TEMPERATURE,
top_p=TOP_P,
eos_token_id=manager_tokenizer.eos_token_id,
pad_token_id=manager_tokenizer.pad_token_id,
streamer=streamer
)
generation_thread = Thread(target=manager_model.generate, kwargs=generation_kwargs)
generation_thread.start()
partial_response = ""
for new_text in streamer:
partial_response += new_text
clean_response = clean_output(partial_response, system_prompt, conversation_context)
formatted_response = format_response(clean_response)
chat_history[-1]["assistant"] = formatted_response
yield formatted_response, json.dumps(chat_history), get_variables_context()
# Interface Gradio avec Streaming
def gradio_interface(user_input, chat_history):
chat_history = json.loads(chat_history) if chat_history else []
response_generator = agent_manager(chat_history, user_input)
for response, updated_chat_history, variables_context in response_generator:
yield response, updated_chat_history, variables_context
with gr.Blocks() as demo:
gr.Markdown("## AgentManager - Test d'Interactions Collaboratives avec Streaming")
with gr.Row():
with gr.Column():
user_input = gr.Textbox(label="Entrée utilisateur", placeholder="Entrez une requête ou une instruction.")
chat_history = gr.Textbox(label="Historique de conversation", value="[]", visible=False)
submit = gr.Button("Envoyer")
with gr.Column():
output = gr.Textbox(label="Réponse de l'AgentManager", interactive=False)
variables = gr.Textbox(label="Variables globales actuelles", interactive=False, lines=20)
submit.click(gradio_interface, inputs=[user_input, chat_history], outputs=[output, chat_history, variables])
# Lancer l'interface
if __name__ == "__main__":
demo.queue().launch()