Spaces:
Sleeping
Sleeping
changes in tools
Browse files- __pycache__/app.cpython-311.pyc +0 -0
- __pycache__/tools.cpython-311.pyc +0 -0
- app.py +39 -58
- requirements.txt +8 -1
- test_agent.py +38 -0
- tools.py +113 -1
__pycache__/app.cpython-311.pyc
ADDED
|
Binary file (22.2 kB). View file
|
|
|
__pycache__/tools.cpython-311.pyc
CHANGED
|
Binary files a/__pycache__/tools.cpython-311.pyc and b/__pycache__/tools.cpython-311.pyc differ
|
|
|
app.py
CHANGED
|
@@ -10,16 +10,24 @@ from langgraph.prebuilt import ToolNode, tools_condition
|
|
| 10 |
from langgraph.graph.message import add_messages
|
| 11 |
from typing import TypedDict, Annotated
|
| 12 |
from tools import (
|
| 13 |
-
image_recognition_tool,
|
| 14 |
-
download_file,
|
| 15 |
-
reverse_text_tool,
|
| 16 |
serp_search_tool,
|
| 17 |
python_execution_tool,
|
| 18 |
-
|
| 19 |
audio_processing_tool,
|
|
|
|
|
|
|
| 20 |
file_type_detection_tool,
|
| 21 |
read_file_tool,
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
)
|
| 24 |
import re
|
| 25 |
|
|
@@ -28,18 +36,25 @@ import re
|
|
| 28 |
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
| 29 |
|
| 30 |
# Setting up the llm
|
| 31 |
-
llm = ChatOpenAI(model="gpt-
|
| 32 |
tools = [
|
| 33 |
serp_search_tool,
|
| 34 |
wiki_search_tool,
|
| 35 |
-
download_file,
|
| 36 |
-
image_recognition_tool,
|
| 37 |
-
reverse_text_tool,
|
| 38 |
python_execution_tool,
|
| 39 |
-
|
| 40 |
audio_processing_tool,
|
|
|
|
|
|
|
| 41 |
file_type_detection_tool,
|
| 42 |
-
read_file_tool
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
]
|
| 44 |
chat_with_tools = llm.bind_tools(tools)
|
| 45 |
|
|
@@ -150,53 +165,11 @@ class AgentWrapper:
|
|
| 150 |
def assistant(state: MyAgent):
|
| 151 |
# Add system message to instruct the agent to use the tool
|
| 152 |
system_message = SystemMessage(content="""
|
| 153 |
-
You are a
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
If
|
| 157 |
-
|
| 158 |
-
If the answer is a list, output only a comma-separated list.
|
| 159 |
-
Do not use any prefixes, suffixes, or extra words.
|
| 160 |
-
|
| 161 |
-
If you're asked for a number, don't use commas or units like $ or %, unless specified.
|
| 162 |
-
If you're asked for a string, don't use articles or abbreviations (e.g. for cities), and write digits in plain text unless told otherwise.
|
| 163 |
-
|
| 164 |
-
IMPORTANT: You have a maximum of 3 tool uses per question. After 3 tool uses, you MUST provide your best answer based on available information.
|
| 165 |
-
|
| 166 |
-
DECISION MAKING:
|
| 167 |
-
1. First, try to answer from your knowledge if it's a general fact.
|
| 168 |
-
2. If you need specific, current, or detailed information, use serp_search_tool ONCE.
|
| 169 |
-
3. If the question looks reversed (starts with a period), use reverse_text_tool ONCE first.
|
| 170 |
-
4. For factual or historical questions, use wiki_search_tool ONCE.
|
| 171 |
-
5. For file-based questions, use the appropriate file tool.
|
| 172 |
-
6. After using a tool, analyze the result and provide your final answer.
|
| 173 |
-
7. Do NOT cycle between tools unnecessarily.
|
| 174 |
-
|
| 175 |
-
Tool Use Guidelines:
|
| 176 |
-
1. Do **not** use any tools outside of the provided tools list.
|
| 177 |
-
2. Always use **only one tool at a time** in each step of your execution.
|
| 178 |
-
3. You have a MAXIMUM of 3 tool uses per question.
|
| 179 |
-
4. For web searches and current information, use **serp_search_tool** (15s timeout).
|
| 180 |
-
5. For factual or historical questions, use **wiki_search_tool**.
|
| 181 |
-
6. If the question looks reversed (starts with a period or reads backward), first use **reverse_text_tool** to reverse it, then process the question.
|
| 182 |
-
7. For image analysis and description, use **image_recognition_tool** (requires OpenAI API key).
|
| 183 |
-
8. For Python code execution, use **python_execution_tool**.
|
| 184 |
-
9. For video analysis, use **video_analysis_tool**.
|
| 185 |
-
10. For audio processing, use **audio_processing_tool**.
|
| 186 |
-
11. For file type detection, use **file_type_detection_tool**.
|
| 187 |
-
12. For reading file contents, use **read_file_tool**.
|
| 188 |
-
13. File downloading is handled automatically - you don't need to download files manually.
|
| 189 |
-
14. Keep responses concise and efficient.
|
| 190 |
-
15. If you can't find the answer after using 2-3 tools, provide your best estimate based on available information.
|
| 191 |
-
16. NEVER use more than 3 tools for a single question.
|
| 192 |
-
17. After using a tool, provide your final answer immediately.
|
| 193 |
-
|
| 194 |
-
FILE PROCESSING:
|
| 195 |
-
- Questions may come with attached files (mp3, excel, images, etc.)
|
| 196 |
-
- File processing is automatically handled before the question reaches you
|
| 197 |
-
- If a file is attached, you'll see the file content/analysis in the question
|
| 198 |
-
- Focus on answering based on the enhanced question that includes file information
|
| 199 |
-
- You don't need to process files manually - just use the information provided
|
| 200 |
""")
|
| 201 |
|
| 202 |
# Combine system message with user messages
|
|
@@ -410,3 +383,11 @@ if __name__ == "__main__":
|
|
| 410 |
|
| 411 |
print("Launching Gradio Interface for Basic Agent Evaluation...")
|
| 412 |
demo.launch(debug=True, share=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
from langgraph.graph.message import add_messages
|
| 11 |
from typing import TypedDict, Annotated
|
| 12 |
from tools import (
|
|
|
|
|
|
|
|
|
|
| 13 |
serp_search_tool,
|
| 14 |
python_execution_tool,
|
| 15 |
+
reverse_text_tool,
|
| 16 |
audio_processing_tool,
|
| 17 |
+
video_analysis_tool,
|
| 18 |
+
image_recognition_tool,
|
| 19 |
file_type_detection_tool,
|
| 20 |
read_file_tool,
|
| 21 |
+
code_execution_tool,
|
| 22 |
+
math_calculation_tool,
|
| 23 |
+
wiki_search_tool,
|
| 24 |
+
python_repl_tool,
|
| 25 |
+
save_and_read_file_tool,
|
| 26 |
+
download_file_from_url_tool,
|
| 27 |
+
extract_text_from_image_tool,
|
| 28 |
+
analyze_csv_file_tool,
|
| 29 |
+
analyze_excel_file_tool,
|
| 30 |
+
download_file,
|
| 31 |
)
|
| 32 |
import re
|
| 33 |
|
|
|
|
| 36 |
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
|
| 37 |
|
| 38 |
# Setting up the llm
|
| 39 |
+
llm = ChatOpenAI(model="gpt-4o", temperature=0)
|
| 40 |
tools = [
|
| 41 |
serp_search_tool,
|
| 42 |
wiki_search_tool,
|
|
|
|
|
|
|
|
|
|
| 43 |
python_execution_tool,
|
| 44 |
+
reverse_text_tool,
|
| 45 |
audio_processing_tool,
|
| 46 |
+
video_analysis_tool,
|
| 47 |
+
image_recognition_tool,
|
| 48 |
file_type_detection_tool,
|
| 49 |
+
read_file_tool,
|
| 50 |
+
code_execution_tool,
|
| 51 |
+
math_calculation_tool,
|
| 52 |
+
python_repl_tool,
|
| 53 |
+
save_and_read_file_tool,
|
| 54 |
+
download_file_from_url_tool,
|
| 55 |
+
extract_text_from_image_tool,
|
| 56 |
+
analyze_csv_file_tool,
|
| 57 |
+
analyze_excel_file_tool,
|
| 58 |
]
|
| 59 |
chat_with_tools = llm.bind_tools(tools)
|
| 60 |
|
|
|
|
| 165 |
def assistant(state: MyAgent):
|
| 166 |
# Add system message to instruct the agent to use the tool
|
| 167 |
system_message = SystemMessage(content="""
|
| 168 |
+
You are a helpful assistant tasked with answering questions using a set of tools.
|
| 169 |
+
Now, I will ask you a question. Report your thoughts, and finish your answer with the following template:
|
| 170 |
+
FINAL ANSWER: [YOUR FINAL ANSWER].
|
| 171 |
+
YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, Apply the rules above for each element (number or string), ensure there is exactly one space after each comma.
|
| 172 |
+
Your answer should only start with "FINAL ANSWER: ", then follows with the answer.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
""")
|
| 174 |
|
| 175 |
# Combine system message with user messages
|
|
|
|
| 383 |
|
| 384 |
print("Launching Gradio Interface for Basic Agent Evaluation...")
|
| 385 |
demo.launch(debug=True, share=False)
|
| 386 |
+
|
| 387 |
+
|
| 388 |
+
# test
|
| 389 |
+
messages = [HumanMessage(
|
| 390 |
+
content="Question: How many studio albums were published by Mercedes Sosa between 2000 and 2009 (included)? You can use the latest 2022 version of english wikipedia.")]
|
| 391 |
+
response = my_agent.invoke({"messages": messages})
|
| 392 |
+
print("🎩 Alfred's Response:")
|
| 393 |
+
print(response['messages'][-1].content)
|
requirements.txt
CHANGED
|
@@ -17,4 +17,11 @@ langchain-huggingface
|
|
| 17 |
pydub
|
| 18 |
google-search-results
|
| 19 |
pytesseract
|
| 20 |
-
numpy
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
pydub
|
| 18 |
google-search-results
|
| 19 |
pytesseract
|
| 20 |
+
numpy
|
| 21 |
+
wikipedia
|
| 22 |
+
langchain_experimental
|
| 23 |
+
uuid
|
| 24 |
+
openpyxl
|
| 25 |
+
xlrd
|
| 26 |
+
ffmpeg-python
|
| 27 |
+
opencv-python
|
test_agent.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import requests
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def fetch_questions():
|
| 6 |
+
api_url = os.getenv("DEFAULT_API_URL",
|
| 7 |
+
"https://agents-course-unit4-scoring.hf.space")
|
| 8 |
+
questions_url = f"{api_url}/questions"
|
| 9 |
+
print(f"Fetching questions from: {questions_url}")
|
| 10 |
+
try:
|
| 11 |
+
response = requests.get(questions_url, timeout=15)
|
| 12 |
+
response.raise_for_status()
|
| 13 |
+
questions_data = response.json()
|
| 14 |
+
if not questions_data:
|
| 15 |
+
print("Fetched questions list is empty.")
|
| 16 |
+
return []
|
| 17 |
+
print(f"Fetched {len(questions_data)} questions.")
|
| 18 |
+
return questions_data
|
| 19 |
+
except Exception as e:
|
| 20 |
+
print(f"Error fetching questions: {e}")
|
| 21 |
+
return []
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def main():
|
| 25 |
+
questions = fetch_questions()
|
| 26 |
+
if not questions:
|
| 27 |
+
print("No questions to display.")
|
| 28 |
+
return
|
| 29 |
+
print("\nFirst 20 questions from the API:")
|
| 30 |
+
for idx, q in enumerate(questions[:20], 1):
|
| 31 |
+
print(f"\n[{idx}] Task ID: {q.get('task_id')}")
|
| 32 |
+
print(f"Question: {q.get('question')}")
|
| 33 |
+
if q.get('file_name'):
|
| 34 |
+
print(f"Attached file: {q['file_name']}")
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
if __name__ == "__main__":
|
| 38 |
+
main()
|
tools.py
CHANGED
|
@@ -21,7 +21,10 @@ from pydub import AudioSegment
|
|
| 21 |
import pandas as pd
|
| 22 |
from PIL import Image
|
| 23 |
from langchain_community.document_loaders import WikipediaLoader
|
| 24 |
-
|
|
|
|
|
|
|
|
|
|
| 25 |
# Load environment variables
|
| 26 |
print("Current working directory:", os.getcwd())
|
| 27 |
|
|
@@ -546,3 +549,112 @@ wiki_search_tool = Tool(
|
|
| 546 |
func=wiki_search,
|
| 547 |
description="Search Wikipedia for a query and return up to 2 results. Use this for factual or historical questions."
|
| 548 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
import pandas as pd
|
| 22 |
from PIL import Image
|
| 23 |
from langchain_community.document_loaders import WikipediaLoader
|
| 24 |
+
from langchain_experimental.tools.python.tool import PythonREPLTool
|
| 25 |
+
import uuid
|
| 26 |
+
import pytesseract
|
| 27 |
+
from urllib.parse import urlparse
|
| 28 |
# Load environment variables
|
| 29 |
print("Current working directory:", os.getcwd())
|
| 30 |
|
|
|
|
| 549 |
func=wiki_search,
|
| 550 |
description="Search Wikipedia for a query and return up to 2 results. Use this for factual or historical questions."
|
| 551 |
)
|
| 552 |
+
|
| 553 |
+
python_tool = PythonREPLTool()
|
| 554 |
+
|
| 555 |
+
python_repl_tool = Tool(
|
| 556 |
+
name="python_repl_tool",
|
| 557 |
+
func=python_tool,
|
| 558 |
+
description="Executes Python code in a REPL environment. Use this for running Python code snippets interactively."
|
| 559 |
+
)
|
| 560 |
+
|
| 561 |
+
# --- New Tools ---
|
| 562 |
+
|
| 563 |
+
|
| 564 |
+
def save_and_read_file(content: str, filename: str = None) -> str:
|
| 565 |
+
temp_dir = tempfile.gettempdir()
|
| 566 |
+
if filename is None:
|
| 567 |
+
temp_file = tempfile.NamedTemporaryFile(delete=False, dir=temp_dir)
|
| 568 |
+
filepath = temp_file.name
|
| 569 |
+
else:
|
| 570 |
+
filepath = os.path.join(temp_dir, filename)
|
| 571 |
+
with open(filepath, "w") as f:
|
| 572 |
+
f.write(content)
|
| 573 |
+
return f"File saved to {filepath}. You can read this file to process its contents."
|
| 574 |
+
|
| 575 |
+
|
| 576 |
+
save_and_read_file_tool = Tool(
|
| 577 |
+
name="save_and_read_file_tool",
|
| 578 |
+
func=save_and_read_file,
|
| 579 |
+
description="Save content to a file and return the path. Optionally specify a filename."
|
| 580 |
+
)
|
| 581 |
+
|
| 582 |
+
|
| 583 |
+
def download_file_from_url(url: str, filename: str = None) -> str:
|
| 584 |
+
try:
|
| 585 |
+
if not filename:
|
| 586 |
+
path = urlparse(url).path
|
| 587 |
+
filename = os.path.basename(path)
|
| 588 |
+
if not filename:
|
| 589 |
+
filename = f"downloaded_{uuid.uuid4().hex[:8]}"
|
| 590 |
+
temp_dir = tempfile.gettempdir()
|
| 591 |
+
filepath = os.path.join(temp_dir, filename)
|
| 592 |
+
response = requests.get(url, stream=True)
|
| 593 |
+
response.raise_for_status()
|
| 594 |
+
with open(filepath, "wb") as f:
|
| 595 |
+
for chunk in response.iter_content(chunk_size=8192):
|
| 596 |
+
f.write(chunk)
|
| 597 |
+
return f"File downloaded to {filepath}. You can read this file to process its contents."
|
| 598 |
+
except Exception as e:
|
| 599 |
+
return f"Error downloading file: {str(e)}"
|
| 600 |
+
|
| 601 |
+
|
| 602 |
+
download_file_from_url_tool = Tool(
|
| 603 |
+
name="download_file_from_url_tool",
|
| 604 |
+
func=download_file_from_url,
|
| 605 |
+
description="Download a file from a URL and save it to a temporary location. Optionally specify a filename."
|
| 606 |
+
)
|
| 607 |
+
|
| 608 |
+
|
| 609 |
+
def extract_text_from_image(image_path: str) -> str:
|
| 610 |
+
try:
|
| 611 |
+
image = Image.open(image_path)
|
| 612 |
+
text = pytesseract.image_to_string(image)
|
| 613 |
+
return f"Extracted text from image:\n\n{text}"
|
| 614 |
+
except Exception as e:
|
| 615 |
+
return f"Error extracting text from image: {str(e)}"
|
| 616 |
+
|
| 617 |
+
|
| 618 |
+
extract_text_from_image_tool = Tool(
|
| 619 |
+
name="extract_text_from_image_tool",
|
| 620 |
+
func=extract_text_from_image,
|
| 621 |
+
description="Extract text from an image using OCR (pytesseract)."
|
| 622 |
+
)
|
| 623 |
+
|
| 624 |
+
|
| 625 |
+
def analyze_csv_file(file_path: str, query: str) -> str:
|
| 626 |
+
try:
|
| 627 |
+
df = pd.read_csv(file_path)
|
| 628 |
+
result = f"CSV file loaded with {len(df)} rows and {len(df.columns)} columns.\n"
|
| 629 |
+
result += f"Columns: {', '.join(df.columns)}\n\n"
|
| 630 |
+
result += "Summary statistics:\n"
|
| 631 |
+
result += str(df.describe())
|
| 632 |
+
return result
|
| 633 |
+
except Exception as e:
|
| 634 |
+
return f"Error analyzing CSV file: {str(e)}"
|
| 635 |
+
|
| 636 |
+
|
| 637 |
+
analyze_csv_file_tool = Tool(
|
| 638 |
+
name="analyze_csv_file_tool",
|
| 639 |
+
func=analyze_csv_file,
|
| 640 |
+
description="Analyze a CSV file using pandas and answer a question about it."
|
| 641 |
+
)
|
| 642 |
+
|
| 643 |
+
|
| 644 |
+
def analyze_excel_file(file_path: str, query: str) -> str:
|
| 645 |
+
try:
|
| 646 |
+
df = pd.read_excel(file_path)
|
| 647 |
+
result = f"Excel file loaded with {len(df)} rows and {len(df.columns)} columns.\n"
|
| 648 |
+
result += f"Columns: {', '.join(df.columns)}\n\n"
|
| 649 |
+
result += "Summary statistics:\n"
|
| 650 |
+
result += str(df.describe())
|
| 651 |
+
return result
|
| 652 |
+
except Exception as e:
|
| 653 |
+
return f"Error analyzing Excel file: {str(e)}"
|
| 654 |
+
|
| 655 |
+
|
| 656 |
+
analyze_excel_file_tool = Tool(
|
| 657 |
+
name="analyze_excel_file_tool",
|
| 658 |
+
func=analyze_excel_file,
|
| 659 |
+
description="Analyze an Excel file using pandas and answer a question about it."
|
| 660 |
+
)
|