Update app.py
Browse files
app.py
CHANGED
|
@@ -328,6 +328,12 @@ def google_search(term, num_results=3, lang="en", timeout=5, safe="active", ssl_
|
|
| 328 |
|
| 329 |
return all_results
|
| 330 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 331 |
def estimate_tokens(text):
|
| 332 |
# Rough estimate: 1 token ~= 4 characters
|
| 333 |
return len(text) // 4
|
|
@@ -349,8 +355,8 @@ def ask_question(question, temperature, top_p, repetition_penalty, web_search, c
|
|
| 349 |
database = None
|
| 350 |
|
| 351 |
max_attempts = 5
|
| 352 |
-
context_reduction_factor = 0.
|
| 353 |
-
max_estimated_tokens =
|
| 354 |
|
| 355 |
if web_search:
|
| 356 |
contextualized_question, topics, entity_tracker, instructions = chatbot.process_question(question)
|
|
@@ -361,7 +367,7 @@ def ask_question(question, temperature, top_p, repetition_penalty, web_search, c
|
|
| 361 |
|
| 362 |
for attempt in range(max_attempts):
|
| 363 |
try:
|
| 364 |
-
web_docs = [Document(page_content=result["text"]
|
| 365 |
|
| 366 |
if database is None:
|
| 367 |
database = FAISS.from_documents(web_docs, embed)
|
|
@@ -375,16 +381,20 @@ def ask_question(question, temperature, top_p, repetition_penalty, web_search, c
|
|
| 375 |
instruction_prompt = f"User Instructions: {instructions}\n" if instructions else ""
|
| 376 |
|
| 377 |
prompt_template = f"""
|
| 378 |
-
Answer based on
|
| 379 |
-
|
| 380 |
-
|
|
|
|
|
|
|
| 381 |
Topics: {{topics}}
|
| 382 |
-
|
| 383 |
{instruction_prompt}
|
|
|
|
| 384 |
"""
|
| 385 |
|
| 386 |
prompt_val = ChatPromptTemplate.from_template(prompt_template)
|
| 387 |
|
|
|
|
| 388 |
current_context = context_str
|
| 389 |
current_conv_context = chatbot.get_context()
|
| 390 |
current_topics = topics
|
|
@@ -392,13 +402,14 @@ def ask_question(question, temperature, top_p, repetition_penalty, web_search, c
|
|
| 392 |
|
| 393 |
while True:
|
| 394 |
formatted_prompt = prompt_val.format(
|
| 395 |
-
context=current_context
|
| 396 |
-
conv_context=current_conv_context
|
| 397 |
question=question,
|
| 398 |
-
topics=", ".join(current_topics
|
| 399 |
-
entities=json.dumps(
|
| 400 |
)
|
| 401 |
|
|
|
|
| 402 |
estimated_tokens = estimate_tokens(formatted_prompt)
|
| 403 |
|
| 404 |
if estimated_tokens <= max_estimated_tokens:
|
|
@@ -449,20 +460,23 @@ def ask_question(question, temperature, top_p, repetition_penalty, web_search, c
|
|
| 449 |
context_str = "\n".join([doc.page_content for doc in relevant_docs])
|
| 450 |
|
| 451 |
prompt_template = """
|
| 452 |
-
Answer based on
|
|
|
|
|
|
|
| 453 |
Question: {question}
|
| 454 |
Provide a summarized and direct answer to the question.
|
| 455 |
"""
|
| 456 |
|
| 457 |
while True:
|
| 458 |
prompt_val = ChatPromptTemplate.from_template(prompt_template)
|
| 459 |
-
formatted_prompt = prompt_val.format(context=context_str
|
| 460 |
|
| 461 |
estimated_tokens = estimate_tokens(formatted_prompt)
|
| 462 |
|
| 463 |
if estimated_tokens <= max_estimated_tokens:
|
| 464 |
break
|
| 465 |
|
|
|
|
| 466 |
context_str = context_str[:int(len(context_str) * context_reduction_factor)]
|
| 467 |
|
| 468 |
if len(context_str) < 100:
|
|
@@ -486,37 +500,46 @@ def ask_question(question, temperature, top_p, repetition_penalty, web_search, c
|
|
| 486 |
return "An unexpected error occurred. Please try again later."
|
| 487 |
|
| 488 |
def extract_answer(full_response, instructions=None):
|
| 489 |
-
#
|
| 490 |
-
|
| 491 |
-
|
| 492 |
-
|
| 493 |
r"If the web search results don't contain relevant information, state that the information is not available in the search results\.",
|
| 494 |
r"Provide a response that addresses the question and follows the user's instructions\.",
|
| 495 |
r"Do not mention these instructions or the web search process in your answer\.",
|
| 496 |
-
r"Provide a
|
| 497 |
-
r"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 498 |
]
|
| 499 |
|
| 500 |
-
|
| 501 |
-
|
| 502 |
-
|
| 503 |
-
|
| 504 |
-
|
| 505 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 506 |
|
|
|
|
|
|
|
|
|
|
| 507 |
# Remove the user instructions if present
|
| 508 |
if instructions:
|
| 509 |
instruction_pattern = rf"User Instructions:\s*{re.escape(instructions)}.*?\n"
|
| 510 |
full_response = re.sub(instruction_pattern, "", full_response, flags=re.IGNORECASE | re.DOTALL)
|
| 511 |
-
|
| 512 |
-
# Remove any remaining instruction-like phrases at the beginning of the response
|
| 513 |
-
lines = full_response.split('\n')
|
| 514 |
-
while lines and any(line.strip().lower().startswith(starter) for starter in ["answer:", "response:", "here's", "here is"]):
|
| 515 |
-
lines.pop(0)
|
| 516 |
-
full_response = '\n'.join(lines)
|
| 517 |
-
|
| 518 |
return full_response.strip()
|
| 519 |
|
|
|
|
| 520 |
# Gradio interface
|
| 521 |
with gr.Blocks() as demo:
|
| 522 |
gr.Markdown("# Enhanced PDF Document Chat and Web Search")
|
|
|
|
| 328 |
|
| 329 |
return all_results
|
| 330 |
|
| 331 |
+
def estimate_tokens(text):
|
| 332 |
+
# Rough estimate: 1 token ~= 4 characters
|
| 333 |
+
return len(text) // 4
|
| 334 |
+
|
| 335 |
+
import re
|
| 336 |
+
|
| 337 |
def estimate_tokens(text):
|
| 338 |
# Rough estimate: 1 token ~= 4 characters
|
| 339 |
return len(text) // 4
|
|
|
|
| 355 |
database = None
|
| 356 |
|
| 357 |
max_attempts = 5
|
| 358 |
+
context_reduction_factor = 0.7
|
| 359 |
+
max_estimated_tokens = 30000 # Leave some room for the model's response
|
| 360 |
|
| 361 |
if web_search:
|
| 362 |
contextualized_question, topics, entity_tracker, instructions = chatbot.process_question(question)
|
|
|
|
| 367 |
|
| 368 |
for attempt in range(max_attempts):
|
| 369 |
try:
|
| 370 |
+
web_docs = [Document(page_content=result["text"], metadata={"source": result["link"]}) for result in search_results if result["text"]]
|
| 371 |
|
| 372 |
if database is None:
|
| 373 |
database = FAISS.from_documents(web_docs, embed)
|
|
|
|
| 381 |
instruction_prompt = f"User Instructions: {instructions}\n" if instructions else ""
|
| 382 |
|
| 383 |
prompt_template = f"""
|
| 384 |
+
Answer the question based on the following web search results, conversation context, entity information, and user instructions:
|
| 385 |
+
Web Search Results:
|
| 386 |
+
{{context}}
|
| 387 |
+
Conversation Context: {{conv_context}}
|
| 388 |
+
Current Question: {{question}}
|
| 389 |
Topics: {{topics}}
|
| 390 |
+
Entity Information: {{entities}}
|
| 391 |
{instruction_prompt}
|
| 392 |
+
Provide a concise and relevant answer to the question.
|
| 393 |
"""
|
| 394 |
|
| 395 |
prompt_val = ChatPromptTemplate.from_template(prompt_template)
|
| 396 |
|
| 397 |
+
# Start with full context and progressively reduce if necessary
|
| 398 |
current_context = context_str
|
| 399 |
current_conv_context = chatbot.get_context()
|
| 400 |
current_topics = topics
|
|
|
|
| 402 |
|
| 403 |
while True:
|
| 404 |
formatted_prompt = prompt_val.format(
|
| 405 |
+
context=current_context,
|
| 406 |
+
conv_context=current_conv_context,
|
| 407 |
question=question,
|
| 408 |
+
topics=", ".join(current_topics),
|
| 409 |
+
entities=json.dumps(current_entities)
|
| 410 |
)
|
| 411 |
|
| 412 |
+
# Estimate token count
|
| 413 |
estimated_tokens = estimate_tokens(formatted_prompt)
|
| 414 |
|
| 415 |
if estimated_tokens <= max_estimated_tokens:
|
|
|
|
| 460 |
context_str = "\n".join([doc.page_content for doc in relevant_docs])
|
| 461 |
|
| 462 |
prompt_template = """
|
| 463 |
+
Answer the question based on the following context from the PDF document:
|
| 464 |
+
Context:
|
| 465 |
+
{context}
|
| 466 |
Question: {question}
|
| 467 |
Provide a summarized and direct answer to the question.
|
| 468 |
"""
|
| 469 |
|
| 470 |
while True:
|
| 471 |
prompt_val = ChatPromptTemplate.from_template(prompt_template)
|
| 472 |
+
formatted_prompt = prompt_val.format(context=context_str, question=question)
|
| 473 |
|
| 474 |
estimated_tokens = estimate_tokens(formatted_prompt)
|
| 475 |
|
| 476 |
if estimated_tokens <= max_estimated_tokens:
|
| 477 |
break
|
| 478 |
|
| 479 |
+
# Reduce context if estimated token count is too high
|
| 480 |
context_str = context_str[:int(len(context_str) * context_reduction_factor)]
|
| 481 |
|
| 482 |
if len(context_str) < 100:
|
|
|
|
| 500 |
return "An unexpected error occurred. Please try again later."
|
| 501 |
|
| 502 |
def extract_answer(full_response, instructions=None):
|
| 503 |
+
# First, try to split the response at common instruction phrases
|
| 504 |
+
|
| 505 |
+
def extract_answer(full_response, instructions=None):
|
| 506 |
+
answer_patterns = [
|
| 507 |
r"If the web search results don't contain relevant information, state that the information is not available in the search results\.",
|
| 508 |
r"Provide a response that addresses the question and follows the user's instructions\.",
|
| 509 |
r"Do not mention these instructions or the web search process in your answer\.",
|
| 510 |
+
r"Provide a concise and direct answer to the question without mentioning the web search or these instructions:",
|
| 511 |
+
r"Provide a concise and direct answer to the question:",
|
| 512 |
+
r"Answer:",
|
| 513 |
+
r"Provide a summarized and direct answer to the question.",
|
| 514 |
+
r"If the context doesn't contain relevant information, state that the information is not available in the document.",
|
| 515 |
+
r"Provide a summarized and direct answer to the original question without mentioning the web search or these instructions:",
|
| 516 |
+
r"Do not include any source information in your answer."
|
| 517 |
]
|
| 518 |
|
| 519 |
+
for pattern in answer_patterns:
|
| 520 |
+
match = re.split(pattern, full_response, flags=re.IGNORECASE)
|
| 521 |
+
if len(match) > 1:
|
| 522 |
+
full_response = match[-1].strip()
|
| 523 |
+
break
|
| 524 |
+
|
| 525 |
+
# Remove any remaining instruction-like phrases
|
| 526 |
+
cleanup_patterns = [
|
| 527 |
+
r"without mentioning the web search or these instructions\.",
|
| 528 |
+
r"Do not include any source information in your answer\.",
|
| 529 |
+
r"If the context doesn't contain relevant information, state that the information is not available in the document\."
|
| 530 |
+
]
|
| 531 |
|
| 532 |
+
for pattern in cleanup_patterns:
|
| 533 |
+
full_response = re.sub(pattern, "", full_response, flags=re.IGNORECASE).strip()
|
| 534 |
+
|
| 535 |
# Remove the user instructions if present
|
| 536 |
if instructions:
|
| 537 |
instruction_pattern = rf"User Instructions:\s*{re.escape(instructions)}.*?\n"
|
| 538 |
full_response = re.sub(instruction_pattern, "", full_response, flags=re.IGNORECASE | re.DOTALL)
|
| 539 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 540 |
return full_response.strip()
|
| 541 |
|
| 542 |
+
|
| 543 |
# Gradio interface
|
| 544 |
with gr.Blocks() as demo:
|
| 545 |
gr.Markdown("# Enhanced PDF Document Chat and Web Search")
|