LeVinh commited on
Commit
cfdcca2
·
1 Parent(s): 60d9f79

fix unable to answer agent

Browse files
Files changed (6) hide show
  1. .gradio/certificate.pem +31 -0
  2. Gradio_UI.py +0 -295
  3. agent.py +1 -12
  4. app.js +25 -0
  5. app.py +104 -57
  6. server.py +0 -97
.gradio/certificate.pem ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -----BEGIN CERTIFICATE-----
2
+ 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
31
+ -----END CERTIFICATE-----
Gradio_UI.py DELETED
@@ -1,295 +0,0 @@
1
- #!/usr/bin/env python
2
- # coding=utf-8
3
- # Copyright 2024 The HuggingFace Inc. team. All rights reserved.
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
- import mimetypes
17
- import os
18
- import re
19
- import shutil
20
- from typing import Optional
21
-
22
- from smolagents.agent_types import AgentAudio, AgentImage, AgentText, handle_agent_output_types
23
- from smolagents.agents import ActionStep, MultiStepAgent
24
- from smolagents.memory import MemoryStep
25
- from smolagents.utils import _is_package_available
26
-
27
-
28
- def pull_messages_from_step(
29
- step_log: MemoryStep,
30
- ):
31
- """Extract ChatMessage objects from agent steps with proper nesting"""
32
- import gradio as gr
33
-
34
- if isinstance(step_log, ActionStep):
35
- # Output the step number
36
- step_number = f"Step {step_log.step_number}" if step_log.step_number is not None else ""
37
- yield gr.ChatMessage(role="assistant", content=f"**{step_number}**")
38
-
39
- # First yield the thought/reasoning from the LLM
40
- if hasattr(step_log, "model_output") and step_log.model_output is not None:
41
- # Clean up the LLM output
42
- model_output = step_log.model_output.strip()
43
- # Remove any trailing <end_code> and extra backticks, handling multiple possible formats
44
- model_output = re.sub(r"```\s*<end_code>", "```", model_output) # handles ```<end_code>
45
- model_output = re.sub(r"<end_code>\s*```", "```", model_output) # handles <end_code>```
46
- model_output = re.sub(r"```\s*\n\s*<end_code>", "```", model_output) # handles ```\n<end_code>
47
- model_output = model_output.strip()
48
- yield gr.ChatMessage(role="assistant", content=model_output)
49
-
50
- # For tool calls, create a parent message
51
- if hasattr(step_log, "tool_calls") and step_log.tool_calls is not None:
52
- first_tool_call = step_log.tool_calls[0]
53
- used_code = first_tool_call.name == "python_interpreter"
54
- parent_id = f"call_{len(step_log.tool_calls)}"
55
-
56
- # Tool call becomes the parent message with timing info
57
- # First we will handle arguments based on type
58
- args = first_tool_call.arguments
59
- if isinstance(args, dict):
60
- content = str(args.get("answer", str(args)))
61
- else:
62
- content = str(args).strip()
63
-
64
- if used_code:
65
- # Clean up the content by removing any end code tags
66
- content = re.sub(r"```.*?\n", "", content) # Remove existing code blocks
67
- content = re.sub(r"\s*<end_code>\s*", "", content) # Remove end_code tags
68
- content = content.strip()
69
- if not content.startswith("```python"):
70
- content = f"```python\n{content}\n```"
71
-
72
- parent_message_tool = gr.ChatMessage(
73
- role="assistant",
74
- content=content,
75
- metadata={
76
- "title": f"🛠️ Used tool {first_tool_call.name}",
77
- "id": parent_id,
78
- "status": "pending",
79
- },
80
- )
81
- yield parent_message_tool
82
-
83
- # Nesting execution logs under the tool call if they exist
84
- if hasattr(step_log, "observations") and (
85
- step_log.observations is not None and step_log.observations.strip()
86
- ): # Only yield execution logs if there's actual content
87
- log_content = step_log.observations.strip()
88
- if log_content:
89
- log_content = re.sub(r"^Execution logs:\s*", "", log_content)
90
- yield gr.ChatMessage(
91
- role="assistant",
92
- content=f"{log_content}",
93
- metadata={"title": "📝 Execution Logs", "parent_id": parent_id, "status": "done"},
94
- )
95
-
96
- # Nesting any errors under the tool call
97
- if hasattr(step_log, "error") and step_log.error is not None:
98
- yield gr.ChatMessage(
99
- role="assistant",
100
- content=str(step_log.error),
101
- metadata={"title": "💥 Error", "parent_id": parent_id, "status": "done"},
102
- )
103
-
104
- # Update parent message metadata to done status without yielding a new message
105
- parent_message_tool.metadata["status"] = "done"
106
-
107
- # Handle standalone errors but not from tool calls
108
- elif hasattr(step_log, "error") and step_log.error is not None:
109
- yield gr.ChatMessage(role="assistant", content=str(step_log.error), metadata={"title": "💥 Error"})
110
-
111
- # Calculate duration and token information
112
- step_footnote = f"{step_number}"
113
- if hasattr(step_log, "input_token_count") and hasattr(step_log, "output_token_count"):
114
- token_str = (
115
- f" | Input-tokens:{step_log.input_token_count:,} | Output-tokens:{step_log.output_token_count:,}"
116
- )
117
- step_footnote += token_str
118
- if hasattr(step_log, "duration"):
119
- step_duration = f" | Duration: {round(float(step_log.duration), 2)}" if step_log.duration else None
120
- step_footnote += step_duration
121
- step_footnote = f"""<span style="color: #bbbbc2; font-size: 12px;">{step_footnote}</span> """
122
- yield gr.ChatMessage(role="assistant", content=f"{step_footnote}")
123
- yield gr.ChatMessage(role="assistant", content="-----")
124
-
125
-
126
- def stream_to_gradio(
127
- agent,
128
- task: str,
129
- reset_agent_memory: bool = False,
130
- additional_args: Optional[dict] = None,
131
- ):
132
- """Runs an agent with the given task and streams the messages from the agent as gradio ChatMessages."""
133
- if not _is_package_available("gradio"):
134
- raise ModuleNotFoundError(
135
- "Please install 'gradio' extra to use the GradioUI: `pip install 'smolagents[gradio]'`"
136
- )
137
- import gradio as gr
138
-
139
- total_input_tokens = 0
140
- total_output_tokens = 0
141
-
142
- for step_log in agent.run(task, stream=True, reset=reset_agent_memory, additional_args=additional_args):
143
- # Track tokens if model provides them
144
- if hasattr(agent.model, "last_input_token_count"):
145
- total_input_tokens += agent.model.last_input_token_count
146
- total_output_tokens += agent.model.last_output_token_count
147
- if isinstance(step_log, ActionStep):
148
- step_log.input_token_count = agent.model.last_input_token_count
149
- step_log.output_token_count = agent.model.last_output_token_count
150
-
151
- for message in pull_messages_from_step(
152
- step_log,
153
- ):
154
- yield message
155
-
156
- final_answer = step_log # Last log is the run's final_answer
157
- final_answer = handle_agent_output_types(final_answer)
158
-
159
- if isinstance(final_answer, AgentText):
160
- yield gr.ChatMessage(
161
- role="assistant",
162
- content=f"**Final answer:**\n{final_answer.to_string()}\n",
163
- )
164
- elif isinstance(final_answer, AgentImage):
165
- yield gr.ChatMessage(
166
- role="assistant",
167
- content={"path": final_answer.to_string(), "mime_type": "image/png"},
168
- )
169
- elif isinstance(final_answer, AgentAudio):
170
- yield gr.ChatMessage(
171
- role="assistant",
172
- content={"path": final_answer.to_string(), "mime_type": "audio/wav"},
173
- )
174
- else:
175
- yield gr.ChatMessage(role="assistant", content=f"**Final answer:** {str(final_answer)}")
176
-
177
-
178
- class GradioUI:
179
- """A one-line interface to launch your agent in Gradio"""
180
-
181
- def __init__(self, agent: MultiStepAgent, file_upload_folder: str | None = None):
182
- if not _is_package_available("gradio"):
183
- raise ModuleNotFoundError(
184
- "Please install 'gradio' extra to use the GradioUI: `pip install 'smolagents[gradio]'`"
185
- )
186
- self.agent = agent
187
- self.file_upload_folder = file_upload_folder
188
- if self.file_upload_folder is not None:
189
- if not os.path.exists(file_upload_folder):
190
- os.mkdir(file_upload_folder)
191
-
192
- def interact_with_agent(self, prompt, messages):
193
- import gradio as gr
194
-
195
- messages.append(gr.ChatMessage(role="user", content=prompt))
196
- yield messages
197
- for msg in stream_to_gradio(self.agent, task=prompt, reset_agent_memory=False):
198
- messages.append(msg)
199
- yield messages
200
- yield messages
201
-
202
- def upload_file(
203
- self,
204
- file,
205
- file_uploads_log,
206
- allowed_file_types=[
207
- "application/pdf",
208
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
209
- "text/plain",
210
- ],
211
- ):
212
- """
213
- Handle file uploads, default allowed types are .pdf, .docx, and .txt
214
- """
215
- import gradio as gr
216
-
217
- if file is None:
218
- return gr.Textbox("No file uploaded", visible=True), file_uploads_log
219
-
220
- try:
221
- mime_type, _ = mimetypes.guess_type(file.name)
222
- except Exception as e:
223
- return gr.Textbox(f"Error: {e}", visible=True), file_uploads_log
224
-
225
- if mime_type not in allowed_file_types:
226
- return gr.Textbox("File type disallowed", visible=True), file_uploads_log
227
-
228
- # Sanitize file name
229
- original_name = os.path.basename(file.name)
230
- sanitized_name = re.sub(
231
- r"[^\w\-.]", "_", original_name
232
- ) # Replace any non-alphanumeric, non-dash, or non-dot characters with underscores
233
-
234
- type_to_ext = {}
235
- for ext, t in mimetypes.types_map.items():
236
- if t not in type_to_ext:
237
- type_to_ext[t] = ext
238
-
239
- # Ensure the extension correlates to the mime type
240
- sanitized_name = sanitized_name.split(".")[:-1]
241
- sanitized_name.append("" + type_to_ext[mime_type])
242
- sanitized_name = "".join(sanitized_name)
243
-
244
- # Save the uploaded file to the specified folder
245
- file_path = os.path.join(self.file_upload_folder, os.path.basename(sanitized_name))
246
- shutil.copy(file.name, file_path)
247
-
248
- return gr.Textbox(f"File uploaded: {file_path}", visible=True), file_uploads_log + [file_path]
249
-
250
- def log_user_message(self, text_input, file_uploads_log):
251
- return (
252
- text_input
253
- + (
254
- f"\nYou have been provided with these files, which might be helpful or not: {file_uploads_log}"
255
- if len(file_uploads_log) > 0
256
- else ""
257
- ),
258
- "",
259
- )
260
-
261
- def launch(self, **kwargs):
262
- import gradio as gr
263
-
264
- with gr.Blocks(fill_height=True) as demo:
265
- stored_messages = gr.State([])
266
- file_uploads_log = gr.State([])
267
- chatbot = gr.Chatbot(
268
- label="Agent",
269
- type="messages",
270
- avatar_images=(
271
- None,
272
- "https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/communication/Alfred.png",
273
- ),
274
- scale=1,
275
- )
276
- # If an upload folder is provided, enable the upload feature
277
- if self.file_upload_folder is not None:
278
- upload_file = gr.File(label="Upload a file")
279
- upload_status = gr.Textbox(label="Upload Status", interactive=False, visible=False)
280
- upload_file.change(
281
- self.upload_file,
282
- [upload_file, file_uploads_log],
283
- [upload_status, file_uploads_log],
284
- )
285
- text_input = gr.Textbox(lines=1, label="Chat Message")
286
- text_input.submit(
287
- self.log_user_message,
288
- [text_input, file_uploads_log],
289
- [stored_messages, text_input],
290
- ).then(self.interact_with_agent, [stored_messages, chatbot], [chatbot])
291
-
292
- demo.launch(debug=True, share=True, **kwargs)
293
-
294
-
295
- __all__ = ["stream_to_gradio", "GradioUI"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
agent.py CHANGED
@@ -742,18 +742,7 @@ def build_graph(provider: str = "groq"):
742
 
743
  def retriever(state: MessagesState):
744
  """Retriever node to find similar questions."""
745
- if vector_store is not None:
746
- try:
747
- similar_question = vector_store.similarity_search(state["messages"][0].content)
748
-
749
- if similar_question:
750
- example_msg = HumanMessage(
751
- content=f"Here I provide a similar question and answer for reference: \n\n{similar_question[0].page_content}",
752
- )
753
- return {"messages": [sys_msg] + state["messages"] + [example_msg]}
754
- except Exception as e:
755
- print(f"Error in retriever: {e}")
756
-
757
  return {"messages": [sys_msg] + state["messages"]}
758
 
759
  builder = StateGraph(MessagesState)
 
742
 
743
  def retriever(state: MessagesState):
744
  """Retriever node to find similar questions."""
745
+ # Retriever disabled to avoid Supabase connection issues
 
 
 
 
 
 
 
 
 
 
 
746
  return {"messages": [sys_msg] + state["messages"]}
747
 
748
  builder = StateGraph(MessagesState)
app.js CHANGED
@@ -67,6 +67,22 @@ const App = () => {
67
  if (window.innerWidth < 1024) setSidebarOpen(false);
68
  };
69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  const updateSessionMessages = (sessionId, newMessage) => {
71
  setSessions(prev => prev.map(s =>
72
  s.id === sessionId
@@ -216,6 +232,15 @@ const App = () => {
216
  >
217
  <Icon path={ICONS.chat} className="w-4 h-4 flex-shrink-0" />
218
  <span className="flex-1 text-xs truncate">{session.title}</span>
 
 
 
 
 
 
 
 
 
219
  </div>
220
  ))
221
  )}
 
67
  if (window.innerWidth < 1024) setSidebarOpen(false);
68
  };
