csabakecskemeti commited on
Commit
bfb4d2b
·
verified ·
1 Parent(s): 9649399

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -39
app.py CHANGED
@@ -18,11 +18,11 @@ ENABLE_DETAILED_LOGGING = True
18
  if ENABLE_DETAILED_LOGGING:
19
  # Create formatter
20
  formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
21
-
22
  # Setup console handler
23
  console_handler = logging.StreamHandler()
24
  console_handler.setFormatter(formatter)
25
-
26
  # Setup rotating file handler (7 days, daily rotation)
27
  file_handler = logging.handlers.TimedRotatingFileHandler(
28
  'agent.log',
@@ -32,7 +32,7 @@ if ENABLE_DETAILED_LOGGING:
32
  encoding='utf-8'
33
  )
34
  file_handler.setFormatter(formatter)
35
-
36
  # Configure root logger
37
  logging.basicConfig(
38
  level=logging.INFO,
@@ -51,8 +51,6 @@ llm_model = os.environ.get('model')
51
 
52
  # Tavily API configuration
53
  tavily_key = os.environ.get('tavily_key', '')
54
- if tavily_key:
55
- os.environ['TAVILY_API_KEY'] = tavily_key
56
 
57
  # Tavily search tool integration
58
 
@@ -64,7 +62,7 @@ class ReactAgentChat:
64
  self.model = model
65
  self.agent = None
66
  self._setup_agent()
67
-
68
  def _setup_agent(self):
69
  """Initialize the LangGraph ReAct agent"""
70
  try:
@@ -72,7 +70,7 @@ class ReactAgentChat:
72
  logger.info(f"=== SETTING UP AGENT ===")
73
  logger.info(f"LLM URL: http://{self.ip}:{self.port}/v1")
74
  logger.info(f"Model: {self.model}")
75
-
76
  # Create OpenAI-compatible model
77
  llm = ChatOpenAI(
78
  base_url=f"http://{self.ip}:{self.port}/v1",
@@ -82,7 +80,7 @@ class ReactAgentChat:
82
  )
83
  if ENABLE_DETAILED_LOGGING:
84
  logger.info("LLM created successfully")
85
-
86
  # Define tools - use Tavily search API with graceful error handling
87
  if tavily_key:
88
  if ENABLE_DETAILED_LOGGING:
@@ -94,6 +92,7 @@ class ReactAgentChat:
94
  """Search the web for current information about any topic."""
95
  try:
96
  tavily_tool = TavilySearch(
 
97
  max_results=5,
98
  topic="general",
99
  include_answer=True,
@@ -107,7 +106,7 @@ class ReactAgentChat:
107
  error_str = str(e).lower()
108
  if ENABLE_DETAILED_LOGGING:
109
  logger.error(f"Tavily search failed for query '{query}': {e}")
110
-
111
  # Check for rate limit or quota issues
112
  if any(keyword in error_str for keyword in ['rate limit', 'quota', 'limit exceeded', 'usage limit', 'billing']):
113
  if ENABLE_DETAILED_LOGGING:
@@ -117,7 +116,7 @@ class ReactAgentChat:
117
  if ENABLE_DETAILED_LOGGING:
118
  logger.error(f"Tavily API error: {e}")
119
  return "I can't search the web right now."
120
-
121
  search_tool = web_search
122
  if ENABLE_DETAILED_LOGGING:
123
  logger.info("Tavily search tool wrapper created successfully")
@@ -140,49 +139,49 @@ class ReactAgentChat:
140
  logger.error("Search attempted but no Tavily API key configured")
141
  return "I can't search the web right now."
142
  search_tool = no_search
143
-
144
  tools = [search_tool]
145
  if ENABLE_DETAILED_LOGGING:
146
  logger.info(f"Tools defined: {[tool.name for tool in tools]}")
147
-
148
  # Bind tools to the model
149
  model_with_tools = llm.bind_tools(tools)
150
  if ENABLE_DETAILED_LOGGING:
151
  logger.info("Tools bound to model")
152
-
153
  # Create the ReAct agent
154
  self.agent = create_react_agent(model_with_tools, tools)
155
  if ENABLE_DETAILED_LOGGING:
156
  logger.info("ReAct agent created successfully")
157
-
158
  except Exception as e:
159
  logger.error(f"=== AGENT SETUP ERROR ===")
160
  logger.error(f"Failed to setup agent: {e}")
161
  import traceback
162
  logger.error(f"Traceback: {traceback.format_exc()}")
163
  raise e
164
-
165
  def update_config(self, ip: str, port: str, api_key: str, model: str):
166
  """Update LLM configuration"""
167
- if (ip != self.ip or port != self.port or
168
  api_key != self.api_key or model != self.model):
169
  self.ip = ip
170
  self.port = port
171
  self.api_key = api_key
172
  self.model = model
173
  self._setup_agent()
174
-
175
  def chat(self, message: str, history: List[List[str]]) -> str:
176
  """Generate chat response using ReAct agent"""
177
  try:
178
  if not self.agent:
179
  return "Error: Agent not initialized"
180
-
181
  if ENABLE_DETAILED_LOGGING:
182
  logger.info(f"=== USER INPUT ===")
183
  logger.info(f"Message: {message}")
184
  logger.info(f"History length: {len(history)}")
185
-
186
  # Convert history to messages for context handling
187
  messages = []
188
  for user_msg, assistant_msg in history:
@@ -190,33 +189,33 @@ class ReactAgentChat:
190
  if assistant_msg: # Only add if assistant responded
191
  from langchain_core.messages import AIMessage
192
  messages.append(AIMessage(content=assistant_msg))
193
-
194
  # Add current message
195
  messages.append(HumanMessage(content=message))
196
-
197
  # Invoke the agent
198
  if ENABLE_DETAILED_LOGGING:
199
  logger.info(f"=== INVOKING AGENT ===")
200
  logger.info(f"Total messages in history: {len(messages)}")
201
  response = self.agent.invoke({"messages": messages})
202
-
203
  if ENABLE_DETAILED_LOGGING:
204
  logger.info(f"=== AGENT RESPONSE ===")
205
  logger.info(f"Full response: {response}")
206
  logger.info(f"Number of messages: {len(response.get('messages', []))}")
207
-
208
  # Log each message in the response
209
  for i, msg in enumerate(response.get("messages", [])):
210
  logger.info(f"Message {i}: Type={type(msg).__name__}, Content={getattr(msg, 'content', 'No content')}")
211
-
212
  # Extract the final response
213
  final_message = response["messages"][-1].content
214
  if ENABLE_DETAILED_LOGGING:
215
  logger.info(f"=== FINAL MESSAGE ===")
216
  logger.info(f"Final message: {final_message}")
217
-
218
  return final_message
219
-
220
  except Exception as e:
221
  error_msg = f"Agent error: {str(e)}"
222
  logger.error(f"=== AGENT ERROR ===")
@@ -229,25 +228,25 @@ class ReactAgentChat:
229
  # Global agent instance
230
  react_agent = ReactAgentChat(llm_ip, llm_port, llm_key, llm_model)
231
 
232
- def generate_response(message: str, history: List[List[str]], system_prompt: str,
233
  max_tokens: int, ip: str, port: str, api_key: str, model: str):
234
  """Generate response using ReAct agent"""
235
  global react_agent
236
-
237
  try:
238
  # Update agent configuration if changed
239
  react_agent.update_config(ip, port, api_key, model)
240
-
241
  # Generate response
242
  response = react_agent.chat(message, history)
243
-
244
  # Stream the response word by word for better UX
245
  words = response.split()
246
  current_response = ""
247
  for word in words:
248
  current_response += word + " "
249
  yield current_response.strip()
250
-
251
  except Exception as e:
252
  error_msg = f"Error: {str(e)}"
253
  logger.error(error_msg)
@@ -261,31 +260,32 @@ chatbot = gr.ChatInterface(
261
  None,
262
  "https://cdn-avatars.huggingface.co/v1/production/uploads/64e6d37e02dee9bcb9d9fa18/o_HhUnXb_PgyYlqJ6gfEO.png"
263
  ],
264
- height="64vh"
 
265
  ),
266
  additional_inputs=[
267
  gr.Textbox(
268
- "You are a helpful AI assistant with web search capabilities.",
269
  label="System Prompt",
270
  lines=2
271
  ),
272
- gr.Slider(50, 2048, label="Max Tokens", value=512,
273
  info="Maximum number of tokens in the response"),
274
- gr.Textbox(llm_ip, label="LLM IP Address",
275
  info="IP address of the OpenAI-compatible LLM server"),
276
- gr.Textbox(llm_port, label="LLM Port",
277
  info="Port of the LLM server"),
278
  gr.Textbox(llm_key, label="API Key", type="password",
279
  info="API key for the LLM server"),
280
- gr.Textbox(llm_model, label="Model Name",
281
  info="Name of the model to use"),
282
  ],
283
  title="🤖 LangGraph ReAct Agent with DuckDuckGo Search",
284
  description="Chat with a LangGraph ReAct agent that can search the web using DuckDuckGo. Ask about current events, research topics, or any questions that require up-to-date information!",
285
  theme="finlaymacklon/smooth_slate",
286
  submit_btn="Send",
287
- # retry_btn="🔄 Regenerate Response",
288
- # undo_btn="↩ Delete Previous",
289
  clear_btn="🗑️ Clear Chat"
290
  )
