mokrane25 commited on
Commit
1f848f3
Β·
verified Β·
1 Parent(s): c1a51db

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +261 -60
app.py CHANGED
@@ -1,64 +1,265 @@
 
 
1
  import gradio as gr
2
- from huggingface_hub import InferenceClient
3
-
4
- """
5
- For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
6
- """
7
- client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
8
-
9
-
10
- def respond(
11
- message,
12
- history: list[tuple[str, str]],
13
- system_message,
14
- max_tokens,
15
- temperature,
16
- top_p,
17
- ):
18
- messages = [{"role": "system", "content": system_message}]
19
-
20
- for val in history:
21
- if val[0]:
22
- messages.append({"role": "user", "content": val[0]})
23
- if val[1]:
24
- messages.append({"role": "assistant", "content": val[1]})
25
-
26
- messages.append({"role": "user", "content": message})
27
-
28
- response = ""
29
-
30
- for message in client.chat_completion(
31
- messages,
32
- max_tokens=max_tokens,
33
- stream=True,
34
- temperature=temperature,
35
- top_p=top_p,
36
- ):
37
- token = message.choices[0].delta.content
38
-
39
- response += token
40
- yield response
41
-
42
-
43
- """
44
- For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
45
- """
46
- demo = gr.ChatInterface(
47
- respond,
48
- additional_inputs=[
49
- gr.Textbox(value="You are a friendly Chatbot.", label="System message"),
50
- gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
51
- gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
52
- gr.Slider(
53
- minimum=0.1,
54
- maximum=1.0,
55
- value=0.95,
56
- step=0.05,
57
- label="Top-p (nucleus sampling)",
58
- ),
59
- ],
60
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
 
 
 
 
 
 
62
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  if __name__ == "__main__":
64
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+
3
  import gradio as gr
4
+ import os
5
+ import traceback
6
+ import asyncio
7
+ from dotenv import load_dotenv
8
+ from models.task_prompt import TaskPrompt
9
+ import time
10
+ from llama_index.core import Settings as LlamaSettings # Import at top level
11
+ from llama_index.llms.anthropic import Anthropic # Import at top level
12
+ from manager_agent import ManagerAgent # Ensure this path is correct
13
+ import concurrent.futures # For running blocking code in a separate thread
14
+
15
+ # Load environment variables from .env file
16
+ load_dotenv()
17
+
18
+ # --- Configuration ---
19
+ LLM_MODEL = "claude-sonnet-4-20250514"
20
+
21
+ # --- Global variables ---
22
+ current_status = "Ready"
23
+ llm_global = None
24
+ manager_agent_global = None
25
+ # Settings_global is not strictly needed as a global if LlamaSettings is imported directly
26
+
27
+ # Thread pool executor for running blocking agent tasks
28
+ thread_pool_executor = concurrent.futures.ThreadPoolExecutor(max_workers=os.cpu_count() or 1)
29
+
30
+
31
+ # --- LlamaIndex LLM Initialization ---
32
+ def initialize_components():
33
+ global llm_global, manager_agent_global
34
+
35
+ api_key = os.environ.get("ANTHROPIC_API_KEY")
36
+ if not api_key:
37
+ print("\n" + "="*60)
38
+ print("⚠️ ERROR: ANTHROPIC_API_KEY not found in environment variables!")
39
+ print("Please set your API key (e.g., in a .env file).")
40
+ print("="*60 + "\n")
41
+ return
42
+
43
+ try:
44
+ llm_global = Anthropic(
45
+ model=LLM_MODEL,
46
+ temperature=0.2,
47
+ max_tokens=4096
48
+ )
49
+ LlamaSettings.llm = llm_global # Use the imported LlamaSettings directly
50
+ print(f"Successfully initialized LlamaIndex with Anthropic model: {LLM_MODEL} (temperature=0.2)")
51
+
52
+ manager_agent_global = ManagerAgent(
53
+ llm_global,
54
+ max_iterations=30, # Keep this reasonable for testing
55
+ update_callback=update_status_callback
56
+ )
57
+ print("βœ… ManagerAgent initialized successfully")
58
+
59
+ except Exception as e:
60
+ print(f"Error initializing Anthropic LLM or ManagerAgent: {e}")
61
+ traceback.print_exc()
62
+
63
+ # --- Update callback function (called by ManagerAgent) ---
64
+ def update_status_callback(message):
65
+ global current_status
66
+ # This function is called from the ManagerAgent's thread (potentially)
67
+ # or the ReAct agent's execution context.
68
+ # It needs to update the global variable, which the Gradio polling thread will pick up.
69
+ current_status = message
70
+ print(f"βœ… UI_STATUS_UPDATE (via callback): {message}") # Differentiate console log
71
+
72
+ # --- Status retrieval function for Gradio polling ---
73
+ def get_current_status_for_ui():
74
+ global current_status
75
+ timestamp = time.time()
76
+ return f"{current_status}<span style='display:none;'>{timestamp}</span>"
77
+
78
+ # --- Gradio Interface Setup ---
79
+ def create_gradio_interface():
80
+ if "ANTHROPIC_API_KEY" not in os.environ:
81
+ gr.Warning("ANTHROPIC_API_KEY not found in environment variables! ALITA may not function correctly.")
82
+
83
+ with gr.Blocks(theme="soft") as demo:
84
+ gr.Markdown("# ALITA")
85
+ gr.Markdown("ALITA is a self-learning AI agent that can search for information, analyze data, create tools, and orchestrate complex tasks.")
86
+
87
+ chatbot_component = gr.Chatbot(
88
+ label="Chat",
89
+ height=500,
90
+ show_label=False,
91
+ # type='messages' # For Gradio 4.x+
92
+ )
93
+ gr.Markdown("Gradio version: " + gr.__version__ + " (Chatbot type defaults to 'tuples' for older versions. Consider `type='messages'` for newer Gradio if issues persist with chat display).")
94
+
95
+
96
+ with gr.Row():
97
+ message_textbox = gr.Textbox(
98
+ placeholder="Type your message here...",
99
+ scale=7,
100
+ show_label=False,
101
+ container=False
102
+ )
103
+
104
+ gr.Examples(
105
+ examples=[
106
+ "πŸ” Search for information on artificial intelligence",
107
+ "πŸ“Š Analyze technology market trends",
108
+ "⚑ Create a script to automate a repetitive task",
109
+ "🌐 Find open source resources for machine learning",
110
+ ],
111
+ inputs=message_textbox,
112
+ )
113
+
114
+ status_box_component = gr.Textbox(
115
+ label="Agent Status",
116
+ value=get_current_status_for_ui(),
117
+ interactive=False,
118
+ # elem_id="status_box_alita" # For potential direct JS manipulation if desperate (avoid)
119
+ )
120
 
121
+ def add_user_msg(user_input_text, chat_history_list):
122
+ if not user_input_text.strip():
123
+ return gr.update(), chat_history_list
124
+ # For older Gradio, history is list of [user_msg, bot_msg] tuples
125
+ chat_history_list.append((user_input_text, None))
126
+ return gr.update(value=""), chat_history_list
127
 
128
+ async def generate_bot_reply(chat_history_list):
129
+ if not chat_history_list or chat_history_list[-1][0] is None:
130
+ # This case should ideally not be reached if add_user_msg works correctly
131
+ yield chat_history_list
132
+ return
133
+
134
+ user_message = chat_history_list[-1][0]
135
+
136
+ if manager_agent_global is None or LlamaSettings.llm is None:
137
+ # This update_status_callback will set current_status
138
+ # The polling mechanism (continuous_status_updater) should pick it up.
139
+ update_status_callback("⚠️ Error: Agent or LLM not initialized. Check API key and logs.")
140
+ # For older Gradio, update the last tuple's second element
141
+ chat_history_list[-1] = (chat_history_list[-1][0], "❌ Critical Error: ALITA is not properly initialized. Please check server logs and API key.")
142
+ yield chat_history_list
143
+ return
144
+
145
+ try:
146
+ print(f"\nπŸ€– GRADIOLOG: Processing user message: '{user_message[:100]}{'...' if len(user_message) > 100 else ''}'")
147
+ update_status_callback(f"πŸ’¬ Processing: '{user_message[:50]}{'...' if len(user_message) > 50 else ''}'")
148
+ await asyncio.sleep(0.01) # Allow UI to briefly update with "Processing..."
149
+
150
+ task_prompt = TaskPrompt(text=user_message)
151
+
152
+ update_status_callback("πŸ”„ Analyzing request and determining optimal workflow...")
153
+ await asyncio.sleep(0.01) # Allow UI to briefly update
154
+
155
+ # Run the blocking manager_agent_global.run_task in a separate thread
156
+ loop = asyncio.get_event_loop()
157
+ response_text_from_agent = await loop.run_in_executor(
158
+ thread_pool_executor,
159
+ manager_agent_global.run_task, # The function to run
160
+ task_prompt # Arguments to the function
161
+ )
162
+ # By this point, run_task has completed, and all its internal
163
+ # calls to update_status_callback (via send_update) should have occurred.
164
+ # The polling mechanism should have picked up these changes.
165
+
166
+ update_status_callback("✨ Generating final response stream...")
167
+ await asyncio.sleep(0.01)
168
+ final_bot_response = response_text_from_agent
169
+
170
+ words = final_bot_response.split()
171
+ accumulated_response_stream = ""
172
+ total_words = len(words)
173
+
174
+ # Initialize bot's part of the message in history for older Gradio
175
+ current_user_message = chat_history_list[-1][0]
176
+ chat_history_list[-1] = (current_user_message, "")
177
+
178
+
179
+ if not words:
180
+ chat_history_list[-1] = (current_user_message, final_bot_response.strip())
181
+ yield chat_history_list
182
+ else:
183
+ for i, word in enumerate(words):
184
+ accumulated_response_stream += word + " "
185
+ # These status updates are for the streaming part,
186
+ # agent's internal updates should have already happened.
187
+ if total_words > 0: # Avoid division by zero
188
+ if i == total_words // 4: update_status_callback("πŸ”„ Streaming response (25%)...")
189
+ elif i == total_words // 2: update_status_callback("πŸ”„ Streaming response (50%)...")
190
+ elif i == (total_words * 3) // 4: update_status_callback("πŸ”„ Streaming response (75%)...")
191
+
192
+ if i % 3 == 0 or i == len(words) - 1:
193
+ chat_history_list[-1] = (current_user_message, accumulated_response_stream.strip())
194
+ yield chat_history_list
195
+ await asyncio.sleep(0.01) # For streaming effect
196
+
197
+ # Ensure final complete response is set
198
+ if chat_history_list[-1][1] != final_bot_response.strip():
199
+ chat_history_list[-1] = (current_user_message, final_bot_response.strip())
200
+ yield chat_history_list
201
+
202
+ print("βœ… GRADIOLOG: Task processing and streaming completed.")
203
+ update_status_callback("βœ… Ready for your next request")
204
+
205
+ except Exception as e:
206
+ error_message_for_ui = f"❌ Gradio/Agent Error: {str(e)}"
207
+ print(f"\n🚨 GRADIOLOG: Error in generate_bot_reply: {e}")
208
+ traceback.print_exc()
209
+ update_status_callback(f"❌ Error: {str(e)[:100]}...")
210
+ chat_history_list[-1] = (chat_history_list[-1][0], error_message_for_ui)
211
+ yield chat_history_list
212
+
213
+ message_textbox.submit(
214
+ add_user_msg,
215
+ inputs=[message_textbox, chatbot_component],
216
+ outputs=[message_textbox, chatbot_component],
217
+ show_progress="hidden", # Gradio 3.x might not have this, can be ignored
218
+ ).then(
219
+ generate_bot_reply,
220
+ inputs=[chatbot_component],
221
+ outputs=[chatbot_component],
222
+ api_name=False, # Good practice
223
+ # show_progress="hidden", # Gradio 3.x might not have this
224
+ )
225
+
226
+ async def continuous_status_updater(update_interval_seconds=0.3): # Slightly faster poll
227
+ """Continuously yields status updates for the status_box_component."""
228
+ print("GRADIOLOG: Starting continuous_status_updater loop.")
229
+ while True:
230
+ # print(f"POLL: Fetching status: {current_status}") # DEBUG: very verbose
231
+ yield get_current_status_for_ui()
232
+ await asyncio.sleep(update_interval_seconds)
233
+
234
+ demo.load(continuous_status_updater, inputs=None, outputs=status_box_component)
235
+ print("GRADIOLOG: Continuous status updater loaded.")
236
+ return demo
237
+
238
+ # Initialize LLM and Agent components
239
+ initialize_components()
240
+
241
+ # --- Launch the Application ---
242
  if __name__ == "__main__":
243
+ print(f"Gradio version: {gr.__version__}")
244
+
245
+ print("πŸš€ Starting Gradio ALITA Chat Application...")
246
+ alita_interface = create_gradio_interface()
247
+
248
+ try:
249
+ alita_interface.launch(
250
+ share=False,
251
+ server_name="127.0.0.1",
252
+ server_port=6126,
253
+ show_error=True,
254
+ # debug=True # Can be helpful
255
+ )
256
+ except KeyboardInterrupt:
257
+ print("\nπŸ‘‹ Application stopped by user")
258
+ except Exception as e:
259
+ print(f"\n❌ Error launching application: {e}")
260
+ traceback.print_exc()
261
+ finally:
262
+ print("Shutting down thread pool executor...")
263
+ thread_pool_executor.shutdown(wait=True) # Clean up threads
264
+
265
+ print("βœ… Gradio application stopped.")