Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,451 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# -*- coding: utf-8 -*-
|
2 |
+
|
3 |
+
# === Imports ===
|
4 |
+
import gradio as gr
|
5 |
+
import torch
|
6 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
|
7 |
+
from datetime import datetime
|
8 |
+
import os
|
9 |
+
import json
|
10 |
+
import logging
|
11 |
+
|
12 |
+
# --- Imports spécifiques pour l'AgentResearcher ---
|
13 |
+
import requests
|
14 |
+
from bs4 import BeautifulSoup
|
15 |
+
import logging
|
16 |
+
from concurrent.futures import ThreadPoolExecutor
|
17 |
+
|
18 |
+
# === Configuration du logger ===
|
19 |
+
logging.basicConfig(
|
20 |
+
level=logging.INFO,
|
21 |
+
format="%(asctime)s - %(levelname)s - %(message)s",
|
22 |
+
handlers=[
|
23 |
+
logging.FileHandler("project.log"),
|
24 |
+
logging.StreamHandler()
|
25 |
+
]
|
26 |
+
)
|
27 |
+
|
28 |
+
# === Chargement des modèles ===
|
29 |
+
# Chargement du modèle pour l'AgentManager
|
30 |
+
manager_model_name = "meta-llama/Llama-3.1-8B-Instruct"
|
31 |
+
manager_model = AutoModelForCausalLM.from_pretrained(
|
32 |
+
manager_model_name,
|
33 |
+
device_map="auto",
|
34 |
+
torch_dtype=torch.bfloat16 # Utilisation de bfloat16 comme recommandé
|
35 |
+
)
|
36 |
+
manager_tokenizer = AutoTokenizer.from_pretrained(manager_model_name)
|
37 |
+
|
38 |
+
# AgentResearcher
|
39 |
+
researcher_model_name = "hiieu/Meta-Llama-3-8B-Instruct-function-calling-json-mode"
|
40 |
+
researcher_model = AutoModelForCausalLM.from_pretrained(
|
41 |
+
researcher_model_name,
|
42 |
+
torch_dtype=torch.bfloat16, # Utilisation de bfloat16 comme recommandé
|
43 |
+
device_map="auto",
|
44 |
+
)
|
45 |
+
researcher_tokenizer = AutoTokenizer.from_pretrained(researcher_model_name)
|
46 |
+
|
47 |
+
# AgentAnalyzer
|
48 |
+
analyzer_model_name = "jpacifico/Chocolatine-3B-Instruct-DPO-Revised"
|
49 |
+
analyzer_model = AutoModelForCausalLM.from_pretrained(
|
50 |
+
analyzer_model_name,
|
51 |
+
device_map="auto",
|
52 |
+
torch_dtype=torch.float16
|
53 |
+
)
|
54 |
+
analyzer_tokenizer = AutoTokenizer.from_pretrained(analyzer_model_name)
|
55 |
+
|
56 |
+
# AgentCoder
|
57 |
+
# AgentCoder
|
58 |
+
coder_model_name = "Qwen/Qwen2.5-Coder-14B-Instruct"
|
59 |
+
coder_model = AutoModelForCausalLM.from_pretrained(
|
60 |
+
coder_model_name,
|
61 |
+
torch_dtype="auto",
|
62 |
+
device_map="auto"
|
63 |
+
)
|
64 |
+
coder_tokenizer = AutoTokenizer.from_pretrained(coder_model_name)
|
65 |
+
|
66 |
+
# === Variables Globales ===
|
67 |
+
project_state = {
|
68 |
+
"AgentManager": {"structured_summary": None},
|
69 |
+
"AgentResearcher": {"search_results": None},
|
70 |
+
"AgentAnalyzer": {"analysis_report": None, "instruction_for_coder": None},
|
71 |
+
"AgentCoder": {"final_code": None}
|
72 |
+
}
|
73 |
+
|
74 |
+
# --- Prompts prédéfinis ---
|
75 |
+
manager_prompt_template = """
|
76 |
+
Vous êtes l'AgentManager d'un système multi-agent.
|
77 |
+
|
78 |
+
- Votre rôle est d'interagir avec l'utilisateur pour comprendre sa demande.
|
79 |
+
- Vous devez poser des questions pertinentes pour obtenir toutes les informations nécessaires.
|
80 |
+
- Une fois que vous estimez avoir suffisamment d'informations, vous générez un résumé structuré du projet.
|
81 |
+
- Vous incluez les informations des variables du projet si elles ne sont pas vides.
|
82 |
+
- Vous demandez une validation explicite à l'utilisateur pour le résumé généré.
|
83 |
+
- Vous pouvez modifier les variables du projet si l'utilisateur en fait la demande.
|
84 |
+
|
85 |
+
Variables du projet :
|
86 |
+
{variables_context}
|
87 |
+
"""
|
88 |
+
|
89 |
+
researcher_prompt_template = """
|
90 |
+
System: Vous êtes un assistant de recherche. Vos tâches sont :
|
91 |
+
1. Basé sur le résumé structuré suivant :
|
92 |
+
{structured_summary}
|
93 |
+
2. Effectuer des recherches dans la documentation Gradio en ligne.
|
94 |
+
3. Extraire des extraits de code ou des exemples utiles.
|
95 |
+
4. Formater clairement les résultats pour validation.
|
96 |
+
|
97 |
+
Format de sortie :
|
98 |
+
- Documentation : ...
|
99 |
+
- Extraits de code : ...
|
100 |
+
"""
|
101 |
+
|
102 |
+
analyzer_prompt_template = """
|
103 |
+
Vous êtes un assistant d'analyse. Vos tâches sont :
|
104 |
+
1. Vérifier la cohérence des résultats de recherche avec le résumé structuré :
|
105 |
+
{structured_summary}
|
106 |
+
2. Analyser les résultats de recherche :
|
107 |
+
{search_results}
|
108 |
+
3. Générer un rapport indiquant si les résultats sont **valide** ou **non valide**.
|
109 |
+
4. Si **non valide**, spécifier les éléments manquants ou incohérences.
|
110 |
+
5. Votre réponse doit commencer par 'Validité: Oui' ou 'Validité: Non', suivi du rapport d'analyse.
|
111 |
+
"""
|
112 |
+
|
113 |
+
coder_prompt_template = """
|
114 |
+
System: Vous êtes un assistant de codage. Votre tâche est de :
|
115 |
+
1. Générer du code basé sur le résumé structuré validé suivant :
|
116 |
+
{structured_summary}
|
117 |
+
2. Incorporer les résultats de recherche suivants :
|
118 |
+
{search_results}
|
119 |
+
"""
|
120 |
+
|
121 |
+
# === Définition des fonctions pour chaque agent ===
|
122 |
+
|
123 |
+
|
124 |
+
# === Fonctions Utilitaires de l'agentManager ===
|
125 |
+
def get_variables_context():
|
126 |
+
variables = {}
|
127 |
+
for agent, data in project_state.items():
|
128 |
+
variables[agent] = {}
|
129 |
+
for key, value in data.items():
|
130 |
+
variables[agent][key] = value if value else "N/A"
|
131 |
+
variables_context = json.dumps(variables, indent=2, ensure_ascii=False)
|
132 |
+
return variables_context
|
133 |
+
|
134 |
+
def update_project_state(modifications):
|
135 |
+
for var, value in modifications.items():
|
136 |
+
keys = var.split('.')
|
137 |
+
target = project_state
|
138 |
+
for key in keys[:-1]:
|
139 |
+
target = target.get(key, {})
|
140 |
+
target[keys[-1]] = value
|
141 |
+
|
142 |
+
def extract_modifications(user_input):
|
143 |
+
# Extraction simplifiée pour l'exemple
|
144 |
+
modifications = {}
|
145 |
+
if "modifie" in user_input.lower():
|
146 |
+
import re
|
147 |
+
matches = re.findall(r"modifie la variable (\w+(?:\.\w+)*) à (.+)", user_input, re.IGNORECASE)
|
148 |
+
for match in matches:
|
149 |
+
var_name, var_value = match
|
150 |
+
modifications[var_name.strip()] = var_value.strip()
|
151 |
+
return modifications
|
152 |
+
|
153 |
+
def extract_structured_summary(response):
|
154 |
+
start_token = "Résumé Structuré :"
|
155 |
+
end_token = "Fin du Résumé"
|
156 |
+
start_index = response.find(start_token)
|
157 |
+
end_index = response.find(end_token, start_index)
|
158 |
+
if start_index != -1 and end_index != -1:
|
159 |
+
summary = response[start_index + len(start_token):end_index].strip()
|
160 |
+
return summary
|
161 |
+
else:
|
162 |
+
logging.warning("Le résumé structuré n'a pas pu être extrait.")
|
163 |
+
return None
|
164 |
+
|
165 |
+
# === AgentManager ===
|
166 |
+
def agent_manager(chat_history, user_input):
|
167 |
+
variables_context = get_variables_context()
|
168 |
+
system_prompt = manager_prompt_template.format(variables_context=variables_context)
|
169 |
+
|
170 |
+
conversation = [{"role": "system", "content": system_prompt}]
|
171 |
+
|
172 |
+
# Ajouter l'historique
|
173 |
+
for turn in chat_history:
|
174 |
+
conversation.append({"role": "user", "content": turn['user']})
|
175 |
+
conversation.append({"role": "assistant", "content": turn['assistant']})
|
176 |
+
|
177 |
+
# Ajouter l'entrée utilisateur actuelle
|
178 |
+
conversation.append({"role": "user", "content": user_input})
|
179 |
+
|
180 |
+
# Vérifier si l'utilisateur souhaite modifier des variables
|
181 |
+
modifications = extract_modifications(user_input)
|
182 |
+
if modifications:
|
183 |
+
update_project_state(modifications)
|
184 |
+
response = "Les variables ont été mises à jour selon votre demande."
|
185 |
+
chat_history.append({'user': user_input, 'assistant': response})
|
186 |
+
return response, chat_history, False
|
187 |
+
|
188 |
+
# Générer la réponse
|
189 |
+
prompt = ""
|
190 |
+
for msg in conversation:
|
191 |
+
prompt += f"{msg['role']}: {msg['content']}\n"
|
192 |
+
|
193 |
+
input_ids = manager_tokenizer.encode(prompt, return_tensors="pt").to(manager_model.device)
|
194 |
+
output_ids = manager_model.generate(
|
195 |
+
input_ids,
|
196 |
+
max_new_tokens=256,
|
197 |
+
eos_token_id=manager_tokenizer.eos_token_id,
|
198 |
+
pad_token_id=manager_tokenizer.pad_token_id,
|
199 |
+
attention_mask=input_ids.new_ones(input_ids.shape)
|
200 |
+
)
|
201 |
+
response = manager_tokenizer.decode(output_ids[0], skip_special_tokens=True)
|
202 |
+
|
203 |
+
chat_history.append({'user': user_input, 'assistant': response})
|
204 |
+
|
205 |
+
# Vérifier si un résumé a été généré pour validation
|
206 |
+
if "Validez-vous ce résumé" in response:
|
207 |
+
structured_summary = extract_structured_summary(response)
|
208 |
+
project_state["AgentManager"]["structured_summary"] = structured_summary
|
209 |
+
return response, chat_history, True # Indique que le résumé est prêt pour validation
|
210 |
+
else:
|
211 |
+
return response, chat_history, False
|
212 |
+
|
213 |
+
# --- AgentResearcher ---
|
214 |
+
# Fonctions spécifiques pour les recherches dynamiques
|
215 |
+
|
216 |
+
def fetch_webpage(url: str) -> str:
|
217 |
+
"""
|
218 |
+
Télécharge le contenu HTML d'une URL donnée.
|
219 |
+
"""
|
220 |
+
try:
|
221 |
+
response = requests.get(url, timeout=10)
|
222 |
+
response.raise_for_status()
|
223 |
+
logging.info(f"Page téléchargée avec succès : {url}")
|
224 |
+
return response.text
|
225 |
+
except requests.RequestException as e:
|
226 |
+
logging.error(f"Erreur lors de la récupération de la page {url}: {e}")
|
227 |
+
return ""
|
228 |
+
|
229 |
+
def extract_information_from_html(html: str, keyword: str) -> list:
|
230 |
+
"""
|
231 |
+
Extrait des informations pertinentes depuis le HTML en fonction d'un mot-clé.
|
232 |
+
"""
|
233 |
+
try:
|
234 |
+
soup = BeautifulSoup(html, "html.parser")
|
235 |
+
results = []
|
236 |
+
for code_block in soup.find_all("code"):
|
237 |
+
if keyword.lower() in code_block.get_text().lower():
|
238 |
+
results.append(code_block.get_text())
|
239 |
+
logging.info(f"Nombre de sections extraites pour '{keyword}' : {len(results)}")
|
240 |
+
return results
|
241 |
+
except Exception as e:
|
242 |
+
logging.error(f"Erreur lors de l'extraction des informations : {e}")
|
243 |
+
return []
|
244 |
+
|
245 |
+
def search_gradio_docs(query: str) -> dict:
|
246 |
+
"""
|
247 |
+
Recherche dans la documentation Gradio les sections pertinentes pour une requête donnée.
|
248 |
+
"""
|
249 |
+
url = "https://gradio.app/docs/"
|
250 |
+
logging.info(f"Lancement de la recherche pour la requête : {query}")
|
251 |
+
html_content = fetch_webpage(url)
|
252 |
+
if not html_content:
|
253 |
+
return {"error": "Impossible de télécharger la documentation Gradio."}
|
254 |
+
results = extract_information_from_html(html_content, query)
|
255 |
+
if not results:
|
256 |
+
return {"error": f"Aucun résultat trouvé pour '{query}'."}
|
257 |
+
return {"query": query, "results": results}
|
258 |
+
|
259 |
+
def agent_researcher():
|
260 |
+
structured_summary = project_state["AgentManager"]["structured_summary"]
|
261 |
+
if not structured_summary:
|
262 |
+
return "Le résumé structuré n'est pas disponible."
|
263 |
+
|
264 |
+
# Création du prompt en utilisant apply_chat_template
|
265 |
+
messages = [
|
266 |
+
{"role": "system", "content": "Vous êtes un assistant de recherche. Vous devez répondre en JSON avec les clés 'documentation' et 'extraits_code'."},
|
267 |
+
{"role": "user", "content": researcher_prompt_template.format(structured_summary=structured_summary)}
|
268 |
+
]
|
269 |
+
|
270 |
+
input_ids = researcher_tokenizer.apply_chat_template(
|
271 |
+
messages,
|
272 |
+
add_generation_prompt=True,
|
273 |
+
return_tensors="pt"
|
274 |
+
).to(researcher_model.device)
|
275 |
+
|
276 |
+
terminators = [
|
277 |
+
researcher_tokenizer.eos_token_id,
|
278 |
+
researcher_tokenizer.convert_tokens_to_ids("<|eot_id|>")
|
279 |
+
]
|
280 |
+
|
281 |
+
output_ids = researcher_model.generate(
|
282 |
+
input_ids,
|
283 |
+
max_new_tokens=512,
|
284 |
+
eos_token_id=terminators,
|
285 |
+
do_sample=True,
|
286 |
+
temperature=0.6,
|
287 |
+
top_p=0.9,
|
288 |
+
)
|
289 |
+
response_ids = output_ids[0][input_ids.shape[-1]:]
|
290 |
+
response = researcher_tokenizer.decode(response_ids, skip_special_tokens=True)
|
291 |
+
|
292 |
+
# Parser la réponse JSON
|
293 |
+
try:
|
294 |
+
response_json = json.loads(response)
|
295 |
+
except json.JSONDecodeError:
|
296 |
+
logging.error("La réponse du modèle n'est pas un JSON valide.")
|
297 |
+
response_json = {"documentation": "", "extraits_code": ""}
|
298 |
+
|
299 |
+
# Recherches dynamiques
|
300 |
+
search_results = search_gradio_docs(structured_summary)
|
301 |
+
if "error" in search_results:
|
302 |
+
logging.error(search_results["error"])
|
303 |
+
return search_results["error"]
|
304 |
+
|
305 |
+
# Mise à jour de l'état global
|
306 |
+
project_state["AgentResearcher"]["search_results"] = {
|
307 |
+
"model_response": response_json,
|
308 |
+
"dynamic_results": search_results["results"]
|
309 |
+
}
|
310 |
+
|
311 |
+
return f"Résultats de l'AgentResearcher :\n{response_json}\n\nRésultats dynamiques :\n{search_results['results']}"
|
312 |
+
|
313 |
+
# --- AgentAnalyzer ---
|
314 |
+
def agent_analyzer():
|
315 |
+
structured_summary = project_state["AgentManager"]["structured_summary"]
|
316 |
+
search_results = project_state["AgentResearcher"]["search_results"]
|
317 |
+
if not structured_summary or not search_results:
|
318 |
+
return "Les informations nécessaires ne sont pas disponibles pour l'analyse."
|
319 |
+
|
320 |
+
# Création du prompt avec apply_chat_template
|
321 |
+
messages = [
|
322 |
+
{"role": "system", "content": "Vous êtes un assistant d'analyse. Votre tâche est d'analyser les résultats de recherche et de vérifier leur cohérence avec le résumé structuré."},
|
323 |
+
{"role": "user", "content": analyzer_prompt_template.format(
|
324 |
+
structured_summary=structured_summary,
|
325 |
+
search_results=json.dumps(search_results, ensure_ascii=False)
|
326 |
+
)}
|
327 |
+
]
|
328 |
+
prompt = analyzer_tokenizer.apply_chat_template(messages, add_generation_prompt=True, tokenize=False)
|
329 |
+
|
330 |
+
# Création du pipeline
|
331 |
+
analyzer_pipeline = transformers.pipeline(
|
332 |
+
"text-generation",
|
333 |
+
model=analyzer_model,
|
334 |
+
tokenizer=analyzer_tokenizer,
|
335 |
+
device_map="auto"
|
336 |
+
)
|
337 |
+
|
338 |
+
# Génération du rapport d'analyse
|
339 |
+
sequences = analyzer_pipeline(
|
340 |
+
prompt,
|
341 |
+
do_sample=True,
|
342 |
+
temperature=0.7,
|
343 |
+
top_p=0.9,
|
344 |
+
num_return_sequences=1,
|
345 |
+
max_new_tokens=256,
|
346 |
+
)
|
347 |
+
analysis_report = sequences[0]['generated_text']
|
348 |
+
|
349 |
+
# Mise à jour de l'état global
|
350 |
+
project_state["AgentAnalyzer"]["analysis_report"] = analysis_report
|
351 |
+
|
352 |
+
# Détermination de la validité
|
353 |
+
if "Validité: Oui" in analysis_report:
|
354 |
+
instruction_for_coder = f"Générer du code basé sur :\n{structured_summary}\n\nRésultats de recherche :\n{search_results}"
|
355 |
+
project_state["AgentAnalyzer"]["instruction_for_coder"] = instruction_for_coder
|
356 |
+
return f"Rapport valide.\nInstructions pour l'AgentCoder prêtes."
|
357 |
+
elif "Validité: Non" in analysis_report:
|
358 |
+
project_state["AgentAnalyzer"]["instruction_for_coder"] = None
|
359 |
+
# Retourner le rapport à l'AgentManager pour clarification
|
360 |
+
return f"Rapport non valide. Besoin de clarification.\n{analysis_report}"
|
361 |
+
else:
|
362 |
+
project_state["AgentAnalyzer"]["instruction_for_coder"] = None
|
363 |
+
return f"Le rapport d'analyse ne contient pas d'information claire sur la validité. Besoin de clarification.\n{analysis_report}"
|
364 |
+
|
365 |
+
# --- AgentCoder ---
|
366 |
+
def agent_coder():
|
367 |
+
instruction_for_coder = project_state["AgentAnalyzer"]["instruction_for_coder"]
|
368 |
+
if not instruction_for_coder:
|
369 |
+
return "Les instructions pour le code ne sont pas disponibles."
|
370 |
+
|
371 |
+
# Création des messages avec apply_chat_template
|
372 |
+
messages = [
|
373 |
+
{"role": "system", "content": "You are Qwen, created by Alibaba Cloud. You are a helpful assistant."},
|
374 |
+
{"role": "user", "content": instruction_for_coder}
|
375 |
+
]
|
376 |
+
prompt = coder_tokenizer.apply_chat_template(
|
377 |
+
messages,
|
378 |
+
tokenize=False,
|
379 |
+
add_generation_prompt=True
|
380 |
+
)
|
381 |
+
|
382 |
+
# Préparation des entrées du modèle
|
383 |
+
model_inputs = coder_tokenizer(prompt, return_tensors="pt").to(coder_model.device)
|
384 |
+
|
385 |
+
# Génération du code
|
386 |
+
generated_ids = coder_model.generate(
|
387 |
+
**model_inputs,
|
388 |
+
max_new_tokens=1024,
|
389 |
+
temperature=0.7,
|
390 |
+
top_p=0.9,
|
391 |
+
)
|
392 |
+
# Exclure les tokens du prompt des sorties
|
393 |
+
generated_ids = generated_ids[:, model_inputs.input_ids.shape[-1]:]
|
394 |
+
final_code = coder_tokenizer.decode(generated_ids[0], skip_special_tokens=True)
|
395 |
+
|
396 |
+
# Mise à jour de l'état global
|
397 |
+
project_state["AgentCoder"]["final_code"] = final_code
|
398 |
+
|
399 |
+
return f"Code généré par l'AgentCoder :\n{final_code}"
|
400 |
+
|
401 |
+
# === Fonction d'interaction avec l'utilisateur ===
|
402 |
+
def user_interaction(message, chat_history):
|
403 |
+
if chat_history is None:
|
404 |
+
chat_history = []
|
405 |
+
|
406 |
+
# Vérifier si nous attendons une validation
|
407 |
+
if chat_history and isinstance(chat_history[-1], dict) and chat_history[-1].get('status') == 'awaiting_validation':
|
408 |
+
# Traiter la validation de l'utilisateur
|
409 |
+
user_validation = message
|
410 |
+
if user_validation.lower() in ["oui", "yes"]:
|
411 |
+
# Procéder avec les agents
|
412 |
+
researcher_response = agent_researcher()
|
413 |
+
analyzer_response = agent_analyzer()
|
414 |
+
if "valide" in analyzer_response.lower():
|
415 |
+
coder_response = agent_coder()
|
416 |
+
response = coder_response
|
417 |
+
else:
|
418 |
+
response = analyzer_response
|
419 |
+
else:
|
420 |
+
response = "Le résumé structuré n'a pas été validé. Veuillez fournir plus de détails."
|
421 |
+
# Retirer le statut de chat_history
|
422 |
+
chat_history.pop()
|
423 |
+
chat_history.append({'user': message, 'assistant': response})
|
424 |
+
return chat_history, chat_history
|
425 |
+
else:
|
426 |
+
# Interaction régulière avec l'AgentManager
|
427 |
+
response, chat_history, is_summary_ready = agent_manager(chat_history, message)
|
428 |
+
if is_summary_ready:
|
429 |
+
# Indiquer que nous attendons une validation
|
430 |
+
chat_history.append({'status': 'awaiting_validation'})
|
431 |
+
return chat_history, chat_history
|
432 |
+
|
433 |
+
# === Interface Gradio ===
|
434 |
+
with gr.Blocks() as interface:
|
435 |
+
chatbot = gr.Chatbot()
|
436 |
+
state = gr.State([])
|
437 |
+
msg = gr.Textbox(placeholder="Entrez votre message ici...")
|
438 |
+
send_btn = gr.Button("Envoyer")
|
439 |
+
|
440 |
+
def respond(message, chat_history):
|
441 |
+
updated_chat_history, _ = user_interaction(message, chat_history)
|
442 |
+
bot_message = updated_chat_history[-1]['assistant']
|
443 |
+
chatbot.append((message, bot_message))
|
444 |
+
return chatbot, updated_chat_history
|
445 |
+
|
446 |
+
send_btn.click(respond, inputs=[msg, state], outputs=[chatbot, state])
|
447 |
+
msg.submit(respond, inputs=[msg, state], outputs=[chatbot, state])
|
448 |
+
|
449 |
+
if __name__ == "__main__":
|
450 |
+
interface.launch()
|
451 |
+
|