Update app.py
Browse files
app.py
CHANGED
|
@@ -177,13 +177,27 @@ def delete_workspace(workspace_id):
|
|
| 177 |
|
| 178 |
|
| 179 |
# -------------------------------------------------------------------
|
| 180 |
-
#
|
| 181 |
# -------------------------------------------------------------------
|
| 182 |
-
def
|
| 183 |
"""
|
| 184 |
-
|
| 185 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
# Prepare the headers
|
| 188 |
headers = {
|
| 189 |
"User-Agent": "Mozilla/5.0",
|
|
@@ -192,49 +206,24 @@ def chat_with_assistant(user_input, chat_history, bot_id, workspace_id, temperat
|
|
| 192 |
"Cookie": AUTH_COOKIE
|
| 193 |
}
|
| 194 |
|
| 195 |
-
#
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
for msg in chat_history:
|
| 199 |
-
if msg["role"] == "system":
|
| 200 |
-
system_prompt = msg["content"]
|
| 201 |
-
else:
|
| 202 |
-
messages.append({
|
| 203 |
-
"role": msg["role"],
|
| 204 |
-
"content": msg["content"],
|
| 205 |
-
"type": "text"
|
| 206 |
-
})
|
| 207 |
-
|
| 208 |
-
# Add the latest user input if not already in chat history
|
| 209 |
-
if user_input and (not messages or messages[-1]["role"] != "user" or messages[-1]["content"] != user_input):
|
| 210 |
-
messages.append({
|
| 211 |
-
"role": "user",
|
| 212 |
-
"content": user_input,
|
| 213 |
-
"type": "text"
|
| 214 |
-
})
|
| 215 |
|
| 216 |
# Prepare the payload for the API
|
| 217 |
payload = {
|
| 218 |
-
"type": "
|
| 219 |
"input": {
|
| 220 |
-
"
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
"
|
| 224 |
-
"messages": messages,
|
| 225 |
-
"temperature": temperature,
|
| 226 |
-
|
| 227 |
-
"debug": False,
|
| 228 |
}
|
| 229 |
}
|
| 230 |
|
| 231 |
-
# Add maxTokens to the payload if provided
|
| 232 |
-
if max_tokens is not None:
|
| 233 |
-
payload["input"]["maxTokens"] = max_tokens
|
| 234 |
-
|
| 235 |
botpress_url = "https://api.botpress.cloud/v1/chat/actions"
|
| 236 |
max_retries = 3
|
| 237 |
-
timeout =
|
| 238 |
|
| 239 |
# Flag to track if we need to create new IDs due to quota exceeded
|
| 240 |
quota_exceeded = False
|
|
@@ -242,15 +231,14 @@ def chat_with_assistant(user_input, chat_history, bot_id, workspace_id, temperat
|
|
| 242 |
# Attempt to send the request
|
| 243 |
for attempt in range(max_retries):
|
| 244 |
try:
|
| 245 |
-
print(f"Attempt {attempt+1}: Sending request to Botpress API with bot_id={bot_id}, workspace_id={workspace_id}")
|
| 246 |
response = requests.post(botpress_url, json=payload, headers=headers, timeout=timeout)
|
| 247 |
|
| 248 |
# If successful (200)
|
| 249 |
if response.status_code == 200:
|
| 250 |
data = response.json()
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
return assistant_content, bot_id, workspace_id
|
| 254 |
|
| 255 |
# Check for quota exceeded error specifically
|
| 256 |
elif response.status_code == 403:
|
|
@@ -268,7 +256,7 @@ def chat_with_assistant(user_input, chat_history, bot_id, workspace_id, temperat
|
|
| 268 |
time.sleep(2)
|
| 269 |
continue
|
| 270 |
else:
|
| 271 |
-
return f"Unable to get
|
| 272 |
|
| 273 |
# Handle network errors or timeouts (just retry)
|
| 274 |
elif response.status_code in [404, 408, 502, 503, 504]:
|
|
@@ -283,7 +271,7 @@ def chat_with_assistant(user_input, chat_history, bot_id, workspace_id, temperat
|
|
| 283 |
time.sleep(2)
|
| 284 |
continue
|
| 285 |
else:
|
| 286 |
-
return f"Unable to get
|
| 287 |
|
| 288 |
except requests.exceptions.Timeout:
|
| 289 |
print(f"Request timed out. Retrying...")
|
|
@@ -291,7 +279,7 @@ def chat_with_assistant(user_input, chat_history, bot_id, workspace_id, temperat
|
|
| 291 |
time.sleep(2)
|
| 292 |
continue
|
| 293 |
else:
|
| 294 |
-
return "The
|
| 295 |
|
| 296 |
except Exception as e:
|
| 297 |
print(f"Error during request: {str(e)}")
|
|
@@ -299,7 +287,7 @@ def chat_with_assistant(user_input, chat_history, bot_id, workspace_id, temperat
|
|
| 299 |
time.sleep(2)
|
| 300 |
continue
|
| 301 |
else:
|
| 302 |
-
return f"Unable to get
|
| 303 |
|
| 304 |
# If quota exceeded, we need to create new resources
|
| 305 |
if quota_exceeded:
|
|
@@ -328,12 +316,12 @@ def chat_with_assistant(user_input, chat_history, bot_id, workspace_id, temperat
|
|
| 328 |
# Create new workspace
|
| 329 |
new_workspace_id = create_workspace()
|
| 330 |
if not new_workspace_id:
|
| 331 |
-
return "Failed to create a new workspace after quota exceeded. Please try again later.", bot_id, workspace_id
|
| 332 |
|
| 333 |
# Create new bot in the new workspace
|
| 334 |
new_bot_id = create_bot(new_workspace_id)
|
| 335 |
if not new_bot_id:
|
| 336 |
-
return "Failed to create a new bot after quota exceeded. Please try again later.", new_workspace_id, workspace_id
|
| 337 |
|
| 338 |
# Update headers with new bot ID
|
| 339 |
headers["x-bot-id"] = new_bot_id
|
|
@@ -345,85 +333,58 @@ def chat_with_assistant(user_input, chat_history, bot_id, workspace_id, temperat
|
|
| 345 |
|
| 346 |
if retry_response.status_code == 200:
|
| 347 |
data = retry_response.json()
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
return assistant_content, new_bot_id, new_workspace_id
|
| 351 |
else:
|
| 352 |
print(f"Failed with new IDs: {retry_response.status_code}, {retry_response.text}")
|
| 353 |
-
return f"Unable to get
|
| 354 |
|
| 355 |
except Exception as e:
|
| 356 |
print(f"Error with new IDs: {str(e)}")
|
| 357 |
-
return f"Unable to get
|
| 358 |
|
| 359 |
# Should not reach here due to the handling in the loop
|
| 360 |
-
return "Unable to get
|
| 361 |
|
| 362 |
|
| 363 |
# -------------------------------------------------------------------
|
| 364 |
-
# Flask
|
| 365 |
# -------------------------------------------------------------------
|
| 366 |
-
@app.route("/
|
| 367 |
-
def
|
| 368 |
"""
|
|
|
|
| 369 |
Expects JSON with:
|
| 370 |
{
|
| 371 |
-
"
|
| 372 |
-
"
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
...
|
| 376 |
-
],
|
| 377 |
-
"temperature": 0.9, // Optional, defaults to 0.9
|
| 378 |
-
"top_p": 0.95, // Optional, defaults to 0.95
|
| 379 |
-
"max_tokens": 1000 // Optional, defaults to null (no limit)
|
| 380 |
-
}
|
| 381 |
-
Returns JSON with:
|
| 382 |
-
{
|
| 383 |
-
"assistant_response": "string"
|
| 384 |
}
|
|
|
|
| 385 |
"""
|
| 386 |
global GLOBAL_WORKSPACE_ID, GLOBAL_BOT_ID
|
| 387 |
|
| 388 |
# Parse JSON from request
|
| 389 |
data = request.get_json(force=True)
|
| 390 |
-
|
| 391 |
-
|
|
|
|
|
|
|
| 392 |
|
| 393 |
-
#
|
| 394 |
-
|
| 395 |
-
|
| 396 |
-
max_tokens = data.get("max_tokens", None)
|
| 397 |
|
| 398 |
-
# Validate
|
| 399 |
try:
|
| 400 |
-
|
| 401 |
-
if
|
| 402 |
-
|
| 403 |
-
print(f"Invalid
|
| 404 |
except (ValueError, TypeError):
|
| 405 |
-
|
| 406 |
-
print(f"Invalid
|
| 407 |
-
|
| 408 |
-
try:
|
| 409 |
-
top_p = float(top_p)
|
| 410 |
-
if not 0 <= top_p <= 1:
|
| 411 |
-
top_p = 0.95
|
| 412 |
-
print(f"Invalid top_p value. Using default: {top_p}")
|
| 413 |
-
except (ValueError, TypeError):
|
| 414 |
-
top_p = 0.95
|
| 415 |
-
print(f"Invalid top_p format. Using default: {top_p}")
|
| 416 |
-
|
| 417 |
-
# Validate max_tokens if provided
|
| 418 |
-
if max_tokens is not None:
|
| 419 |
-
try:
|
| 420 |
-
max_tokens = int(max_tokens)
|
| 421 |
-
if max_tokens <= 0:
|
| 422 |
-
print("Invalid max_tokens value (must be positive). Not using max_tokens.")
|
| 423 |
-
max_tokens = None
|
| 424 |
-
except (ValueError, TypeError):
|
| 425 |
-
print("Invalid max_tokens format. Not using max_tokens.")
|
| 426 |
-
max_tokens = None
|
| 427 |
|
| 428 |
# If we don't yet have a workspace or bot, create them
|
| 429 |
if not GLOBAL_WORKSPACE_ID or not GLOBAL_BOT_ID:
|
|
@@ -434,20 +395,19 @@ def chat_endpoint():
|
|
| 434 |
|
| 435 |
# If creation failed
|
| 436 |
if not GLOBAL_WORKSPACE_ID or not GLOBAL_BOT_ID:
|
| 437 |
-
return jsonify({"
|
| 438 |
|
| 439 |
-
# Call our function
|
| 440 |
-
print(f"Sending
|
| 441 |
-
print(f"Using
|
| 442 |
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
|
|
|
|
|
|
| 446 |
GLOBAL_BOT_ID,
|
| 447 |
-
GLOBAL_WORKSPACE_ID
|
| 448 |
-
temperature,
|
| 449 |
-
top_p,
|
| 450 |
-
max_tokens
|
| 451 |
)
|
| 452 |
|
| 453 |
# Update global IDs if they changed
|
|
@@ -456,7 +416,8 @@ def chat_endpoint():
|
|
| 456 |
GLOBAL_BOT_ID = updated_bot_id
|
| 457 |
GLOBAL_WORKSPACE_ID = updated_workspace_id
|
| 458 |
|
| 459 |
-
|
|
|
|
| 460 |
|
| 461 |
|
| 462 |
# -------------------------------------------------------------------
|
|
|
|
| 177 |
|
| 178 |
|
| 179 |
# -------------------------------------------------------------------
|
| 180 |
+
# Web Search Function
|
| 181 |
# -------------------------------------------------------------------
|
| 182 |
+
def web_search(query, count=3, include_sites=None, exclude_sites=None, bot_id=None, workspace_id=None):
|
| 183 |
"""
|
| 184 |
+
Performs a web search using the Botpress API
|
| 185 |
+
|
| 186 |
+
Args:
|
| 187 |
+
query (str): The search query
|
| 188 |
+
count (int): Number of search results to return
|
| 189 |
+
include_sites (list): List of sites to include in the search
|
| 190 |
+
exclude_sites (list): List of sites to exclude from the search
|
| 191 |
+
bot_id (str): The bot ID to use for the request
|
| 192 |
+
workspace_id (str): The workspace ID to use for the request
|
| 193 |
+
|
| 194 |
+
Returns:
|
| 195 |
+
tuple: (search_results, bot_id, workspace_id)
|
| 196 |
"""
|
| 197 |
+
if not bot_id or not workspace_id:
|
| 198 |
+
print("Cannot perform search: Missing bot ID or workspace ID")
|
| 199 |
+
return {"error": "Missing bot ID or workspace ID"}, bot_id, workspace_id
|
| 200 |
+
|
| 201 |
# Prepare the headers
|
| 202 |
headers = {
|
| 203 |
"User-Agent": "Mozilla/5.0",
|
|
|
|
| 206 |
"Cookie": AUTH_COOKIE
|
| 207 |
}
|
| 208 |
|
| 209 |
+
# Prepare include/exclude sites
|
| 210 |
+
include_sites = include_sites or []
|
| 211 |
+
exclude_sites = exclude_sites or []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 212 |
|
| 213 |
# Prepare the payload for the API
|
| 214 |
payload = {
|
| 215 |
+
"type": "browser:webSearch",
|
| 216 |
"input": {
|
| 217 |
+
"query": query,
|
| 218 |
+
"includeSites": include_sites,
|
| 219 |
+
"excludeSites": exclude_sites,
|
| 220 |
+
"count": count
|
|
|
|
|
|
|
|
|
|
|
|
|
| 221 |
}
|
| 222 |
}
|
| 223 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 224 |
botpress_url = "https://api.botpress.cloud/v1/chat/actions"
|
| 225 |
max_retries = 3
|
| 226 |
+
timeout = 60
|
| 227 |
|
| 228 |
# Flag to track if we need to create new IDs due to quota exceeded
|
| 229 |
quota_exceeded = False
|
|
|
|
| 231 |
# Attempt to send the request
|
| 232 |
for attempt in range(max_retries):
|
| 233 |
try:
|
| 234 |
+
print(f"Attempt {attempt+1}: Sending search request to Botpress API with bot_id={bot_id}, workspace_id={workspace_id}")
|
| 235 |
response = requests.post(botpress_url, json=payload, headers=headers, timeout=timeout)
|
| 236 |
|
| 237 |
# If successful (200)
|
| 238 |
if response.status_code == 200:
|
| 239 |
data = response.json()
|
| 240 |
+
print(f"Successfully received search results from Botpress API")
|
| 241 |
+
return data, bot_id, workspace_id
|
|
|
|
| 242 |
|
| 243 |
# Check for quota exceeded error specifically
|
| 244 |
elif response.status_code == 403:
|
|
|
|
| 256 |
time.sleep(2)
|
| 257 |
continue
|
| 258 |
else:
|
| 259 |
+
return {"error": f"Unable to get search results (Error 403)."}, bot_id, workspace_id
|
| 260 |
|
| 261 |
# Handle network errors or timeouts (just retry)
|
| 262 |
elif response.status_code in [404, 408, 502, 503, 504]:
|
|
|
|
| 271 |
time.sleep(2)
|
| 272 |
continue
|
| 273 |
else:
|
| 274 |
+
return {"error": f"Unable to get search results (Error {response.status_code})."}, bot_id, workspace_id
|
| 275 |
|
| 276 |
except requests.exceptions.Timeout:
|
| 277 |
print(f"Request timed out. Retrying...")
|
|
|
|
| 279 |
time.sleep(2)
|
| 280 |
continue
|
| 281 |
else:
|
| 282 |
+
return {"error": "The search request timed out. Please try again."}, bot_id, workspace_id
|
| 283 |
|
| 284 |
except Exception as e:
|
| 285 |
print(f"Error during request: {str(e)}")
|
|
|
|
| 287 |
time.sleep(2)
|
| 288 |
continue
|
| 289 |
else:
|
| 290 |
+
return {"error": f"Unable to get search results: {str(e)}"}, bot_id, workspace_id
|
| 291 |
|
| 292 |
# If quota exceeded, we need to create new resources
|
| 293 |
if quota_exceeded:
|
|
|
|
| 316 |
# Create new workspace
|
| 317 |
new_workspace_id = create_workspace()
|
| 318 |
if not new_workspace_id:
|
| 319 |
+
return {"error": "Failed to create a new workspace after quota exceeded. Please try again later."}, bot_id, workspace_id
|
| 320 |
|
| 321 |
# Create new bot in the new workspace
|
| 322 |
new_bot_id = create_bot(new_workspace_id)
|
| 323 |
if not new_bot_id:
|
| 324 |
+
return {"error": "Failed to create a new bot after quota exceeded. Please try again later."}, new_workspace_id, workspace_id
|
| 325 |
|
| 326 |
# Update headers with new bot ID
|
| 327 |
headers["x-bot-id"] = new_bot_id
|
|
|
|
| 333 |
|
| 334 |
if retry_response.status_code == 200:
|
| 335 |
data = retry_response.json()
|
| 336 |
+
print(f"Successfully received search results with new IDs")
|
| 337 |
+
return data, new_bot_id, new_workspace_id
|
|
|
|
| 338 |
else:
|
| 339 |
print(f"Failed with new IDs: {retry_response.status_code}, {retry_response.text}")
|
| 340 |
+
return {"error": f"Unable to get search results with new credentials."}, new_bot_id, new_workspace_id
|
| 341 |
|
| 342 |
except Exception as e:
|
| 343 |
print(f"Error with new IDs: {str(e)}")
|
| 344 |
+
return {"error": f"Unable to get search results with new credentials: {str(e)}"}, new_bot_id, new_workspace_id
|
| 345 |
|
| 346 |
# Should not reach here due to the handling in the loop
|
| 347 |
+
return {"error": "Unable to get search results."}, bot_id, workspace_id
|
| 348 |
|
| 349 |
|
| 350 |
# -------------------------------------------------------------------
|
| 351 |
+
# Flask Endpoints
|
| 352 |
# -------------------------------------------------------------------
|
| 353 |
+
@app.route("/search", methods=["POST"])
|
| 354 |
+
def search_endpoint():
|
| 355 |
"""
|
| 356 |
+
Endpoint for web search.
|
| 357 |
Expects JSON with:
|
| 358 |
{
|
| 359 |
+
"query": "search query",
|
| 360 |
+
"count": 3, // Optional, defaults to 3
|
| 361 |
+
"include_sites": [], // Optional, defaults to empty list
|
| 362 |
+
"exclude_sites": [] // Optional, defaults to empty list
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 363 |
}
|
| 364 |
+
Returns the raw search results JSON from the Botpress API
|
| 365 |
"""
|
| 366 |
global GLOBAL_WORKSPACE_ID, GLOBAL_BOT_ID
|
| 367 |
|
| 368 |
# Parse JSON from request
|
| 369 |
data = request.get_json(force=True)
|
| 370 |
+
query = data.get("query", "")
|
| 371 |
+
count = data.get("count", 3)
|
| 372 |
+
include_sites = data.get("include_sites", [])
|
| 373 |
+
exclude_sites = data.get("exclude_sites", [])
|
| 374 |
|
| 375 |
+
# Validate query
|
| 376 |
+
if not query:
|
| 377 |
+
return jsonify({"error": "Query parameter is required"}), 400
|
|
|
|
| 378 |
|
| 379 |
+
# Validate count
|
| 380 |
try:
|
| 381 |
+
count = int(count)
|
| 382 |
+
if count <= 0:
|
| 383 |
+
count = 3
|
| 384 |
+
print(f"Invalid count value. Using default: {count}")
|
| 385 |
except (ValueError, TypeError):
|
| 386 |
+
count = 3
|
| 387 |
+
print(f"Invalid count format. Using default: {count}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 388 |
|
| 389 |
# If we don't yet have a workspace or bot, create them
|
| 390 |
if not GLOBAL_WORKSPACE_ID or not GLOBAL_BOT_ID:
|
|
|
|
| 395 |
|
| 396 |
# If creation failed
|
| 397 |
if not GLOBAL_WORKSPACE_ID or not GLOBAL_BOT_ID:
|
| 398 |
+
return jsonify({"error": "Failed to initialize search capability. Please try again later."}), 500
|
| 399 |
|
| 400 |
+
# Call our search function
|
| 401 |
+
print(f"Sending search request with query='{query}', count={count}")
|
| 402 |
+
print(f"Using existing bot_id={GLOBAL_BOT_ID}, workspace_id={GLOBAL_WORKSPACE_ID}")
|
| 403 |
|
| 404 |
+
search_results, updated_bot_id, updated_workspace_id = web_search(
|
| 405 |
+
query,
|
| 406 |
+
count,
|
| 407 |
+
include_sites,
|
| 408 |
+
exclude_sites,
|
| 409 |
GLOBAL_BOT_ID,
|
| 410 |
+
GLOBAL_WORKSPACE_ID
|
|
|
|
|
|
|
|
|
|
| 411 |
)
|
| 412 |
|
| 413 |
# Update global IDs if they changed
|
|
|
|
| 416 |
GLOBAL_BOT_ID = updated_bot_id
|
| 417 |
GLOBAL_WORKSPACE_ID = updated_workspace_id
|
| 418 |
|
| 419 |
+
# Return the raw API response
|
| 420 |
+
return jsonify(search_results)
|
| 421 |
|
| 422 |
|
| 423 |
# -------------------------------------------------------------------
|