File size: 6,005 Bytes
34d197c
 
 
9b27e1d
34d197c
895992e
9d098dd
 
766d2d7
34d197c
 
9d098dd
 
 
9b27e1d
 
9d098dd
766d2d7
 
 
 
 
 
9d098dd
 
cc9ee3d
895992e
 
7a87e6a
895992e
7a87e6a
 
 
 
 
895992e
 
 
 
 
 
 
 
 
 
7a87e6a
895992e
 
 
 
34d197c
895992e
766d2d7
895992e
 
766d2d7
 
 
 
9d098dd
17885ea
cc9ee3d
 
895992e
 
 
 
766d2d7
 
17885ea
 
 
 
 
 
 
af2043a
9b27e1d
17885ea
9b27e1d
 
17885ea
 
 
 
 
 
 
 
 
895992e
17885ea
895992e
 
 
17885ea
 
 
 
895992e
17885ea
 
 
 
 
9b27e1d
7376a97
cc9ee3d
 
 
 
9d098dd
7376a97
 
cc9ee3d
17885ea
7376a97
cc9ee3d
 
 
 
 
9d098dd
17885ea
7376a97
 
 
 
 
17885ea
7376a97
17885ea
 
 
7376a97
 
 
 
 
 
7a87e6a
 
 
 
cc9ee3d
 
 
7a87e6a
17885ea
 
af2043a
cc9ee3d
af2043a
895992e
7a87e6a
 
 
 
 
 
895992e
 
 
 
 
7a87e6a
895992e
766d2d7
895992e
34d197c
cc9ee3d
766d2d7
 
cc9ee3d
766d2d7
cc9ee3d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import os
import logging
import sys
import time

import markitdown
import smolagents

# Logs appear to be swallowed.
LOG = logging.getLogger(__name__)

SYSTEM_PROMPT = """
You are a general AI assistant. I will ask you a question. Report your thoughts, and finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER]. 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 above rules depending of whether the element to be put in the list is a number or a string.

The current date is April 30, 2025.

Take the time to plan the steps to reach the solution. Show the steps and then execute the steps.

The question is below:
"""

SUFFIX_PROMPT = """
Remember - The FINAL ANSWER must be a string, a number or a comma separated list that is only strings and numbers. No other output is allowed for a FINAL ANSWER! If any other output is provided other than a string, number or comma separated list that contains only strings and numbers, you fail. Don't fail.
"""


@smolagents.tool
def convert_from_url(url: str) -> str:
  """Convert data at a url into a markdown string.

   This method takes a url as input and converts the contents
   into a markdown. It can convert file formats such as
   pdf, excel, xlsx, csv, powerpoint, ppt, etc.

   It can also transcribe audio files such as mp3.

   Args:
     url: the url to access the file. If the file is on the
          local machine, the url should start with "file://"
          instead of the traditional "http://" or "https://".

   Returns:
     string that is in the markdown format.
   """
  # Don't need third-party plugins.
  md = markitdown.MarkItDown(enable_plugins=False)
  result = md.convert(url)
  return result.text_content


class BasicAgent:

  def check_results(self, final_answer, agent_memory):
    if isinstance(final_answer, str) or isinstance(
        final_answer, int) or isinstance(final_answer, float):
      return True
    failure = "FAILED! The final answer must be a string, a number or a comma separated list of strings and numbers."
    print(f"Feedback: {failure}")
    raise Exception(failure)

  def __init__(self):
    print("BasicAgent initializing.")

    # too big
    #    self.manager_model_id = "google/gemma-3-27B-it"
    #    self.manager_model_id = "OpenGVLab/InternVL3-14B"
    #    self.manager_model_id = "AIDC-AI/Ovis2-34B"

    self.manager_model_id = "meta-llama/Llama-3.3-70B-Instruct"
    self.manager_model = None

    self.code_model_id = "Qwen/Qwen2.5-Coder-32B-Instruct"
    self.code_model = None

    if not self.manager_model:
      self.manager_model = smolagents.HfApiModel(
          max_tokens=64000,
          temperature=0.3,
          model_id=self.manager_model_id,
          custom_role_conversions=None,
      )

    if not self.code_model:
      self.code_model = smolagents.HfApiModel(
          max_tokens=32000,
          temperature=0.3,
          model_id=self.code_model_id,
          custom_role_conversions=None,
      )

    print(f"NEW5: BasicAgent {self.manager_model_id=} {self.code_model_id=}")

    math_tools = [
        smolagents.FinalAnswerTool(),
    ]
    self.math_agent = smolagents.CodeAgent(
        name="date_time_math_agent",
        description="Handle date, time and math caclulations",
        model=self.code_model,
        tools=math_tools,
        max_steps=6,
        verbosity_level=2,
        planning_interval=None,
        additional_authorized_imports=["datetime", "time", "calendar"],
    )

    web_search_tools = [
        smolagents.DuckDuckGoSearchTool(),
        smolagents.VisitWebpageTool(),
        smolagents.FinalAnswerTool()
    ]

    self.web_search_agent = smolagents.CodeAgent(
        name="web_search_agent",
        description="Search the web",
        model=self.code_model,
        tools=web_search_tools,
        max_steps=6,
        verbosity_level=2,
        planning_interval=None,
        additional_authorized_imports=["duckduckgo_search"],
    )

    wikipedia_search_tools = [
        smolagents.WikipediaSearchTool(),
        smolagents.VisitWebpageTool(),
        smolagents.FinalAnswerTool()
    ]

    self.wikipedia_search_agent = smolagents.CodeAgent(
        name="wikipedia_search_agent",
        description="Best search of wikipedia pages",
        model=self.code_model,
        tools=wikipedia_search_tools,
        max_steps=6,
        verbosity_level=2,
        planning_interval=None,
        additional_authorized_imports=["wikipedia-api"],
    )

    manager_tools = [
        convert_from_url,
        smolagents.FinalAnswerTool(),
    ]
    self.manager_agent = smolagents.CodeAgent(
        name="manager_agent",
        description="Manger of other agents",
        tools=manager_tools,
        model=self.manager_model,
        add_base_tools=True,
        max_steps=15,
        verbosity_level=2,
        planning_interval=3,
        additional_authorized_imports=[
            "duckduckgo_search",
            "wikipedia-api",
            "markitdown",
            "requests",
            "pandas",
            "io",
        ],
        managed_agents=[
            self.web_search_agent,
            self.wikipedia_search_agent,
            self.math_agent,
            #            self.convert_files_to_markdown,
        ],
        final_answer_checks=[self.check_results],
    )

  def __call__(self, question: str) -> str:
    print(f"Agent received question (first 50 chars): {question[:50]}...")
    prompt = f'{SYSTEM_PROMPT}\n\n{question}\n\n {SUFFIX_PROMPT}'
    answer = self.manager_agent.run(prompt)
    print(f"{answer=}")
    return answer