291
 
 
18
  if ENABLE_DETAILED_LOGGING:
19
  # Create formatter
20
  formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
21
+
22
  # Setup console handler
23
  console_handler = logging.StreamHandler()
24
  console_handler.setFormatter(formatter)
25
+
26
  # Setup rotating file handler (7 days, daily rotation)
27
  file_handler = logging.handlers.TimedRotatingFileHandler(
28
  'agent.log',
 
32
  encoding='utf-8'
33
  )
34
  file_handler.setFormatter(formatter)
35
+
36
  # Configure root logger
37
  logging.basicConfig(
38
  level=logging.INFO,
 
51
 
52
  # Tavily API configuration
53
  tavily_key = os.environ.get('tavily_key', '')
 
 
54
 
55
  # Tavily search tool integration
56
 
 
62
  self.model = model
63
  self.agent = None
64
  self._setup_agent()
65
+
66
  def _setup_agent(self):
67
  """Initialize the LangGraph ReAct agent"""
68
  try:
 
70
  logger.info(f"=== SETTING UP AGENT ===")
71
  logger.info(f"LLM URL: http://{self.ip}:{self.port}/v1")
72
  logger.info(f"Model: {self.model}")
73
+
74
  # Create OpenAI-compatible model
75
  llm = ChatOpenAI(
76
  base_url=f"http://{self.ip}:{self.port}/v1",
 
80
  )
81
  if ENABLE_DETAILED_LOGGING:
82
  logger.info("LLM created successfully")
83
+
84
  # Define tools - use Tavily search API with graceful error handling
85
  if tavily_key:
86
  if ENABLE_DETAILED_LOGGING:
 
92
  """Search the web for current information about any topic."""
93
  try:
94
  tavily_tool = TavilySearch(
95
+ api_key=tavily_key,
96
  max_results=5,
97
  topic="general",
98
  include_answer=True,
 
106
  error_str = str(e).lower()
107
  if ENABLE_DETAILED_LOGGING:
108
  logger.error(f"Tavily search failed for query '{query}': {e}")
109
+
110
  # Check for rate limit or quota issues
111
  if any(keyword in error_str for keyword in ['rate limit', 'quota', 'limit exceeded', 'usage limit', 'billing']):
112
  if ENABLE_DETAILED_LOGGING:
 
116
  if ENABLE_DETAILED_LOGGING:
117
  logger.error(f"Tavily API error: {e}")
118
  return "I can't search the web right now."
119
+
120
  search_tool = web_search
121
  if ENABLE_DETAILED_LOGGING:
122
  logger.info("Tavily search tool wrapper created successfully")
 
139
  logger.error("Search attempted but no Tavily API key configured")
140
  return "I can't search the web right now."
141
  search_tool = no_search
142
+
143
  tools = [search_tool]
144
  if ENABLE_DETAILED_LOGGING:
145
  logger.info(f"Tools defined: {[tool.name for tool in tools]}")
146
+
147
  # Bind tools to the model
148
  model_with_tools = llm.bind_tools(tools)
149
  if ENABLE_DETAILED_LOGGING:
150
  logger.info("Tools bound to model")
151
+
152
  # Create the ReAct agent
153
  self.agent = create_react_agent(model_with_tools, tools)
154
  if ENABLE_DETAILED_LOGGING:
155
  logger.info("ReAct agent created successfully")
156
+
157
  except Exception as e:
158
  logger.error(f"=== AGENT SETUP ERROR ===")
159
  logger.error(f"Failed to setup agent: {e}")
160
  import traceback
161
  logger.error(f"Traceback: {traceback.format_exc()}")
162
  raise e
163
+
164
  def update_config(self, ip: str, port: str, api_key: str, model: str):
165
  """Update LLM configuration"""
166
+ if (ip != self.ip or port != self.port or
167
  api_key != self.api_key or model != self.model):
168
  self.ip = ip
169
  self.port = port
170
  self.api_key = api_key
171
  self.model = model
172
  self._setup_agent()
173
+
174
  def chat(self, message: str, history: List[List[str]]) -> str:
175
  """Generate chat response using ReAct agent"""
176
  try:
177
  if not self.agent:
178
  return "Error: Agent not initialized"
179
+
180
  if ENABLE_DETAILED_LOGGING:
181
  logger.info(f"=== USER INPUT ===")
182
  logger.info(f"Message: {message}")
183
  logger.info(f"History length: {len(history)}")
184
+
185
  # Convert history to messages for context handling
186
  messages = []
187
  for user_msg, assistant_msg in history:
 
189
  if assistant_msg: # Only add if assistant responded
190
  from langchain_core.messages import AIMessage
191
  messages.append(AIMessage(content=assistant_msg))
192
+
193
  # Add current message
194
  messages.append(HumanMessage(content=message))
195
+
196
  # Invoke the agent
197
  if ENABLE_DETAILED_LOGGING:
198
  logger.info(f"=== INVOKING AGENT ===")
199
  logger.info(f"Total messages in history: {len(messages)}")
200
  response = self.agent.invoke({"messages": messages})
201
+
202
  if ENABLE_DETAILED_LOGGING:
203
  logger.info(f"=== AGENT RESPONSE ===")
204
  logger.info(f"Full response: {response}")
205
  logger.info(f"Number of messages: {len(response.get('messages', []))}")
206
+
207
  # Log each message in the response
208
  for i, msg in enumerate(response.get("messages", [])):
209
  logger.info(f"Message {i}: Type={type(msg).__name__}, Content={getattr(msg, 'content', 'No content')}")
210
+
211
  # Extract the final response
212
  final_message = response["messages"][-1].content
213
  if ENABLE_DETAILED_LOGGING:
214
  logger.info(f"=== FINAL MESSAGE ===")
215
  logger.info(f"Final message: {final_message}")
216
+
217
  return final_message
218
+
219
  except Exception as e:
220
  error_msg = f"Agent error: {str(e)}"
221
  logger.error(f"=== AGENT ERROR ===")
 
228
  # Global agent instance
229
  react_agent = ReactAgentChat(llm_ip, llm_port, llm_key, llm_model)
230
 
231
+ def generate_response(message: str, history: List[List[str]], system_prompt: str,
232
  max_tokens: int, ip: str, port: str, api_key: str, model: str):
233
  """Generate response using ReAct agent"""
234
  global react_agent
235
+
236
  try:
237
  # Update agent configuration if changed
238
  react_agent.update_config(ip, port, api_key, model)
239
+
240
  # Generate response
241
  response = react_agent.chat(message, history)
242
+
243
  # Stream the response word by word for better UX
244
  words = response.split()
245
  current_response = ""
246
  for word in words:
247
  current_response += word + " "
248
  yield current_response.strip()
249
+
250
  except Exception as e:
251
  error_msg = f"Error: {str(e)}"
252
  logger.error(error_msg)
 
260
  None,
261
  "https://cdn-avatars.huggingface.co/v1/production/uploads/64e6d37e02dee9bcb9d9fa18/o_HhUnXb_PgyYlqJ6gfEO.png"
262
  ],
263
+ height="64vh",
264
+ type="messages"
265
  ),
