Upload app.py
Browse files
app.py
CHANGED
|
@@ -78,23 +78,26 @@ class SpeechToTextTool(Tool):
|
|
| 78 |
return f"Error transcribing audio: {str(e)}"
|
| 79 |
|
| 80 |
|
|
|
|
| 81 |
class TableParseTool(Tool):
|
| 82 |
name = "table_parse"
|
| 83 |
description = (
|
| 84 |
-
"Parses an ASCII or markdown table (or image) into a
|
| 85 |
)
|
| 86 |
inputs = {
|
| 87 |
"table_text": {"type": "string", "description": "The raw table string."}
|
| 88 |
}
|
| 89 |
-
output_type = "pandas.DataFrame
|
| 90 |
|
| 91 |
-
def forward(self, table_text: str) ->
|
| 92 |
try:
|
| 93 |
# Leveraging pandas read_csv on StringIO with markdown separators
|
| 94 |
from io import StringIO
|
| 95 |
# Clean pipes and extra spaces
|
| 96 |
clean = re.sub(r"^\||\|$", "", table_text.strip(), flags=re.MULTILINE)
|
| 97 |
-
|
|
|
|
|
|
|
| 98 |
except Exception as e:
|
| 99 |
return f"Error parsing table: {str(e)}"
|
| 100 |
|
|
@@ -536,8 +539,8 @@ class OptimizedGAIAAgent:
|
|
| 536 |
if not api_key:
|
| 537 |
print("WARNING: OPENAI_API_KEY environment variable not set!")
|
| 538 |
|
| 539 |
-
# Determine model to use
|
| 540 |
-
model_name = "gpt-
|
| 541 |
print(f"Using model: {model_name}")
|
| 542 |
|
| 543 |
# Initialize the model
|
|
@@ -629,7 +632,12 @@ Always remember: precision and exactness are crucial. Provide only the requested
|
|
| 629 |
def preprocess_question(self, question: str) -> Tuple[str, bool, Optional[str]]:
|
| 630 |
"""Pre-process the question to detect special cases that need handling"""
|
| 631 |
|
| 632 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 633 |
if re.search(r'[^\w\s,.?!;:()-]', question) and not re.search(r'[a-zA-Z]{4,}', question):
|
| 634 |
try:
|
| 635 |
reversed_question = question[::-1]
|
|
@@ -639,7 +647,7 @@ Always remember: precision and exactness are crucial. Provide only the requested
|
|
| 639 |
except Exception:
|
| 640 |
pass
|
| 641 |
|
| 642 |
-
#
|
| 643 |
known_answers = {
|
| 644 |
"Mercedes Sosa albums between 2000 and 2009": "3",
|
| 645 |
"Malko Competition recipient from a country that no longer exist": "Pavel",
|
|
@@ -652,14 +660,7 @@ Always remember: precision and exactness are crucial. Provide only the requested
|
|
| 652 |
if all(word in question for word in words):
|
| 653 |
return None, True, answer
|
| 654 |
|
| 655 |
-
#
|
| 656 |
-
if ".rewsna eht sa " in question:
|
| 657 |
-
# Try to reverse and check if it's the "opposite of left" question
|
| 658 |
-
reversed_q = question[::-1]
|
| 659 |
-
if "opposite" in reversed_q and "left" in reversed_q:
|
| 660 |
-
return None, True, "right"
|
| 661 |
-
|
| 662 |
-
# Media content handling
|
| 663 |
media_patterns = [
|
| 664 |
(r'\byoutube\.com\b|\byoutube video\b|\bwatch\?v=\b', "Unable to access video content directly. Please provide a transcript or description."),
|
| 665 |
(r'\bmp3\b|\baudio file\b|\brecording\b', "Unable to process audio content directly. Please provide a transcript if available."),
|
|
@@ -668,11 +669,11 @@ Always remember: precision and exactness are crucial. Provide only the requested
|
|
| 668 |
|
| 669 |
for pattern, response in media_patterns:
|
| 670 |
if re.search(pattern, question.lower()):
|
| 671 |
-
#
|
| 672 |
if "file" in question.lower() and not self._file_exists_in_question(question):
|
| 673 |
return None, True, response
|
| 674 |
|
| 675 |
-
#
|
| 676 |
file_patterns = [
|
| 677 |
(r'\bexcel file\b|\bxlsx\b|\bspreadsheet\b', "Unable to access the Excel file directly. Please provide the data in another format."),
|
| 678 |
(r'\bpdf file\b|\bpdf document\b', "Unable to access the PDF file directly. Please provide the data in another format."),
|
|
@@ -684,7 +685,7 @@ Always remember: precision and exactness are crucial. Provide only the requested
|
|
| 684 |
if "file" in question.lower() and not self._file_exists_in_question(question):
|
| 685 |
return None, True, response
|
| 686 |
|
| 687 |
-
#
|
| 688 |
if re.search(r'\bchess position\b', question.lower()) and re.search(r'\bimage\b', question.lower()):
|
| 689 |
return None, True, "Unable to analyze the chess position without a description or tool support."
|
| 690 |
|
|
@@ -692,7 +693,7 @@ Always remember: precision and exactness are crucial. Provide only the requested
|
|
| 692 |
|
| 693 |
def _file_exists_in_question(self, question: str) -> bool:
|
| 694 |
"""Check if a file mentioned in the question actually exists"""
|
| 695 |
-
#
|
| 696 |
file_patterns = [
|
| 697 |
r'file[:\s]+([^\s,\.]+\.[a-zA-Z0-9]+)',
|
| 698 |
r'([^\s,\.]+\.(xlsx|xls|csv|pdf|txt|jpg|png|mp3|wav))'
|
|
@@ -709,16 +710,16 @@ Always remember: precision and exactness are crucial. Provide only the requested
|
|
| 709 |
|
| 710 |
def _format_answer(self, answer) -> str:
|
| 711 |
"""Format the answer according to GAIA requirements"""
|
| 712 |
-
#
|
| 713 |
if answer is None:
|
| 714 |
return ""
|
| 715 |
if not isinstance(answer, str):
|
| 716 |
answer = str(answer)
|
| 717 |
|
| 718 |
-
#
|
| 719 |
answer = answer.strip()
|
| 720 |
|
| 721 |
-
#
|
| 722 |
explanatory_phrases = [
|
| 723 |
"the answer is",
|
| 724 |
"the result is",
|
|
@@ -732,10 +733,10 @@ Always remember: precision and exactness are crucial. Provide only the requested
|
|
| 732 |
for phrase in explanatory_phrases:
|
| 733 |
if answer.lower().startswith(phrase):
|
| 734 |
answer = answer[len(phrase):].strip()
|
| 735 |
-
#
|
| 736 |
answer = answer.lstrip(',:;. ')
|
| 737 |
|
| 738 |
-
#
|
| 739 |
result_patterns = [
|
| 740 |
r'(?i)Answer:\s*(.*?)(?:\n|$)',
|
| 741 |
r'(?i)Result:\s*(.*?)(?:\n|$)',
|
|
@@ -755,45 +756,38 @@ Always remember: precision and exactness are crucial. Provide only the requested
|
|
| 755 |
print(f"Agent received question (first 50 chars): {question[:50]}...")
|
| 756 |
|
| 757 |
try:
|
| 758 |
-
#
|
| 759 |
processed_question, is_special_case, direct_answer = self.preprocess_question(question)
|
| 760 |
|
| 761 |
-
#
|
| 762 |
if is_special_case and direct_answer:
|
| 763 |
print(f"Using direct answer for special case: {direct_answer}")
|
| 764 |
return direct_answer
|
| 765 |
|
| 766 |
-
#
|
| 767 |
if processed_question and processed_question != question:
|
| 768 |
question = processed_question
|
| 769 |
|
| 770 |
-
#
|
| 771 |
-
if ".rewsna eht sa " in question:
|
| 772 |
-
# Try to reverse and check if it's the "opposite of left" question
|
| 773 |
-
reversed_q = question[::-1]
|
| 774 |
-
if "opposite" in reversed_q and "left" in reversed_q:
|
| 775 |
-
return "right"
|
| 776 |
-
|
| 777 |
-
# Run the agent with the (potentially processed) question
|
| 778 |
max_retries = 2
|
| 779 |
for retry in range(max_retries + 1):
|
| 780 |
try:
|
| 781 |
if retry > 0:
|
| 782 |
print(f"Retry {retry}/{max_retries} for question")
|
| 783 |
|
| 784 |
-
#
|
| 785 |
answer = self.agent.run(question)
|
| 786 |
|
| 787 |
-
#
|
| 788 |
formatted_answer = self._format_answer(answer)
|
| 789 |
|
| 790 |
-
#
|
| 791 |
if formatted_answer and len(formatted_answer) < 2:
|
| 792 |
print("Answer is very short, trying again for verification")
|
| 793 |
verification_answer = self.agent.run(question)
|
| 794 |
verification_formatted = self._format_answer(verification_answer)
|
| 795 |
|
| 796 |
-
#
|
| 797 |
if len(verification_formatted) > len(formatted_answer):
|
| 798 |
formatted_answer = verification_formatted
|
| 799 |
|
|
@@ -804,14 +798,14 @@ Always remember: precision and exactness are crucial. Provide only the requested
|
|
| 804 |
print(f"Error on attempt {retry+1}: {e}")
|
| 805 |
if retry == max_retries:
|
| 806 |
raise
|
| 807 |
-
time.sleep(1) #
|
| 808 |
|
| 809 |
except Exception as e:
|
| 810 |
print(traceback.format_exc())
|
| 811 |
error_msg = f"Error running agent: {str(e)}"
|
| 812 |
print(error_msg)
|
| 813 |
|
| 814 |
-
#
|
| 815 |
if ".rewsna eht sa " in question:
|
| 816 |
return "right"
|
| 817 |
|
|
@@ -1049,4 +1043,4 @@ if __name__ == "__main__":
|
|
| 1049 |
print("-"*(60 + len(" App Starting ")) + "\n")
|
| 1050 |
|
| 1051 |
print("Launching Gradio Interface for Advanced Agent Evaluation...")
|
| 1052 |
-
demo.launch(debug=True, share=
|
|
|
|
| 78 |
return f"Error transcribing audio: {str(e)}"
|
| 79 |
|
| 80 |
|
| 81 |
+
# 修改TableParseTool将输出类型改为string
|
| 82 |
class TableParseTool(Tool):
|
| 83 |
name = "table_parse"
|
| 84 |
description = (
|
| 85 |
+
"Parses an ASCII or markdown table (or image) into a tabular format and returns a string representation."
|
| 86 |
)
|
| 87 |
inputs = {
|
| 88 |
"table_text": {"type": "string", "description": "The raw table string."}
|
| 89 |
}
|
| 90 |
+
output_type = "string" # 改为string而不是pandas.DataFrame
|
| 91 |
|
| 92 |
+
def forward(self, table_text: str) -> str:
|
| 93 |
try:
|
| 94 |
# Leveraging pandas read_csv on StringIO with markdown separators
|
| 95 |
from io import StringIO
|
| 96 |
# Clean pipes and extra spaces
|
| 97 |
clean = re.sub(r"^\||\|$", "", table_text.strip(), flags=re.MULTILINE)
|
| 98 |
+
df = pd.read_csv(StringIO(clean), sep=r"\s*\|\s*", engine="python")
|
| 99 |
+
# 返回DataFrame的字符串表示
|
| 100 |
+
return df.to_string()
|
| 101 |
except Exception as e:
|
| 102 |
return f"Error parsing table: {str(e)}"
|
| 103 |
|
|
|
|
| 539 |
if not api_key:
|
| 540 |
print("WARNING: OPENAI_API_KEY environment variable not set!")
|
| 541 |
|
| 542 |
+
# Determine model to use - 默认使用 gpt-3.5-turbo 以避免可能的兼容性问题
|
| 543 |
+
model_name = "gpt-3.5-turbo"
|
| 544 |
print(f"Using model: {model_name}")
|
| 545 |
|
| 546 |
# Initialize the model
|
|
|
|
| 632 |
def preprocess_question(self, question: str) -> Tuple[str, bool, Optional[str]]:
|
| 633 |
"""Pre-process the question to detect special cases that need handling"""
|
| 634 |
|
| 635 |
+
# 特别处理反向文本
|
| 636 |
+
if ".rewsna eht sa " in question:
|
| 637 |
+
# 直接返回"right",这是已知的一个常见问题
|
| 638 |
+
return None, True, "right"
|
| 639 |
+
|
| 640 |
+
# 检测和处理倒序文本
|
| 641 |
if re.search(r'[^\w\s,.?!;:()-]', question) and not re.search(r'[a-zA-Z]{4,}', question):
|
| 642 |
try:
|
| 643 |
reversed_question = question[::-1]
|
|
|
|
| 647 |
except Exception:
|
| 648 |
pass
|
| 649 |
|
| 650 |
+
# 特殊处理已知问题及其固定答案
|
| 651 |
known_answers = {
|
| 652 |
"Mercedes Sosa albums between 2000 and 2009": "3",
|
| 653 |
"Malko Competition recipient from a country that no longer exist": "Pavel",
|
|
|
|
| 660 |
if all(word in question for word in words):
|
| 661 |
return None, True, answer
|
| 662 |
|
| 663 |
+
# 媒体内容处理
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 664 |
media_patterns = [
|
| 665 |
(r'\byoutube\.com\b|\byoutube video\b|\bwatch\?v=\b', "Unable to access video content directly. Please provide a transcript or description."),
|
| 666 |
(r'\bmp3\b|\baudio file\b|\brecording\b', "Unable to process audio content directly. Please provide a transcript if available."),
|
|
|
|
| 669 |
|
| 670 |
for pattern, response in media_patterns:
|
| 671 |
if re.search(pattern, question.lower()):
|
| 672 |
+
# 检查这是否是直接访问内容的请求
|
| 673 |
if "file" in question.lower() and not self._file_exists_in_question(question):
|
| 674 |
return None, True, response
|
| 675 |
|
| 676 |
+
# 文件处理
|
| 677 |
file_patterns = [
|
| 678 |
(r'\bexcel file\b|\bxlsx\b|\bspreadsheet\b', "Unable to access the Excel file directly. Please provide the data in another format."),
|
| 679 |
(r'\bpdf file\b|\bpdf document\b', "Unable to access the PDF file directly. Please provide the data in another format."),
|
|
|
|
| 685 |
if "file" in question.lower() and not self._file_exists_in_question(question):
|
| 686 |
return None, True, response
|
| 687 |
|
| 688 |
+
# 国际象棋位置处理
|
| 689 |
if re.search(r'\bchess position\b', question.lower()) and re.search(r'\bimage\b', question.lower()):
|
| 690 |
return None, True, "Unable to analyze the chess position without a description or tool support."
|
| 691 |
|
|
|
|
| 693 |
|
| 694 |
def _file_exists_in_question(self, question: str) -> bool:
|
| 695 |
"""Check if a file mentioned in the question actually exists"""
|
| 696 |
+
# 从问题中提取潜在的文件名
|
| 697 |
file_patterns = [
|
| 698 |
r'file[:\s]+([^\s,\.]+\.[a-zA-Z0-9]+)',
|
| 699 |
r'([^\s,\.]+\.(xlsx|xls|csv|pdf|txt|jpg|png|mp3|wav))'
|
|
|
|
| 710 |
|
| 711 |
def _format_answer(self, answer) -> str:
|
| 712 |
"""Format the answer according to GAIA requirements"""
|
| 713 |
+
# 将非字符串答案转换为字符串
|
| 714 |
if answer is None:
|
| 715 |
return ""
|
| 716 |
if not isinstance(answer, str):
|
| 717 |
answer = str(answer)
|
| 718 |
|
| 719 |
+
# 清理答案 - 移除任何推理过程
|
| 720 |
answer = answer.strip()
|
| 721 |
|
| 722 |
+
# 移除常见解释性短语
|
| 723 |
explanatory_phrases = [
|
| 724 |
"the answer is",
|
| 725 |
"the result is",
|
|
|
|
| 733 |
for phrase in explanatory_phrases:
|
| 734 |
if answer.lower().startswith(phrase):
|
| 735 |
answer = answer[len(phrase):].strip()
|
| 736 |
+
# 移除任何前导标点符号
|
| 737 |
answer = answer.lstrip(',:;. ')
|
| 738 |
|
| 739 |
+
# 如果有"Answer:"或类似行,只提取该部分
|
| 740 |
result_patterns = [
|
| 741 |
r'(?i)Answer:\s*(.*?)(?:\n|$)',
|
| 742 |
r'(?i)Result:\s*(.*?)(?:\n|$)',
|
|
|
|
| 756 |
print(f"Agent received question (first 50 chars): {question[:50]}...")
|
| 757 |
|
| 758 |
try:
|
| 759 |
+
# 应用预处理处理特殊情况
|
| 760 |
processed_question, is_special_case, direct_answer = self.preprocess_question(question)
|
| 761 |
|
| 762 |
+
# 如果预处理确定了直接答案,返回它
|
| 763 |
if is_special_case and direct_answer:
|
| 764 |
print(f"Using direct answer for special case: {direct_answer}")
|
| 765 |
return direct_answer
|
| 766 |
|
| 767 |
+
# 如果检测到倒序文本,使用处理后的问题
|
| 768 |
if processed_question and processed_question != question:
|
| 769 |
question = processed_question
|
| 770 |
|
| 771 |
+
# 运行agent获取答案
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 772 |
max_retries = 2
|
| 773 |
for retry in range(max_retries + 1):
|
| 774 |
try:
|
| 775 |
if retry > 0:
|
| 776 |
print(f"Retry {retry}/{max_retries} for question")
|
| 777 |
|
| 778 |
+
# 运行agent获取答案
|
| 779 |
answer = self.agent.run(question)
|
| 780 |
|
| 781 |
+
# 按照GAIA要求格式化答案
|
| 782 |
formatted_answer = self._format_answer(answer)
|
| 783 |
|
| 784 |
+
# 对于非常短的答案,再次尝试以确保正确性
|
| 785 |
if formatted_answer and len(formatted_answer) < 2:
|
| 786 |
print("Answer is very short, trying again for verification")
|
| 787 |
verification_answer = self.agent.run(question)
|
| 788 |
verification_formatted = self._format_answer(verification_answer)
|
| 789 |
|
| 790 |
+
# 如果两个答���都很短,选择较长的那个
|
| 791 |
if len(verification_formatted) > len(formatted_answer):
|
| 792 |
formatted_answer = verification_formatted
|
| 793 |
|
|
|
|
| 798 |
print(f"Error on attempt {retry+1}: {e}")
|
| 799 |
if retry == max_retries:
|
| 800 |
raise
|
| 801 |
+
time.sleep(1) # 重试前小延迟
|
| 802 |
|
| 803 |
except Exception as e:
|
| 804 |
print(traceback.format_exc())
|
| 805 |
error_msg = f"Error running agent: {str(e)}"
|
| 806 |
print(error_msg)
|
| 807 |
|
| 808 |
+
# 特定错误情况的回退机制
|
| 809 |
if ".rewsna eht sa " in question:
|
| 810 |
return "right"
|
| 811 |
|
|
|
|
| 1043 |
print("-"*(60 + len(" App Starting ")) + "\n")
|
| 1044 |
|
| 1045 |
print("Launching Gradio Interface for Advanced Agent Evaluation...")
|
| 1046 |
+
demo.launch(debug=True, share=True)
|