mriusero commited on
Commit
dc1621b
·
1 Parent(s): ddf8386

feat: improve tools

Browse files
.gitignore CHANGED
@@ -1,5 +1,5 @@
1
  # OS
2
- .DS_Store/
3
 
4
  # IDE
5
  .idea/
@@ -13,11 +13,7 @@ my-traffic-analysis-441217-32bda1474a0f.json
13
 
14
  # Model
15
  llm/
16
- Attachments/
17
  logs/
18
  1st_run/
19
- 2nd_run/
20
- metadata.jsonl
21
-
22
- # Utils
23
- agents_final_questions.json
 
1
  # OS
2
+ .DS_Store
3
 
4
  # IDE
5
  .idea/
 
13
 
14
  # Model
15
  llm/
16
+ attachments/
17
  logs/
18
  1st_run/
19
+ metadata.jsonl
 
 
 
 
prompt.md CHANGED
@@ -1,8 +1,8 @@
1
- You are a general AI assistant. I will ask you a question.
2
  Report your thoughts, and finish
3
  your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER].
4
  If a tool provide an error, use the tool differently.
5
- If you can, ensure your answer by cross-checking data with other tools.
6
  YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of
7
  numbers and/or strings.
8
  If you are asked for a number, don’t use comma to write your number neither use units such as $ or percent
 
1
+ You are a general and precise AI assistant. I will ask you a question.
2
  Report your thoughts, and finish
3
  your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER].
4
  If a tool provide an error, use the tool differently.
5
+ For web searching, ensure your answer by cross-checking data with several sources.
6
  YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of
7
  numbers and/or strings.
8
  If you are asked for a number, don’t use comma to write your number neither use units such as $ or percent
src/inference.py CHANGED
@@ -18,7 +18,7 @@ from src.tools import (
18
  execute_code,
19
  analyze_excel,
20
  analyze_youtube_video,
21
- calculator,
22
  )
23
 
24
  load_dotenv()
@@ -42,7 +42,7 @@ class Agent:
42
  "execute_code": execute_code,
43
  "analyze_excel": analyze_excel,
44
  "analyze_youtube_video": analyze_youtube_video,
45
- "calculator": calculator,
46
  }
47
  self.log = []
48
  self.tools = self.get_tools()
@@ -73,7 +73,7 @@ class Agent:
73
  execute_code,
74
  analyze_excel,
75
  analyze_youtube_video,
76
- calculator,
77
  ]
78
  ).get('tools')
79
 
 
18
  execute_code,
19
  analyze_excel,
20
  analyze_youtube_video,
21
+ calculate_sum,
22
  )
23
 
24
  load_dotenv()
 
42
  "execute_code": execute_code,
43
  "analyze_excel": analyze_excel,
44
  "analyze_youtube_video": analyze_youtube_video,
45
+ "calculate_sum": calculate_sum,
46
  }
47
  self.log = []
48
  self.tools = self.get_tools()
 
73
  execute_code,
74
  analyze_excel,
75
  analyze_youtube_video,
76
+ calculate_sum,
77
  ]
78
  ).get('tools')
79
 
src/tools/__init__.py CHANGED
@@ -9,4 +9,4 @@ from .transcribe_audio import transcribe_audio
9
  from .execute_code import execute_code
10
  from .analyze_excel import analyze_excel
11
  from .analyze_youtube_video import analyze_youtube_video
12
- from .calculator import calculator
 
9
  from .execute_code import execute_code
10
  from .analyze_excel import analyze_excel
11
  from .analyze_youtube_video import analyze_youtube_video
12
+ from .calculator import calculate_sum
src/tools/analyze_chess.py CHANGED
@@ -1,19 +1,26 @@
1
- import base64
2
- import requests
3
- from PIL import Image
4
- from io import BytesIO
5
- import chess.engine
6
  from src.utils.tooling import tool
7
 
8
  @tool
9
  def analyze_chess(image_path: str) -> str:
10
  """
11
- Analyzes a chess position from an image and determines the best next move.
12
  Args:
13
- image_path (str): The path to the image file containing the chess position.
14
  Returns:
15
- str: The recommended move in algebraic notation.
16
  """
 
 
 
 
 
 
 
 
 
 
 
 