69
 
70
+ const handleDeleteSession = (e, sessionId) => {
71
+ e.stopPropagation();
72
+ setSessions(prev => {
73
+ const filtered = prev.filter(s => s.id !== sessionId);
74
+ if (filtered.length === 0) {
75
+ const newSession = createNewSession();
76
+ setCurrentSessionId(newSession.id);
77
+ return [newSession];
78
+ }
79
+ if (sessionId === currentSessionId) {
80
+ setCurrentSessionId(filtered[0].id);
81
+ }
82
+ return filtered;
83
+ });
84
+ };
85
+
86
  const updateSessionMessages = (sessionId, newMessage) => {
87
  setSessions(prev => prev.map(s =>
88
  s.id === sessionId
 
232
  >
233
  <Icon path={ICONS.chat} className="w-4 h-4 flex-shrink-0" />
234
  <span className="flex-1 text-xs truncate">{session.title}</span>
235
+ <button
236
+ onClick={(e) => handleDeleteSession(e, session.id)}
237
+ className="opacity-0 group-hover:opacity-100 p-1 hover:bg-red-500/20 rounded transition-all"
238
+ title="Delete chat"
239
+ >
240
+ <svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
241
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
242
+ </svg>
243
+ </button>
244
  </div>
245
  ))
246
  )}
