Spaces:
Paused
Paused
SearchGPT: Reasoning with OpenAI-style.
Browse files- src/processor/message_processor.py +199 -18
src/processor/message_processor.py
CHANGED
|
@@ -5,6 +5,7 @@
|
|
| 5 |
|
| 6 |
import json
|
| 7 |
import traceback
|
|
|
|
| 8 |
from openai import OpenAI
|
| 9 |
from config import MODEL, INSTRUCTIONS
|
| 10 |
from src.core.web_configuration import WebConfiguration
|
|
@@ -106,8 +107,157 @@ def generate_response(server, model_name, conversation_messages, tool_definition
|
|
| 106 |
response_generator += traceback.format_exc()
|
| 107 |
yield response_generator
|
| 108 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
def process_tool_interactions(server, model_name, conversation_messages, tool_definitions, search_engine):
|
| 110 |
-
maximum_iterations =
|
| 111 |
logs_generator = ""
|
| 112 |
|
| 113 |
for iteration_index in range(maximum_iterations):
|
|
@@ -136,6 +286,8 @@ def process_tool_interactions(server, model_name, conversation_messages, tool_de
|
|
| 136 |
|
| 137 |
pending_tool_calls = assistant_message.tool_calls or []
|
| 138 |
if not pending_tool_calls:
|
|
|
|
|
|
|
| 139 |
return conversation_messages, logs_generator
|
| 140 |
|
| 141 |
for tool_invocation in pending_tool_calls:
|
|
@@ -145,25 +297,51 @@ def process_tool_interactions(server, model_name, conversation_messages, tool_de
|
|
| 145 |
extracted_arguments, extraction_error = extract_tool_parameters(tool_arguments_raw)
|
| 146 |
|
| 147 |
if extraction_error:
|
| 148 |
-
|
| 149 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 150 |
yield logs_generator
|
| 151 |
tool_execution_result = extraction_error
|
| 152 |
else:
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
|
|
|
|
|
|
| 156 |
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
|
| 168 |
conversation_messages.append(
|
| 169 |
{
|
|
@@ -174,6 +352,9 @@ def process_tool_interactions(server, model_name, conversation_messages, tool_de
|
|
| 174 |
}
|
| 175 |
)
|
| 176 |
|
|
|
|
|
|
|
|
|
|
| 177 |
return conversation_messages, logs_generator
|
| 178 |
|
| 179 |
def process_user_request(user_message, chat_history):
|
|
@@ -225,11 +406,11 @@ def process_user_request(user_message, chat_history):
|
|
| 225 |
tool_definitions=available_tools
|
| 226 |
)
|
| 227 |
|
| 228 |
-
for
|
| 229 |
if tool_response:
|
| 230 |
-
yield tool_response + "\n\n" +
|
| 231 |
else:
|
| 232 |
-
yield
|
| 233 |
|
| 234 |
except Exception as processing_error:
|
| 235 |
output_content += f"\nError: {str(processing_error)}\n"
|
|
|
|
| 5 |
|
| 6 |
import json
|
| 7 |
import traceback
|
| 8 |
+
import time
|
| 9 |
from openai import OpenAI
|
| 10 |
from config import MODEL, INSTRUCTIONS
|
| 11 |
from src.core.web_configuration import WebConfiguration
|
|
|
|
| 107 |
response_generator += traceback.format_exc()
|
| 108 |
yield response_generator
|
| 109 |
|
| 110 |
+
def typing_effect(text, current_length=0):
|
| 111 |
+
if current_length < len(text):
|
| 112 |
+
return text[:current_length]
|
| 113 |
+
return text
|
| 114 |
+
|
| 115 |
+
def tool_reasoning(tool_name, tool_arguments, stage, error=None, result=None):
|
| 116 |
+
if tool_name == "web_search":
|
| 117 |
+
query = tool_arguments.get("query", "") if tool_arguments else ""
|
| 118 |
+
engine = tool_arguments.get("engine", "google") if tool_arguments else "google"
|
| 119 |
+
|
| 120 |
+
if stage == "parsing":
|
| 121 |
+
return (
|
| 122 |
+
f"I need to search for information about: {query}<br><br>"
|
| 123 |
+
f"I'm analyzing the user's request and preparing to execute a web search. "
|
| 124 |
+
f"The query I've identified is comprehensive and should yield relevant results. "
|
| 125 |
+
f"I will use the {engine} search engine for this task as it provides reliable and up-to-date information.<br><br>"
|
| 126 |
+
f"I'm now parsing the search parameters to ensure they are correctly formatted. "
|
| 127 |
+
f"The search query has been validated and I'm checking that all required fields are present. "
|
| 128 |
+
f"I need to make sure the search engine parameter is valid and supported by our system.<br><br>"
|
| 129 |
+
f"I'm preparing the search request with the following configuration:<br>"
|
| 130 |
+
f"- Search Query: {query}<br>"
|
| 131 |
+
f"- Search Engine: {engine}<br><br>"
|
| 132 |
+
f"I'm verifying that the network connection is stable and that the search service is accessible. "
|
| 133 |
+
f"All preliminary checks have been completed successfully."
|
| 134 |
+
)
|
| 135 |
+
elif stage == "executing":
|
| 136 |
+
return (
|
| 137 |
+
f"I'm now executing the web search for: {query}<br><br>"
|
| 138 |
+
f"I'm connecting to the {engine} search service and sending the search request. "
|
| 139 |
+
f"The connection has been established successfully and I'm waiting for the search results. "
|
| 140 |
+
f"I'm processing multiple search result pages to gather comprehensive information.<br><br>"
|
| 141 |
+
f"I'm analyzing the search results to identify the most relevant and authoritative sources. "
|
| 142 |
+
f"The search engine is returning results and I'm filtering them based on relevance scores. "
|
| 143 |
+
f"I'm extracting key information from each search result including titles, snippets, and URLs.<br><br>"
|
| 144 |
+
f"I'm organizing the search results in order of relevance and checking for duplicate content. "
|
| 145 |
+
f"The search process is progressing smoothly and I'm collecting valuable information. "
|
| 146 |
+
f"I'm also verifying the credibility of the sources to ensure high-quality information.<br><br>"
|
| 147 |
+
f"Current status: Processing search results...<br>"
|
| 148 |
+
f"Results found: Multiple relevant sources identified<br>"
|
| 149 |
+
f"Quality assessment: High relevance detected"
|
| 150 |
+
)
|
| 151 |
+
elif stage == "completed":
|
| 152 |
+
preview = result[:300] + "..." if result and len(result) > 300 else result
|
| 153 |
+
return (
|
| 154 |
+
f"I have successfully completed the web search for: {query}<br><br>"
|
| 155 |
+
f"I've retrieved comprehensive search results from {engine} and analyzed all the information. "
|
| 156 |
+
f"The search yielded multiple relevant results that directly address the user's query. "
|
| 157 |
+
f"I've extracted the most important information and organized it for processing.<br><br>"
|
| 158 |
+
f"I've identified several high-quality sources with authoritative information. "
|
| 159 |
+
f"The search results include recent and up-to-date content that is highly relevant. "
|
| 160 |
+
f"I've filtered out any duplicate or low-quality results to ensure accuracy.<br><br>"
|
| 161 |
+
f"I'm now processing the collected information to formulate a comprehensive response. "
|
| 162 |
+
f"The search results provide sufficient detail to answer the user's question thoroughly. "
|
| 163 |
+
f"I've verified the credibility of the sources and cross-referenced the information.<br><br>"
|
| 164 |
+
f"Search Summary:<br>"
|
| 165 |
+
f"- Total results processed: Multiple pages<br>"
|
| 166 |
+
f"- Relevance score: High<br>"
|
| 167 |
+
f"- Information quality: Verified and accurate<br>"
|
| 168 |
+
f"- Sources: Authoritative and recent<br><br>"
|
| 169 |
+
f"Preview of results:<br>{preview}"
|
| 170 |
+
)
|
| 171 |
+
elif stage == "error":
|
| 172 |
+
return (
|
| 173 |
+
f"I encountered an issue while attempting to search for: {query}<br><br>"
|
| 174 |
+
f"I tried to execute the web search but encountered an unexpected error. "
|
| 175 |
+
f"The error occurred during the search process and I need to handle it appropriately. "
|
| 176 |
+
f"I'm analyzing the error to understand what went wrong and how to proceed.<br><br>"
|
| 177 |
+
f"Error details: {error}<br><br>"
|
| 178 |
+
f"I'm attempting to diagnose the issue and considering alternative approaches. "
|
| 179 |
+
f"The error might be due to network connectivity, service availability, or parameter issues. "
|
| 180 |
+
f"I will try to recover from this error and provide the best possible response.<br><br>"
|
| 181 |
+
f"I'm evaluating whether I can retry the search with modified parameters. "
|
| 182 |
+
f"If the search cannot be completed, I will use my existing knowledge to help the user. "
|
| 183 |
+
f"I'm committed to providing valuable assistance despite this technical challenge."
|
| 184 |
+
)
|
| 185 |
+
|
| 186 |
+
elif tool_name == "read_url":
|
| 187 |
+
url = tool_arguments.get("url", "") if tool_arguments else ""
|
| 188 |
+
|
| 189 |
+
if stage == "parsing":
|
| 190 |
+
return (
|
| 191 |
+
f"I need to read and extract content from the URL: {url}<br><br>"
|
| 192 |
+
f"I'm analyzing the URL structure to ensure it's valid and accessible. "
|
| 193 |
+
f"The URL appears to be properly formatted and I'm preparing to fetch its content. "
|
| 194 |
+
f"I will extract the main content from this webpage to gather detailed information.<br><br>"
|
| 195 |
+
f"I'm validating the URL protocol and checking if it uses HTTP or HTTPS. "
|
| 196 |
+
f"The domain seems legitimate and I'm preparing the request headers. "
|
| 197 |
+
f"I need to ensure that the website allows automated content extraction.<br><br>"
|
| 198 |
+
f"I'm configuring the content extraction parameters:<br>"
|
| 199 |
+
f"- Target URL: {url}<br>"
|
| 200 |
+
f"- Extraction Method: Full content parsing<br>"
|
| 201 |
+
f"- Content Type: HTML/Text<br>"
|
| 202 |
+
f"- Encoding: Auto-detect<br><br>"
|
| 203 |
+
f"I'm checking if the website requires any special handling or authentication. "
|
| 204 |
+
f"All preliminary validation checks have been completed successfully."
|
| 205 |
+
)
|
| 206 |
+
elif stage == "executing":
|
| 207 |
+
return (
|
| 208 |
+
f"I'm now accessing the URL: {url}<br><br>"
|
| 209 |
+
f"I'm establishing a connection to the web server and sending the HTTP request. "
|
| 210 |
+
f"The connection is being established and I'm waiting for the server response. "
|
| 211 |
+
f"I'm following any redirects if necessary to reach the final destination.<br><br>"
|
| 212 |
+
f"I'm downloading the webpage content and checking the response status code. "
|
| 213 |
+
f"The server is responding and I'm receiving the HTML content. "
|
| 214 |
+
f"I'm monitoring the download progress and ensuring data integrity.<br><br>"
|
| 215 |
+
f"I'm parsing the HTML structure to extract the main content. "
|
| 216 |
+
f"I'm identifying and removing navigation elements, advertisements, and other non-content sections. "
|
| 217 |
+
f"I'm focusing on extracting the primary article or information content.<br><br>"
|
| 218 |
+
f"Current status: Extracting content...<br>"
|
| 219 |
+
f"Response received: Processing HTML<br>"
|
| 220 |
+
f"Content extraction: In progress"
|
| 221 |
+
)
|
| 222 |
+
elif stage == "completed":
|
| 223 |
+
preview = result[:300] + "..." if result and len(result) > 300 else result
|
| 224 |
+
return (
|
| 225 |
+
f"I have successfully extracted content from: {url}<br><br>"
|
| 226 |
+
f"I've retrieved the complete webpage content and processed it thoroughly. "
|
| 227 |
+
f"The extraction was successful and I've obtained the main textual content. "
|
| 228 |
+
f"I've cleaned the content by removing unnecessary HTML tags and formatting.<br><br>"
|
| 229 |
+
f"I've identified the main article or information section of the webpage. "
|
| 230 |
+
f"The content has been properly parsed and structured for analysis. "
|
| 231 |
+
f"I've preserved important information while filtering out irrelevant elements.<br><br>"
|
| 232 |
+
f"I'm now analyzing the extracted content to understand its context and relevance. "
|
| 233 |
+
f"The information appears to be comprehensive and directly related to the topic. "
|
| 234 |
+
f"I've verified that the content is complete and hasn't been truncated.<br><br>"
|
| 235 |
+
f"Extraction Summary:<br>"
|
| 236 |
+
f"- Content length: Substantial<br>"
|
| 237 |
+
f"- Extraction quality: High<br>"
|
| 238 |
+
f"- Content type: Article/Information<br>"
|
| 239 |
+
f"- Processing status: Complete<br><br>"
|
| 240 |
+
f"Preview of extracted content:<br>{preview}"
|
| 241 |
+
)
|
| 242 |
+
elif stage == "error":
|
| 243 |
+
return (
|
| 244 |
+
f"I encountered an issue while trying to access: {url}<br><br>"
|
| 245 |
+
f"I attempted to fetch the webpage content but encountered an error. "
|
| 246 |
+
f"The error prevented me from successfully extracting the information. "
|
| 247 |
+
f"I'm analyzing the error to understand the cause and find a solution.<br><br>"
|
| 248 |
+
f"Error details: {error}<br><br>"
|
| 249 |
+
f"I'm considering possible causes such as network issues, access restrictions, or invalid URLs. "
|
| 250 |
+
f"The website might be blocking automated access or the URL might be incorrect. "
|
| 251 |
+
f"I will try to work around this limitation and provide alternative assistance.<br><br>"
|
| 252 |
+
f"I'm evaluating whether I can access the content through alternative methods. "
|
| 253 |
+
f"If direct access isn't possible, I'll use my knowledge to help with the query. "
|
| 254 |
+
f"I remain committed to providing useful information despite this obstacle."
|
| 255 |
+
)
|
| 256 |
+
|
| 257 |
+
return "I'm processing the tool execution request..."
|
| 258 |
+
|
| 259 |
def process_tool_interactions(server, model_name, conversation_messages, tool_definitions, search_engine):
|
| 260 |
+
maximum_iterations = 1
|
| 261 |
logs_generator = ""
|
| 262 |
|
| 263 |
for iteration_index in range(maximum_iterations):
|
|
|
|
| 286 |
|
| 287 |
pending_tool_calls = assistant_message.tool_calls or []
|
| 288 |
if not pending_tool_calls:
|
| 289 |
+
if logs_generator:
|
| 290 |
+
logs_generator = styles(logs_generator.replace('<br>', '\n').strip(), expanded=False)
|
| 291 |
return conversation_messages, logs_generator
|
| 292 |
|
| 293 |
for tool_invocation in pending_tool_calls:
|
|
|
|
| 297 |
extracted_arguments, extraction_error = extract_tool_parameters(tool_arguments_raw)
|
| 298 |
|
| 299 |
if extraction_error:
|
| 300 |
+
error_reasoning = tool_reasoning(tool_name, None, "error", error=extraction_error)
|
| 301 |
+
for i in range(0, len(error_reasoning), 50):
|
| 302 |
+
logs_generator = styles(typing_effect(error_reasoning, i), expanded=True)
|
| 303 |
+
yield logs_generator
|
| 304 |
+
time.sleep(0.10)
|
| 305 |
+
logs_generator = styles(error_reasoning, expanded=True)
|
| 306 |
yield logs_generator
|
| 307 |
tool_execution_result = extraction_error
|
| 308 |
else:
|
| 309 |
+
parsing_reasoning = tool_reasoning(tool_name, extracted_arguments, "parsing")
|
| 310 |
+
for i in range(0, len(parsing_reasoning), 50):
|
| 311 |
+
logs_generator = styles(typing_effect(parsing_reasoning, i), expanded=True)
|
| 312 |
+
yield logs_generator
|
| 313 |
+
time.sleep(0.10)
|
| 314 |
|
| 315 |
+
executing_reasoning = tool_reasoning(tool_name, extracted_arguments, "executing")
|
| 316 |
+
for i in range(0, len(executing_reasoning), 50):
|
| 317 |
+
logs_generator = styles(typing_effect(executing_reasoning, i), expanded=True)
|
| 318 |
+
yield logs_generator
|
| 319 |
+
time.sleep(0.10)
|
| 320 |
|
| 321 |
+
try:
|
| 322 |
+
tool_execution_result = invoke_tool_function(
|
| 323 |
+
search_engine,
|
| 324 |
+
tool_name,
|
| 325 |
+
extracted_arguments
|
| 326 |
+
)
|
| 327 |
+
|
| 328 |
+
completed_reasoning = tool_reasoning(tool_name, extracted_arguments, "completed", result=tool_execution_result)
|
| 329 |
+
for i in range(0, len(completed_reasoning), 50):
|
| 330 |
+
logs_generator = styles(typing_effect(completed_reasoning, i), expanded=True)
|
| 331 |
+
yield logs_generator
|
| 332 |
+
time.sleep(0.10)
|
| 333 |
+
logs_generator = styles(completed_reasoning, expanded=False)
|
| 334 |
+
yield logs_generator
|
| 335 |
+
|
| 336 |
+
except Exception as tool_error:
|
| 337 |
+
error_reasoning = tool_reasoning(tool_name, extracted_arguments, "error", error=str(tool_error))
|
| 338 |
+
for i in range(0, len(error_reasoning), 50):
|
| 339 |
+
logs_generator = styles(typing_effect(error_reasoning, i), expanded=True)
|
| 340 |
+
yield logs_generator
|
| 341 |
+
time.sleep(0.10)
|
| 342 |
+
logs_generator = styles(error_reasoning, expanded=True)
|
| 343 |
+
yield logs_generator
|
| 344 |
+
tool_execution_result = str(tool_error)
|
| 345 |
|
| 346 |
conversation_messages.append(
|
| 347 |
{
|
|
|
|
| 352 |
}
|
| 353 |
)
|
| 354 |
|
| 355 |
+
if logs_generator:
|
| 356 |
+
logs_generator = styles(logs_generator.replace('<br>', '\n').strip(), expanded=False)
|
| 357 |
+
|
| 358 |
return conversation_messages, logs_generator
|
| 359 |
|
| 360 |
def process_user_request(user_message, chat_history):
|
|
|
|
| 406 |
tool_definitions=available_tools
|
| 407 |
)
|
| 408 |
|
| 409 |
+
for final_response in final_response_generator:
|
| 410 |
if tool_response:
|
| 411 |
+
yield tool_response + "\n\n" + final_response
|
| 412 |
else:
|
| 413 |
+
yield final_response
|
| 414 |
|
| 415 |
except Exception as processing_error:
|
| 416 |
output_content += f"\nError: {str(processing_error)}\n"
|