266
  additional_inputs=[
267
  gr.Textbox(
268
+ "You are a helpful AI assistant with web search capabilities.",
269
  label="System Prompt",
270
  lines=2
271
  ),
272
+ gr.Slider(50, 2048, label="Max Tokens", value=512,
273
  info="Maximum number of tokens in the response"),
274
+ gr.Textbox(llm_ip, label="LLM IP Address",
275
  info="IP address of the OpenAI-compatible LLM server"),
276
+ gr.Textbox(llm_port, label="LLM Port",
277
  info="Port of the LLM server"),
278
  gr.Textbox(llm_key, label="API Key", type="password",
279
  info="API key for the LLM server"),
280
+ gr.Textbox(llm_model, label="Model Name",
281
  info="Name of the model to use"),
282
  ],
283
  title="🤖 LangGraph ReAct Agent with DuckDuckGo Search",
284
  description="Chat with a LangGraph ReAct agent that can search the web using DuckDuckGo. Ask about current events, research topics, or any questions that require up-to-date information!",
285
  theme="finlaymacklon/smooth_slate",
286
  submit_btn="Send",
287
+ retry_btn="🔄 Regenerate Response",
288
+ undo_btn="↩ Delete Previous",
289
  clear_btn="🗑️ Clear Chat"
290
  )
291