Spaces:
Runtime error
Runtime error
Upload app.py
Browse files
app.py
CHANGED
@@ -1,485 +1,24 @@
|
|
1 |
-
import
|
2 |
-
import queue
|
3 |
-
import time
|
4 |
-
import logging
|
5 |
-
from typing import List, Dict, Any, Optional
|
6 |
-
import random
|
7 |
import gradio as gr
|
8 |
-
from
|
9 |
-
import
|
10 |
-
from pathlib import Path
|
11 |
-
from datetime import datetime
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
model = AutoModelForCausalLM.from_pretrained(MODEL_NAME).to("cpu").eval()
|
16 |
|
17 |
-
|
18 |
-
|
19 |
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
|
|
|
|
25 |
|
26 |
-
|
27 |
-
outputs = model.generate(
|
28 |
-
**inputs,
|
29 |
-
max_new_tokens=max_tokens,
|
30 |
-
temperature=temperature,
|
31 |
-
do_sample=True,
|
32 |
-
top_p=0.9,
|
33 |
-
pad_token_id=tokenizer.eos_token_id or tokenizer.pad_token_id,
|
34 |
-
eos_token_id=tokenizer.eos_token_id,
|
35 |
-
)
|
36 |
-
reply = tokenizer.decode(outputs[0][inputs['input_ids'].shape[-1]:], skip_special_tokens=True).strip()
|
37 |
-
chat_history.append((user_input, reply))
|
38 |
|
39 |
-
|
40 |
-
|
41 |
-
return ""
|
42 |
-
|
43 |
-
def save_chat_log(chat_history):
|
44 |
-
data = {
|
45 |
-
"timestamp": datetime.now().isoformat(),
|
46 |
-
"chat": chat_history,
|
47 |
-
}
|
48 |
-
if CHATLOG_FILE.exists():
|
49 |
-
old_data = json.loads(CHATLOG_FILE.read_text())
|
50 |
-
else:
|
51 |
-
old_data = []
|
52 |
-
old_data.append(data)
|
53 |
-
CHATLOG_FILE.write_text(json.dumps(old_data, indent=2))
|
54 |
-
|
55 |
-
def generate_suggestions(feedback):
|
56 |
-
# Simple mock suggestions based on feedback input
|
57 |
-
# Replace with real model inference if desired
|
58 |
-
suggestions = [
|
59 |
-
f"Improve clarity on: {feedback[:50]}...",
|
60 |
-
"Add context awareness for better follow-up answers.",
|
61 |
-
"Enhance error handling for invalid inputs.",
|
62 |
-
]
|
63 |
-
# Save suggestions to changelog file
|
64 |
-
save_changelog(suggestions)
|
65 |
-
return "\n- " + "\n- ".join(suggestions)
|
66 |
-
|
67 |
-
def save_changelog(suggestions):
|
68 |
-
data = {
|
69 |
-
"timestamp": datetime.now().isoformat(),
|
70 |
-
"suggestions": suggestions,
|
71 |
-
}
|
72 |
-
if CHANGELOG_FILE.exists():
|
73 |
-
old_data = json.loads(CHANGELOG_FILE.read_text())
|
74 |
-
else:
|
75 |
-
old_data = []
|
76 |
-
old_data.append(data)
|
77 |
-
CHANGELOG_FILE.write_text(json.dumps(old_data, indent=2))
|
78 |
-
|
79 |
-
with gr.Blocks(title="Autonomous AI Minimal with Self-Improve") as demo:
|
80 |
-
gr.Markdown("# 🤖 Autonomous AI with Feedback & Logging")
|
81 |
-
|
82 |
-
with gr.Tab("Chat"):
|
83 |
-
chatbot = gr.Chatbot(label="Chat")
|
84 |
-
user_input = gr.Textbox(placeholder="Type your message here...", lines=2, label="Your Message")
|
85 |
-
temperature = gr.Slider(0.1, 1.2, value=0.7, step=0.05, label="Temperature")
|
86 |
-
max_tokens = gr.Slider(50, 300, value=150, step=25, label="Max Tokens")
|
87 |
-
send_btn = gr.Button("Send")
|
88 |
-
reset_btn = gr.Button("Reset")
|
89 |
-
|
90 |
-
state = gr.State([])
|
91 |
-
|
92 |
-
send_btn.click(generate_reply, inputs=[user_input, state, temperature, max_tokens], outputs=[user_input, chatbot])
|
93 |
-
reset_btn.click(lambda: [], None, chatbot)
|
94 |
-
reset_btn.click(lambda: [], None, state)
|
95 |
-
|
96 |
-
with gr.Tab("Self-Improve"):
|
97 |
-
feedback = gr.Textbox(label="Enter feedback or observations", lines=3)
|
98 |
-
suggest_btn = gr.Button("Generate Suggestions")
|
99 |
-
suggestions = gr.Textbox(label="Improvement Suggestions", interactive=False, lines=6)
|
100 |
-
|
101 |
-
suggest_btn.click(generate_suggestions, inputs=feedback, outputs=suggestions)
|
102 |
-
|
103 |
-
# Logging config for traceability
|
104 |
-
logging.basicConfig(level=logging.INFO, format='[%(asctime)s] %(levelname)s:%(message)s')
|
105 |
-
|
106 |
-
# ----------------------------
|
107 |
-
# 1. Memory Management Module
|
108 |
-
# ----------------------------
|
109 |
-
|
110 |
-
class MemoryManager:
|
111 |
-
def __init__(self):
|
112 |
-
self.short_term_memory = []
|
113 |
-
self.long_term_memory = []
|
114 |
-
|
115 |
-
def store_short_term(self, data: Any):
|
116 |
-
logging.info("Storing to short-term memory")
|
117 |
-
self.short_term_memory.append(data)
|
118 |
-
|
119 |
-
def store_long_term(self, data: Any):
|
120 |
-
logging.info("Storing to long-term memory")
|
121 |
-
self.long_term_memory.append(data)
|
122 |
-
|
123 |
-
def retrieve(self, query: str) -> List[Any]:
|
124 |
-
# Placeholder: sophisticated semantic retrieval (e.g. embeddings)
|
125 |
-
logging.info(f"Retrieving memory for query: {query}")
|
126 |
-
results = [item for item in self.long_term_memory if query.lower() in str(item).lower()]
|
127 |
-
return results
|
128 |
-
|
129 |
-
# ----------------------------
|
130 |
-
# 2. Multi-modal Processing Module
|
131 |
-
# ----------------------------
|
132 |
-
|
133 |
-
class MultiModalProcessor:
|
134 |
-
def process_text(self, text: str) -> Dict:
|
135 |
-
logging.info("Processing text input")
|
136 |
-
# Integrate NLP pipelines here (e.g., HuggingFace transformers)
|
137 |
-
return {"text": text.upper(), "tokens": text.split()}
|
138 |
-
|
139 |
-
def process_image(self, image_data: bytes) -> Dict:
|
140 |
-
logging.info("Processing image input")
|
141 |
-
# Placeholder for image feature extraction (e.g., CLIP, OpenCV)
|
142 |
-
return {"image_features": "image_vector_representation"}
|
143 |
-
|
144 |
-
def process_audio(self, audio_data: bytes) -> Dict:
|
145 |
-
logging.info("Processing audio input")
|
146 |
-
# Placeholder for speech-to-text or audio embeddings
|
147 |
-
return {"audio_features": "audio_vector_representation"}
|
148 |
-
|
149 |
-
def process_video(self, video_data: bytes) -> Dict:
|
150 |
-
logging.info("Processing video input")
|
151 |
-
# Placeholder for video frame extraction + feature analysis
|
152 |
-
return {"video_features": "video_vector_representation"}
|
153 |
-
|
154 |
-
# ----------------------------
|
155 |
-
# 3. Recursive Reasoning & Self-Prompting Agent
|
156 |
-
# ----------------------------
|
157 |
-
|
158 |
-
class RecursiveReasoningAgent:
|
159 |
-
def generate_prompts(self, context: Dict) -> List[str]:
|
160 |
-
logging.info("Generating reasoning prompts")
|
161 |
-
# Chain-of-thought prompt generation example
|
162 |
-
base_query = context.get("text", "No context")
|
163 |
-
return [f"Consider the implications of {base_query}",
|
164 |
-
f"What assumptions are made about {base_query}?",
|
165 |
-
f"How would changing {base_query} affect the outcome?"]
|
166 |
-
|
167 |
-
def refine_hypotheses(self, hypotheses: List[str]) -> str:
|
168 |
-
logging.info("Refining hypotheses")
|
169 |
-
# Simple heuristic: pick the longest hypothesis
|
170 |
-
if hypotheses:
|
171 |
-
return max(hypotheses, key=len)
|
172 |
-
return "No hypotheses to refine"
|
173 |
-
|
174 |
-
# ----------------------------
|
175 |
-
# 4. Goal Management and Planning
|
176 |
-
# ----------------------------
|
177 |
-
|
178 |
-
class GoalPlanner:
|
179 |
-
def __init__(self):
|
180 |
-
self.goals_queue = queue.Queue()
|
181 |
-
|
182 |
-
def add_goal(self, goal: str):
|
183 |
-
logging.info(f"Adding goal: {goal}")
|
184 |
-
self.goals_queue.put(goal)
|
185 |
-
|
186 |
-
def get_next_goal(self) -> Optional[str]:
|
187 |
-
try:
|
188 |
-
goal = self.goals_queue.get_nowait()
|
189 |
-
logging.info(f"Next goal: {goal}")
|
190 |
-
return goal
|
191 |
-
except queue.Empty:
|
192 |
-
logging.info("No goals remaining")
|
193 |
-
return None
|
194 |
-
|
195 |
-
# ----------------------------
|
196 |
-
# 5. Reinforcement Learning Module (Skeleton)
|
197 |
-
# ----------------------------
|
198 |
-
|
199 |
-
class ReinforcementLearningAgent:
|
200 |
-
def __init__(self):
|
201 |
-
self.q_table = {} # state-action value store
|
202 |
-
|
203 |
-
def select_action(self, state: str) -> str:
|
204 |
-
# Simple random policy placeholder
|
205 |
-
action = random.choice(["explore", "exploit", "wait"])
|
206 |
-
logging.info(f"Selected action '{action}' for state '{state}'")
|
207 |
-
return action
|
208 |
-
|
209 |
-
def update_policy(self, state: str, action: str, reward: float):
|
210 |
-
# Placeholder for policy update, e.g. Q-learning
|
211 |
-
logging.info(f"Updating policy for state {state} and action {action} with reward {reward}")
|
212 |
-
|
213 |
-
# ----------------------------
|
214 |
-
# 6. Neural Architecture Search (NAS) Module
|
215 |
-
# ----------------------------
|
216 |
-
|
217 |
-
class NeuralArchitectureSearch:
|
218 |
-
def search(self) -> str:
|
219 |
-
# Placeholder for automated NAS optimization (complex in real life)
|
220 |
-
new_architecture = "NAS Architecture v" + str(random.randint(1, 10))
|
221 |
-
logging.info(f"Proposed new neural architecture: {new_architecture}")
|
222 |
-
return new_architecture
|
223 |
-
|
224 |
-
# ----------------------------
|
225 |
-
# 7. Bias Detection and Mitigation
|
226 |
-
# ----------------------------
|
227 |
-
|
228 |
-
class BiasMitigation:
|
229 |
-
def detect_bias(self, data: Any) -> bool:
|
230 |
-
# Placeholder bias detection logic
|
231 |
-
bias_found = "bias" in str(data).lower()
|
232 |
-
logging.info(f"Bias detected: {bias_found}")
|
233 |
-
return bias_found
|
234 |
-
|
235 |
-
def mitigate(self, data: Any) -> Any:
|
236 |
-
# Simple mitigation: redact or flag
|
237 |
-
if self.detect_bias(data):
|
238 |
-
return "[Content Redacted for Bias]"
|
239 |
-
return data
|
240 |
-
|
241 |
-
# ----------------------------
|
242 |
-
# 8. Multi-Agent Collaboration System
|
243 |
-
# ----------------------------
|
244 |
-
|
245 |
-
class Agent:
|
246 |
-
def __init__(self, name: str):
|
247 |
-
self.name = name
|
248 |
-
|
249 |
-
def execute(self, task: str) -> str:
|
250 |
-
logging.info(f"Agent {self.name} executing task: {task}")
|
251 |
-
return f"{self.name} completed {task}"
|
252 |
-
|
253 |
-
class MultiAgentSystem:
|
254 |
-
def __init__(self, agents: List[Agent]):
|
255 |
-
self.agents = agents
|
256 |
-
|
257 |
-
def coordinate(self, task: str) -> List[str]:
|
258 |
-
results = []
|
259 |
-
for agent in self.agents:
|
260 |
-
result = agent.execute(task)
|
261 |
-
results.append(result)
|
262 |
-
return results
|
263 |
-
|
264 |
-
# ----------------------------
|
265 |
-
# 9. Explainability Module
|
266 |
-
# ----------------------------
|
267 |
-
|
268 |
-
class Explainability:
|
269 |
-
def generate_explanation(self, decision: str) -> str:
|
270 |
-
explanation = f"Decision '{decision}' was made based on heuristic rules and data analysis."
|
271 |
-
logging.info(f"Generated explanation: {explanation}")
|
272 |
-
return explanation
|
273 |
-
|
274 |
-
# ----------------------------
|
275 |
-
# 10. Ethics and Safety Guardrails
|
276 |
-
# ----------------------------
|
277 |
-
|
278 |
-
class EthicsSafety:
|
279 |
-
def check_compliance(self, output: str) -> bool:
|
280 |
-
# Placeholder ethical compliance check
|
281 |
-
compliant = "illegal" not in output.lower()
|
282 |
-
logging.info(f"Output compliance status: {compliant}")
|
283 |
-
return compliant
|
284 |
-
|
285 |
-
def filter_output(self, output: str) -> str:
|
286 |
-
if self.check_compliance(output):
|
287 |
-
return output
|
288 |
-
return "[Output blocked due to ethical concerns]"
|
289 |
-
|
290 |
-
# ----------------------------
|
291 |
-
# 11. Plugin and API Integration
|
292 |
-
# ----------------------------
|
293 |
-
|
294 |
-
class PluginManager:
|
295 |
-
def call_plugin(self, name: str, params: Dict[str, Any]) -> Any:
|
296 |
-
logging.info(f"Calling plugin '{name}' with params {params}")
|
297 |
-
# Placeholder: invoke external API or service
|
298 |
-
return f"Plugin '{name}' response with params {params}"
|
299 |
-
|
300 |
-
# ----------------------------
|
301 |
-
# 12. Multilingual Support and Translation
|
302 |
-
# ----------------------------
|
303 |
-
|
304 |
-
class LanguageSupport:
|
305 |
-
def detect_language(self, text: str) -> str:
|
306 |
-
# Very naive detection placeholder
|
307 |
-
if any(ord(c) > 128 for c in text):
|
308 |
-
lang = "non-en"
|
309 |
-
else:
|
310 |
-
lang = "en"
|
311 |
-
logging.info(f"Detected language: {lang}")
|
312 |
-
return lang
|
313 |
-
|
314 |
-
def translate(self, text: str, target_lang: str) -> str:
|
315 |
-
logging.info(f"Translating text to {target_lang}")
|
316 |
-
# Placeholder for translation, returns original
|
317 |
-
return text
|
318 |
-
|
319 |
-
# ----------------------------
|
320 |
-
# 13. Streaming Input and Adaptation
|
321 |
-
# ----------------------------
|
322 |
-
|
323 |
-
class StreamingProcessor:
|
324 |
-
def stream_input(self, data_stream: Any):
|
325 |
-
logging.info(f"Processing streaming data: {data_stream}")
|
326 |
-
# Placeholder for real-time processing logic
|
327 |
-
|
328 |
-
# ----------------------------
|
329 |
-
# 14. User Feedback Loop
|
330 |
-
# ----------------------------
|
331 |
-
|
332 |
-
class FeedbackLoop:
|
333 |
-
def receive_feedback(self, feedback: str):
|
334 |
-
logging.info(f"Received user feedback: {feedback}")
|
335 |
-
# Placeholder: integrate feedback to improve system
|
336 |
-
|
337 |
-
# ----------------------------
|
338 |
-
# 15. Deployment Automation
|
339 |
-
# ----------------------------
|
340 |
-
|
341 |
-
class DeploymentManager:
|
342 |
-
def deploy_system(self):
|
343 |
-
logging.info("Deploying system with auto-scaling and monitoring")
|
344 |
-
# Placeholder for actual deployment steps
|
345 |
-
|
346 |
-
# ----------------------------
|
347 |
-
# 16. Security and Privacy
|
348 |
-
# ----------------------------
|
349 |
-
|
350 |
-
class SecurityPrivacyManager:
|
351 |
-
def encrypt(self, data: str) -> str:
|
352 |
-
encrypted = f"encrypted({data})"
|
353 |
-
logging.info(f"Data encrypted")
|
354 |
-
return encrypted
|
355 |
-
|
356 |
-
def anonymize(self, data: str) -> str:
|
357 |
-
anonymized = f"anonymized({data})"
|
358 |
-
logging.info(f"Data anonymized")
|
359 |
-
return anonymized
|
360 |
-
|
361 |
-
# ----------------------------
|
362 |
-
# 17. Dashboard and Monitoring
|
363 |
-
# ----------------------------
|
364 |
-
|
365 |
-
class Dashboard:
|
366 |
-
def update_status(self, status: str):
|
367 |
-
logging.info(f"Dashboard status updated: {status}")
|
368 |
-
|
369 |
-
# ----------------------------
|
370 |
-
# 18. Auto Documentation and Logging
|
371 |
-
# ----------------------------
|
372 |
-
|
373 |
-
class AutoDocumentation:
|
374 |
-
def log_event(self, event: str):
|
375 |
-
logging.info(f"Logged event: {event}")
|
376 |
-
|
377 |
-
# ----------------------------
|
378 |
-
# 19. Personality & Tone Customization
|
379 |
-
# ----------------------------
|
380 |
-
|
381 |
-
class PersonalityModule:
|
382 |
-
def set_personality(self, personality: str):
|
383 |
-
logging.info(f"Personality set to: {personality}")
|
384 |
-
|
385 |
-
# ----------------------------
|
386 |
-
# 20. Robustness & Error Handling
|
387 |
-
# ----------------------------
|
388 |
-
|
389 |
-
class RobustnessManager:
|
390 |
-
def recover_from_error(self, error: Exception):
|
391 |
-
logging.error(f"Error occurred: {error}")
|
392 |
-
logging.info("Attempting recovery procedures")
|
393 |
-
|
394 |
-
# ----------------------------
|
395 |
-
# Main OmniAIvX Orchestrator
|
396 |
-
# ----------------------------
|
397 |
-
|
398 |
-
class OmniAIvX:
|
399 |
-
def __init__(self):
|
400 |
-
self.memory = MemoryManager()
|
401 |
-
self.multi_modal = MultiModalProcessor()
|
402 |
-
self.reasoning_agent = RecursiveReasoningAgent()
|
403 |
-
self.goal_planner = GoalPlanner()
|
404 |
-
self.rl_agent = ReinforcementLearningAgent()
|
405 |
-
self.nas = NeuralArchitectureSearch()
|
406 |
-
self.bias_mitigation = BiasMitigation()
|
407 |
-
self.multi_agent_system = MultiAgentSystem([Agent("RL-Agent"), Agent("NAS-Agent")])
|
408 |
-
self.explainability = Explainability()
|
409 |
-
self.ethics = EthicsSafety()
|
410 |
-
self.plugin_manager = PluginManager()
|
411 |
-
self.language_support = LanguageSupport()
|
412 |
-
self.streaming_processor = StreamingProcessor()
|
413 |
-
self.feedback_loop = FeedbackLoop()
|
414 |
-
self.deployment_manager = DeploymentManager()
|
415 |
-
self.security_privacy = SecurityPrivacyManager()
|
416 |
-
self.dashboard = Dashboard()
|
417 |
-
self.auto_doc = AutoDocumentation()
|
418 |
-
self.personality = PersonalityModule()
|
419 |
-
self.robustness = RobustnessManager()
|
420 |
-
self.task_queue = queue.Queue()
|
421 |
-
|
422 |
-
def process_input(self, input_data: Dict[str, Any]) -> Dict[str, Any]:
|
423 |
-
self.auto_doc.log_event("Input received")
|
424 |
-
processed_data = {}
|
425 |
-
|
426 |
-
# Language detection and translation
|
427 |
-
if "text" in input_data:
|
428 |
-
lang = self.language_support.detect_language(input_data["text"])
|
429 |
-
translated_text = self.language_support.translate(input_data["text"], "en")
|
430 |
-
processed_data["text"] = self.multi_modal.process_text(translated_text)
|
431 |
-
|
432 |
-
if "image" in input_data:
|
433 |
-
processed_data["image"] = self.multi_modal.process_image(input_data["image"])
|
434 |
-
|
435 |
-
if "audio" in input_data:
|
436 |
-
processed_data["audio"] = self.multi_modal.process_audio(input_data["audio"])
|
437 |
-
|
438 |
-
if "video" in input_data:
|
439 |
-
processed_data["video"] = self.multi_modal.process_video(input_data["video"])
|
440 |
-
|
441 |
-
self.memory.store_short_term(processed_data)
|
442 |
-
self.dashboard.update_status("Input processed")
|
443 |
-
return processed_data
|
444 |
-
|
445 |
-
def run_reasoning_cycle(self, context: Dict[str, Any]) -> Dict[str, Any]:
|
446 |
-
prompts = self.reasoning_agent.generate_prompts(context)
|
447 |
-
refined = self.reasoning_agent.refine_hypotheses(prompts)
|
448 |
-
goal = self.goal_planner.get_next_goal()
|
449 |
-
if not goal:
|
450 |
-
return {"message": "No goals to process."}
|
451 |
-
|
452 |
-
action = self.rl_agent.select_action(goal)
|
453 |
-
self.rl_agent.update_policy(goal, action, reward=1.0) # dummy reward
|
454 |
-
multi_agent_results = self.multi_agent_system.coordinate(goal)
|
455 |
-
explanation = self.explainability.generate_explanation(action)
|
456 |
-
safe_output = self.ethics.filter_output(action)
|
457 |
-
|
458 |
-
self.auto_doc.log_event(f"Goal '{goal}' executed with action '{action}'")
|
459 |
-
self.dashboard.update_status(f"Goal executed: {goal}")
|
460 |
-
|
461 |
-
return {
|
462 |
-
"action": safe_output,
|
463 |
-
"explanation": explanation,
|
464 |
-
"multi_agent_results": multi_agent_results,
|
465 |
-
"refined_prompt": refined
|
466 |
-
}
|
467 |
-
|
468 |
-
def update_architecture(self):
|
469 |
-
new_arch = self.nas.search()
|
470 |
-
self.auto_doc.log_event(f"Neural architecture updated to {new_arch}")
|
471 |
-
self.dashboard.update_status("Neural architecture updated")
|
472 |
-
|
473 |
-
def receive_feedback(self, feedback: str):
|
474 |
-
self.feedback_loop.receive_feedback(feedback)
|
475 |
-
self.auto_doc.log_event("User feedback processed")
|
476 |
-
|
477 |
-
def deploy(self):
|
478 |
-
self.deployment_manager.deploy_system()
|
479 |
-
self.auto_doc.log_event("System deployed")
|
480 |
-
|
481 |
-
def encrypt_and_store(self, data: str):
|
482 |
-
encrypted = self.security_privacy.encrypt(data)
|
483 |
-
self.memory.store_long_term(encrypted)
|
484 |
-
if __name__ == "__main__":
|
485 |
-
demo.launch(share=True)
|
|
|
1 |
+
from fastapi import FastAPI
|
|
|
|
|
|
|
|
|
|
|
2 |
import gradio as gr
|
3 |
+
from orchestrator import run_agents
|
4 |
+
from memory import init_memory
|
|
|
|
|
5 |
|
6 |
+
app = FastAPI()
|
7 |
+
memory = init_memory()
|
|
|
8 |
|
9 |
+
def agent_interface(goal):
|
10 |
+
return run_agents(goal, memory)
|
11 |
|
12 |
+
gr_interface = gr.Interface(
|
13 |
+
fn=agent_interface,
|
14 |
+
inputs=gr.Textbox(lines=2, placeholder="Describe your task...", label="Your Task"),
|
15 |
+
outputs=gr.Textbox(lines=20, label="Multi-Agent Output"),
|
16 |
+
title="🧠 Multi-Agent Autonomous AI System",
|
17 |
+
description="Planner → Executor → Critic | Contextual Memory | Logs | Expandable AI System"
|
18 |
+
)
|
19 |
|
20 |
+
gr.mount_gradio_app(app, gr_interface, path="/gradio")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
|
22 |
+
@app.get("/")
|
23 |
+
def root():
|
24 |
+
return {"message": "Multi-Agent AI system with logging and memory."}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|