app.py CHANGED
@@ -1,69 +1,116 @@
1
- from smolagents import CodeAgent,DuckDuckGoSearchTool, HfApiModel,load_tool,tool
2
- import datetime
3
- import requests
4
- import pytz
5
- import yaml
6
- from tools.final_answer import FinalAnswerTool
 
 
 
7
 
8
- from Gradio_UI import GradioUI
 
 
 
 
 
9
 
10
- # Below is an example of a tool that does nothing. Amaze us with your creativity !
11
- @tool
12
- def my_custom_tool(arg1:str, arg2:int)-> str: #it's import to specify the return type
13
- #Keep this format for the description / args / args description but feel free to modify the tool
14
- """A tool that does nothing yet
15
- Args:
16
- arg1: the first argument
17
- arg2: the second argument
18
- """
19
- return "What magic will you build ?"
20
 
21
- @tool
22
- def get_current_time_in_timezone(timezone: str) -> str:
23
- """A tool that fetches the current local time in a specified timezone.
24
- Args:
25
- timezone: A string representing a valid timezone (e.g., 'America/New_York').
26
- """
27
- try:
28
- # Create timezone object
29
- tz = pytz.timezone(timezone)
30
- # Get current time in that timezone
31
- local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
32
- return f"The current local time in {timezone} is: {local_time}"
33
- except Exception as e:
34
- return f"Error fetching time for timezone '{timezone}': {str(e)}"
35
 
 
36
 