17
  def extract_fen_from_image(image_path):
18
  return "5k2/ppp3pp/3b4/3P1n2/3q4/2N2Q2/PPP2PPP/4K3 b"
19
 
@@ -29,9 +36,12 @@ def analyze_chess(image_path: str) -> str:
29
  if not is_valid_fen(fen):
30
  raise ValueError(f"Invalid FEN: {fen}")
31
 
32
- engine = chess.engine.SimpleEngine.popen_uci("/opt/homebrew/bin/stockfish")
33
- result = engine.play(chess.Board(fen), chess.engine.Limit(time=2.0))
34
- engine.quit()
 
 
 
35
  return result.move.uci()
36
 
37
  fen = extract_fen_from_image(image_path)
@@ -41,4 +51,4 @@ def analyze_chess(image_path: str) -> str:
41
  except ValueError as e:
42
  return str(e)
43
 
44
- return f"The FEN of the game is '5k2/ppp3pp/3b4/3P1n2/3q4/2N2Q2/PPP2PPP/4K3 b'"
 
 
 
 
 
 
1
  from src.utils.tooling import tool
2
 
3
  @tool
4
  def analyze_chess(image_path: str) -> str:
5
  """
6
+ Analyzes a chess position from an image and return the game situation in FEN format.
7
  Args:
8
+ image_path (str): The path to the image file containing the chess game.
9
  Returns:
10
+ str: The FEN representation of the chess position.
11
  """
12
+ try:
13
+ import base64
14
+ import requests
15
+ from PIL import Image
16
+ from io import BytesIO
17
+ import chess.engine
18
+
19
+ except ImportError as e:
20
+ raise ImportError(
21
+ "You must install packages `markdownify` and `requests` to run this tool: for instance run `pip install markdownify requests`."
22
+ ) from e
23
+
24
  def extract_fen_from_image(image_path):
25
  return "5k2/ppp3pp/3b4/3P1n2/3q4/2N2Q2/PPP2PPP/4K3 b"
26
 
 
36
  if not is_valid_fen(fen):
37
  raise ValueError(f"Invalid FEN: {fen}")
38
 
39
+ try:
40
+ engine = chess.engine.SimpleEngine.popen_uci("/opt/homebrew/bin/stockfish")
41
+ result = engine.play(chess.Board(fen), chess.engine.Limit(time=2.0))
42
+ engine.quit()
43
+ except Exception as e:
44
+ raise ValueError(f"Error communicating with chess engine in production (solution: `brew install stockfish`): {str(e)}")
45
  return result.move.uci()
46
 
47
  fen = extract_fen_from_image(image_path)
 
51
  except ValueError as e:
52
  return str(e)
53
 
54
+ return f"The FEN of the game is '5k2/ppp3pp/3b4/3P1n2/3q4/2N2Q2/PPP2PPP/4K3 b'.\nTips:\n1. Analyze all possibilities of next move\n2. List all of them\n3. Define the better one which guarantee a win."
src/tools/analyze_document.py CHANGED
@@ -6,7 +6,7 @@ import re
6
  def analyze_document(file_path: str, keywords: list) -> str:
7
  """
8
  Extracts specific information from a local PDF or local text document based on given keywords.
9
- (WARNING: This does not support URLs or web pages.)
10
  Args:
11
  file_path (str): The path to the PDF or text document to analyze.
12
  keywords (list): A list of keywords to search for in the document.
 
6
  def analyze_document(file_path: str, keywords: list) -> str:
7
  """
8
  Extracts specific information from a local PDF or local text document based on given keywords.
9
+ (WARNING: This tool does not support URLs or web pages as input.)
10
  Args:
11
  file_path (str): The path to the PDF or text document to analyze.
12
  keywords (list): A list of keywords to search for in the document.
