Spaces:
Paused
Paused
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() |