37
- final_answer = FinalAnswerTool()
 
 
38
 
39
- # If the agent does not answer, the model is overloaded, please use another model or the following Hugging Face Endpoint that also contains qwen2.5 coder:
40
- # model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud'
 
41
 
42
- model = HfApiModel(
43
- max_tokens=2096,
44
- temperature=0.5,
45
- model_id='Qwen/Qwen2.5-Coder-32B-Instruct',# it is possible that this model may be overloaded
46
- custom_role_conversions=None,
47
- )
 
 
 
48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
- # Import tool from Hub
51
- image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
52
 
53
- with open("prompts.yaml", 'r') as stream:
54
- prompt_templates = yaml.safe_load(stream)
55
-
56
- agent = CodeAgent(
57
- model=model,
58
- tools=[final_answer], ## add your tools here (don't remove final answer)
59
- max_steps=6,
60
- verbosity_level=1,
61
- grammar=None,
62
- planning_interval=None,
63
- name=None,
64
- description=None,
65
- prompt_templates=prompt_templates
66
- )
67
 
 
 
 
 
 
 
68
 
69
- GradioUI(agent).launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import uvicorn
3
+ import json
4
+ from fastapi import FastAPI, UploadFile, File, Form
5
+ from fastapi.responses import FileResponse
6
+ from fastapi.staticfiles import StaticFiles
7
+ from fastapi.middleware.cors import CORSMiddleware
8
+ from pydantic import BaseModel
9
+ from typing import List, Optional
10
 