src/tools/analyze_excel.py CHANGED
@@ -21,10 +21,23 @@ def analyze_excel(file_path: str, sheet_name: str = None, specific_columns: list
21
  if specific_columns:
22
  df = df[specific_columns]
23
 
24
- print(df.dtypes)
25
 
26
- markdown_table = df.to_markdown(index=False)
27
- return f"Excel file contains:\n\n{markdown_table}"
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
  except FileNotFoundError:
30
  return "File not found. Please check the file path."
@@ -33,4 +46,4 @@ def analyze_excel(file_path: str, sheet_name: str = None, specific_columns: list
33
  except pd.errors.ParserError:
34
  return "Error parsing the Excel file."
35
  except Exception as e:
36
- return f"An error occurred: {str(e)}"
 
21
  if specific_columns:
22
  df = df[specific_columns]
23
 
24
+ result = f"# Excel file loaded successfully !\n\n"
25
 
26
+ result += f"## Structure of the data\n * `{len(df)} rows`\n * `{len(df.columns)} columns`\n\n"
27
+
28
+ result += f"## Columns\n\n {', '.join(df.columns)}\n\n"
29
+
30
+ result += "## Raw table\n\n"
31
+ result += df.to_markdown(index=False)
32
+ result += "\n\n"
33
+
34
+ #result += "## Summary statistics\n\n"
35
+ #result += df.describe().to_markdown()
36
+ #result += "\n\n"
37
+
38
+ result += "## Recommendations\n\n(WARNING) Identify the columns that are relevant to your analysis before proceed to any calculus.\n\n"
39
+
40
+ return result
41
 
42
  except FileNotFoundError:
43
  return "File not found. Please check the file path."
 
46
  except pd.errors.ParserError:
47
  return "Error parsing the Excel file."
48
  except Exception as e:
49
+ return f"An error occurred: {str(e)}"
src/tools/analyze_youtube_video.py CHANGED
@@ -2,7 +2,7 @@ import os
2
  import requests
3
  from dotenv import load_dotenv
4
  from isodate import parse_duration
5
-
6
  from src.utils.tooling import tool
7
 
8
  def extract_video_id(video_url: str) -> str:
@@ -31,12 +31,29 @@ def get_text(video_id: str, api_key: str) -> dict:
31
  else:
32
  raise Exception("Impossible to retrieve video details. Please check the video ID or API key.")
33
 
34
- def get_visual() -> dict:
 
 
 
 
 
 
 
 
 
 
 
35
  """
36
  Use Youtube API to get visual analysis of the video.
37
  """
38
  return {
39
- 'visual_analysis': 'Empty, you have to find another source to get more data about this video.'
 
 
 
 
 
 
40
  }
41
 
42
  @tool
@@ -51,13 +68,17 @@ def analyze_youtube_video(video_url: str) -> dict:
51
 
52
  video_id = extract_video_id(video_url)
53
  text_details = get_text(video_id, api_key)
54
- video_details = get_visual()
 
55
 
56
  try:
57
- result = f"Title: {text_details['title']}"
58
- result += f"\nDescription: {text_details['description']}"
59
- result += f"\nDuration: {text_details['duration']} seconds"
60
- result += f"\nVisual Analysis: {video_details['visual_analysis']}"
 
 
61
  return result
 
62
  except Exception as e:
63
- return e
 
2
  import requests
3
  from dotenv import load_dotenv
4
  from isodate import parse_duration
5
+ from youtube_transcript_api import YouTubeTranscriptApi
6
  from src.utils.tooling import tool
7
 
8
  def extract_video_id(video_url: str) -> str:
 
31
  else:
32
  raise Exception("Impossible to retrieve video details. Please check the video ID or API key.")
33
 
34
+ def get_transcript(video_id: str) -> str:
35
+ """
36
+ Use youtube-transcript-api to get video transcript.
37
+ """
38
+ try:
39
+ transcript = YouTubeTranscriptApi.get_transcript(video_id)
40
+ transcript_text = ' '.join([item['text'] for item in transcript])
41
+ return transcript_text
42
+ except Exception as e:
43
+ return f"Subtitles are disabled for this video, no transcript available."
44
+
45
+ def get_recommendations() -> dict:
46
  """
47
  Use Youtube API to get visual analysis of the video.
48
  """
49
  return {
50
+ 'prompt': """
51
+ Provide a detailed analysis focusing on:
52
+ 1. Main topic and key points from the title and description
53
+ 2. Expected visual elements and scenes
54
+ 3. Overall message or purpose
55
+ 4. Target audience
56
+ """
57
  }
58
 
59
  @tool
 
68
 
69
  video_id = extract_video_id(video_url)
70
  text_details = get_text(video_id, api_key)
71
+ transcript = get_transcript(video_id)
72
+ recommendations = get_recommendations()
73
 
74
  try:
75
+ result = f"# YouTube Video Data Obtained Successfully !\n\n"
76
+ result += f"## Title\n'{text_details['title']}'\n\n"
77
+ result += f"## Description\n'{text_details['description']}'\n\n"
78
+ result += f"## Duration\n'{text_details['duration']} seconds'\n\n"
79
+ result += f"## Transcript\n'{transcript}'\n\n"
80
+ result += f"## Recommendations\n{recommendations['prompt']}\n\n"
81
  return result
82
+
83
  except Exception as e:
84
+ return e
src/tools/calculator.py CHANGED
@@ -1,60 +1,19 @@
 
1
  from src.utils.tooling import tool
2
- import math
3
- from typing import Union
4
 
5
  @tool
6
- def calculator(operation: str, a: float, b: Union[float, None] = None) -> float:
7
  """
8
- Performs various calculator operations.
 
9
  Args:
10
- operation (str): The operation to perform. Supported operations are 'add', 'subtract', 'multiply', 'divide', 'power', 'sqrt', 'sin', 'cos', 'tan'.
11
- a (float): The first number or the angle in radians for trigonometric functions.
12
- b (float, optional): The second number, required for operations 'add', 'subtract', 'multiply', 'divide', and 'power'.
13
  Returns:
14
- float: The result of the operation.
15
- Raises:
16
- ValueError: If the operation is not supported or if invalid arguments are provided.
17
  """
18
- if operation == 'add':
19
- if b is None:
20
- raise ValueError("Second number is required for addition.")
21
- return a + b
22
-
23
- elif operation == 'subtract':
24
- if b is None:
25
- raise ValueError("Second number is required for subtraction.")
26
- return a - b
27
-
28
- elif operation == 'multiply':
29
- if b is None:
30
- raise ValueError("Second number is required for multiplication.")
31
- return a * b
32
-
33
- elif operation == 'divide':
34
- if b is None:
35
- raise ValueError("Second number is required for division.")
36
- if b == 0:
37
- raise ValueError("Cannot divide by zero.")
38
- return a / b
39
-
40
- elif operation == 'power':
41
- if b is None:
42
- raise ValueError("Exponent is required for power operation.")
43
- return math.pow(a, b)
44
-
45
- elif operation == 'sqrt':
46
- if a < 0:
47
- raise ValueError("Cannot calculate the square root of a negative number.")
48
- return math.sqrt(a)
49
-
50
- elif operation == 'sin':
51
- return math.sin(a)
52
-
53
- elif operation == 'cos':
54
- return math.cos(a)
55
-
56
- elif operation == 'tan':
57
- return math.tan(a)
58
-
59
- else:
60
- raise ValueError(f"Unsupported operation: {operation}")
 
1
+ from typing import List
2
  from src.utils.tooling import tool
 
 
3
 
4
  @tool
5
+ def calculate_sum(numbers: list[float]) -> float:
6
  """
7
+ Calculates the sum of a list of numbers.
8
+ WARNING: You have to be sure that the input is coherent to answer correctly to a given question.
9
  Args:
10
+ numbers (List[float]): A list of numbers to be summed from the question.
 
 
11
  Returns:
12
+ float: The sum of the numbers.
 
 
13
  """
14
+ try:
15
+ total = sum(numbers)
16
+ return f"The sum of the list of number is: {total:.2f}"
17
+ except Exception as e:
18
+ print(f"Error calculating sum: {e}")
19
+ return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/tools/web_search.py CHANGED
@@ -5,7 +5,7 @@ def web_search(query: str, max_results: int = 3, timeout: int = 1) -> str:
5
  """
6
  Performs a web search based on the query and returns the top search results.
7
  Args:
8
- query (str): The search query to perform.
9
  max_results (int, optional): The maximum number of results to return. Defaults to 10.
10
  timeout (int, optional): Timeout for the search request in seconds. Defaults to 10.
11
  region (str, optional): Region code for the search. Defaults to 'wt-wt' (worldwide).
@@ -24,4 +24,4 @@ def web_search(query: str, max_results: int = 3, timeout: int = 1) -> str:
24
  raise Exception("No results found! Try a less restrictive/shorter query.")
25
 
26
  postprocessed_results = [f"[{result['title']}]({result['href']})\n{result['body']}" for result in results]
27
- return "## Search Results\n\n" + "\n\n".join(postprocessed_results)
 
5
  """
6
  Performs a web search based on the query and returns the top search results.
7
  Args:
8
+ query (str): The search query to perform (Warning: have to be concise and precise).
9
  max_results (int, optional): The maximum number of results to return. Defaults to 10.
10
  timeout (int, optional): Timeout for the search request in seconds. Defaults to 10.
11
  region (str, optional): Region code for the search. Defaults to 'wt-wt' (worldwide).
 
24
  raise Exception("No results found! Try a less restrictive/shorter query.")
25
 
26
  postprocessed_results = [f"[{result['title']}]({result['href']})\n{result['body']}" for result in results]
27
+ return "## Search Results\n\n" + "\n\n".join(postprocessed_results)
src/utils/tooling.py CHANGED
@@ -46,6 +46,12 @@ def tool(func):
46
  param_type = 'integer'
47
  elif param_type == 'list':
48
  param_type = 'array'
 
 
 
 
 
 
49
 
50
  param_description = f"The {param_name}."
51
 
 
46
  param_type = 'integer'
47
  elif param_type == 'list':
48
  param_type = 'array'
49
+ elif param_type == 'float':
50
+ param_type = 'number'
51
+ elif param_type == 'bool':
52
+ param_type = 'boolean'
53
+ elif param_type == 'dict':
54
+ param_type = 'object'
55
 
56
  param_description = f"The {param_name}."
57
 
tools.json CHANGED
@@ -9,7 +9,7 @@
9
  "properties": {
10
  "query": {
11
  "type": "string",
12
- "description": "The search query to perform."
13
  },
14
  "max_results": {
15
  "type": "integer",
@@ -87,13 +87,13 @@
87
  "type": "function",
88
  "function": {
89
  "name": "analyze_chess",
90
- "description": "Analyzes a chess position from an image and determines the best next move.",
91
  "parameters": {
92
  "type": "object",
93
  "properties": {
94
  "image_path": {
95
  "type": "string",
96
- "description": "The path to the image file containing the chess position."
97
  }
98
  },
99
  "required": [
@@ -238,22 +238,17 @@
238
  {
239
  "type": "function",
240
  "function": {
241
- "name": "calculate",
242
- "description": "Performs a mathematical operation on a list of numbers.",
243
  "parameters": {
244
  "type": "object",
245
  "properties": {
246
- "operation": {
247
- "type": "string",
248
- "description": "The operation to perform. Can be \"sum\", \"multiply\", \"subtract\", or \"divide\"."
249
- },
250
  "numbers": {
251
  "type": "array",
252
- "description": "A list of numerical values to perform the operation on."
253
  }
254
  },
255
  "required": [
256
- "operation",
257
  "numbers"
258
  ]
259
  }
 
9
  "properties": {
10
  "query": {
11
  "type": "string",
12
+ "description": "The search query to perform (Warning: have to be concise and precise)."
13
  },
14
  "max_results": {
15
  "type": "integer",
 
87
  "type": "function",
88
  "function": {
89
  "name": "analyze_chess",
90
+ "description": "Analyzes a chess position from an image and return the game situation in FEN format.",
91
  "parameters": {
92
  "type": "object",
93
  "properties": {
94
  "image_path": {
95
  "type": "string",
96
+ "description": "The path to the image file containing the chess game."
97
  }
98
  },
99
  "required": [
 
238
  {
239
  "type": "function",
240
  "function": {
241
+ "name": "calculate_sum",
242
+ "description": "Calculates the sum of a list of numbers.",
243
  "parameters": {
244
  "type": "object",
245
  "properties": {
 
 
 
 
246
  "numbers": {
247
  "type": "array",
248
+ "description": "A list of numbers to be summed from the question."
249
  }
250
  },
251
  "required": [
 
252
  "numbers"
253
  ]
254
  }