11
+ try:
12
+ from logic import GaiaApp
13
+ except ImportError:
14
+ class GaiaApp:
15
+ def process_input(self, msg, hist, files):
16
+ return "Error: logic.py not found", hist, None
17
 
18
+ app = FastAPI()
 
 
 
 
 
 
 
 
 
19
 
20
+ app.add_middleware(
21
+ CORSMiddleware,
22
+ allow_origins=["*"],
23
+ allow_methods=["*"],
24
+ allow_headers=["*"],
25
+ )
 
 
 
 
 
 
 
 
26
 
27
+ gaia_engine = GaiaApp()
28
 
29
+ class Message(BaseModel):
30
+ role: str
31
+ content: str
32
 
33
+ class ChatRequest(BaseModel):
34
+ message: str
35
+ history: List[Message]
36
 
37
+ def format_history(messages: List[Message]) -> List[tuple]:
38
+ """Convert message history from React format to agent format."""
39
+ formatted = []
40
+ for msg in messages:
41
+ if msg.role == 'user':
42
+ formatted.append((msg.content, None))
43
+ elif msg.role == 'model' and formatted and formatted[-1][1] is None:
44
+ formatted[-1] = (formatted[-1][0], msg.content)
45
+ return formatted
46
 
47
+ @app.post("/api/chat")
48
+ async def chat_endpoint(
49
+ message: str = Form(...),
50
+ history: str = Form("[]"),
51
+ files: List[UploadFile] = File(default=[])
52
+ ):
53
+ """Process chat message with optional file uploads and return agent response."""
54
+ try:
55
+ messages = json.loads(history)
56
+ formatted_history = format_history([Message(**msg) for msg in messages])
57
+
58
+ file_paths = []
59
+ if files:
60
+ os.makedirs("uploads", exist_ok=True)
61
+ for file in files:
62
+ file_path = f"uploads/{file.filename}"
63
+ with open(file_path, "wb") as f:
64
+ content = await file.read()
65
+ f.write(content)
66
+ file_paths.append(file_path)
67
+
68
+ generator = gaia_engine.process_input(message, formatted_history, file_paths or None)
69
+
70
+ final_state = None
71
+ for step in generator:
72
+ final_state = step
73
+
74
+ if final_state and final_state[1]:
75
+ # final_state[1] is the history as list of dicts with role/content
76
+ last_message = final_state[1][-1]
77
+ if isinstance(last_message, dict):
78
+ bot_response = last_message.get("content", "No response")
79
+ else:
80
+ # Fallback for tuple format
81
+ bot_response = last_message[1] if len(last_message) > 1 else "No response"
82
+ return {"reply": bot_response}
83
+
84
+ return {"reply": "No response from agent."}
85
+ except Exception as e:
86
+ print(f"Chat endpoint error: {str(e)}")
87
+ import traceback
88
+ traceback.print_exc()
89
+ return {"reply": f"Error: {str(e)}"}
90
 
91
+ ALLOWED_EXTENSIONS = {".css", ".js", ".png", ".html"}
 
92
 
93
+ @app.get("/")
94
+ async def serve_index():
95
+ return FileResponse("index.html")
 
 
 
 
 
 
 
 
 
 
 
96
 
97
+ @app.get("/{filename}")
98
+ async def serve_static(filename: str):
99
+ ext = os.path.splitext(filename)[1]
100
+ if ext in ALLOWED_EXTENSIONS and os.path.exists(filename):
101
+ return FileResponse(filename)
102
+ return FileResponse("index.html", status_code=404)
103
 
104
+ if __name__ == "__main__":
105
+ print("\n" + "="*60)
106
+ print("🚀 GAIA Agent Starting...")
107
+ print("="*60)
108
+ print(f"📍 Open in browser: http://localhost:7860")
109
+ print(f"📍 Or use: http://127.0.0.1:7860")
110
+ print("="*60 + "\n")
111
+ uvicorn.run(
112
+ "app:app",
113
+ host="0.0.0.0",
114
+ port=7860,
115
+ reload=True
116
+ )
server.py DELETED
@@ -1,97 +0,0 @@
1
- import os
2
- import uvicorn
3
- import json
4
- from fastapi import FastAPI, UploadFile, File, Form
5
- from fastapi.responses import FileResponse
6
- from fastapi.staticfiles import StaticFiles
7
- from fastapi.middleware.cors import CORSMiddleware
8
- from pydantic import BaseModel
9
- from typing import List, Optional
10
-
11
- try:
12
- from logic import GaiaApp
13
- except ImportError:
14
- class GaiaApp:
15
- def process_input(self, msg, hist, files):
16
- return "Error: logic.py not found", hist, None
17
-
18
- app = FastAPI()
19
-
20
- app.add_middleware(
21
- CORSMiddleware,
22
- allow_origins=["*"],
23
- allow_methods=["*"],
24
- allow_headers=["*"],
25
- )
26
-
27
- gaia_engine = GaiaApp()
28
-
29
- class Message(BaseModel):
30
- role: str
31
- content: str
32
-
33
- class ChatRequest(BaseModel):
34
- message: str
35
- history: List[Message]
36
-
37
- def format_history(messages: List[Message]) -> List[tuple]:
38
- """Convert message history from React format to agent format."""
39
- formatted = []
40
- for msg in messages:
41
- if msg.role == 'user':
42
- formatted.append((msg.content, None))
43
- elif msg.role == 'model' and formatted and formatted[-1][1] is None:
44
- formatted[-1] = (formatted[-1][0], msg.content)
45
- return formatted
46
-
47
- @app.post("/api/chat")
48
- async def chat_endpoint(
49
- message: str = Form(...),
50
- history: str = Form("[]"),
51
- files: List[UploadFile] = File(default=[])
52
- ):
53
- """Process chat message with optional file uploads and return agent response."""
54
- try:
55
- messages = json.loads(history)
56
- formatted_history = format_history([Message(**msg) for msg in messages])
57
-
58
- file_paths = []
59
- if files:
60
- os.makedirs("uploads", exist_ok=True)
61
- for file in files:
62
- file_path = f"uploads/{file.filename}"
63
- with open(file_path, "wb") as f:
64
- content = await file.read()
65
- f.write(content)
66
- file_paths.append(file_path)
67
-
68
- generator = gaia_engine.process_input(message, formatted_history, file_paths or None)
69
-
70
- final_state = None
71
- for step in generator:
72
- final_state = step
73
-
74
- if final_state and final_state[1]:
75
- bot_response = final_state[1][-1][1]
76
- return {"reply": bot_response}
77
-
78
- return {"reply": "No response from agent."}
79
- except Exception as e:
80
- print(f"Error: {e}")
81
- return {"reply": f"Error: {str(e)}"}
82
-
83
- ALLOWED_EXTENSIONS = {".css", ".js", ".png", ".html"}
84
-
85
- @app.get("/")
86
- async def serve_index():
87
- return FileResponse("index.html")
88
-
89
- @app.get("/{filename}")
90
- async def serve_static(filename: str):
91
- ext = os.path.splitext(filename)[1]
92
- if ext in ALLOWED_EXTENSIONS and os.path.exists(filename):
93
- return FileResponse(filename)
94
- return FileResponse("index.html", status_code=404)
95
-
96
- if __name__ == "__main__":
97
- uvicorn.run("server:app", host="0.0.0.0", port=7860, reload=True)