SrcLurker commited on
Commit
895992e
·
1 Parent(s): aa17a5e

include markitdown

Browse files
Files changed (4) hide show
  1. app.py +14 -6
  2. basic_agent.py +62 -10
  3. basic_agent_test.py +36 -8
  4. requirements.txt +1 -0
app.py CHANGED
@@ -21,11 +21,12 @@ LANGFUSE_PUBLIC_KEY = os.environ.get("LANGFUSE_PUBLIC_KEY")
21
  LANGFUSE_SECRET_KEY = os.environ.get("LANGFUSE_SECRET_KEY")
22
 
23
  LANGFUSE_AUTH = base64.b64encode(
24
- f"{LANGFUSE_PUBLIC_KEY}:{LANGFUSE_SECRET_KEY}".encode()
25
- ).decode()
26
 
27
- os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = os.environ.get("LANGFUSE_HOST") + "/api/public/otel"
28
- os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"Authorization=Basic {LANGFUSE_AUTH}"
 
 
29
 
30
  # Create a TracerProvider for OpenTelemetry
31
  trace_provider = TracerProvider()
@@ -35,6 +36,7 @@ trace_provider.add_span_processor(SimpleSpanProcessor(OTLPSpanExporter()))
35
 
36
  # Set the global default tracer provider
37
  from opentelemetry import trace
 
38
  trace.set_tracer_provider(trace_provider)
39
  tracer = trace.get_tracer(__name__)
40
 
@@ -64,9 +66,7 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
64
 
65
  # 1. Instantiate Agent ( modify this part to create your agent)
66
  try:
67
- print("This is new code creating the new basic_agent")
68
  agent = basic_agent.BasicAgent()
69
- print("This is new code creating the new basic_agent is now done")
70
  except Exception as e:
71
  print(f"Error instantiating agent: {e}")
72
  return f"Error initializing agent: {e}", None
@@ -102,6 +102,14 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
102
  for item in questions_data:
103
  task_id = item.get("task_id")
104
  question_text = item.get("question")
 
 
 
 
 
 
 
 
105
  if not task_id or question_text is None:
106
  print(f"Skipping item with missing task_id or question: {item}")
107
  continue
 
21
  LANGFUSE_SECRET_KEY = os.environ.get("LANGFUSE_SECRET_KEY")
22
 
23
  LANGFUSE_AUTH = base64.b64encode(
24
+ f"{LANGFUSE_PUBLIC_KEY}:{LANGFUSE_SECRET_KEY}".encode()).decode()
 
25
 
26
+ os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = os.environ.get(
27
+ "LANGFUSE_HOST") + "/api/public/otel"
28
+ os.environ[
29
+ "OTEL_EXPORTER_OTLP_HEADERS"] = f"Authorization=Basic {LANGFUSE_AUTH}"
30
 
31
  # Create a TracerProvider for OpenTelemetry
32
  trace_provider = TracerProvider()
 
36
 
37
  # Set the global default tracer provider
38
  from opentelemetry import trace
39
+
40
  trace.set_tracer_provider(trace_provider)
41
  tracer = trace.get_tracer(__name__)
42
 
 
66
 
67
  # 1. Instantiate Agent ( modify this part to create your agent)
68
  try:
 
69
  agent = basic_agent.BasicAgent()
 
70
  except Exception as e:
71
  print(f"Error instantiating agent: {e}")
72
  return f"Error initializing agent: {e}", None
 
102
  for item in questions_data:
103
  task_id = item.get("task_id")
104
  question_text = item.get("question")
105
+ filename = item.get("file_name")
106
+ if filename:
107
+ file_url = f"{api_url}/files/{task_id}"
108
+ print("Question {task_id=} has attachment: {file_url=}")
109
+ quest_with_url = f"{question_text}\nFile url: {file_url}"
110
+ else:
111
+ quest_with_url = question_text
112
+
113
  if not task_id or question_text is None:
114
  print(f"Skipping item with missing task_id or question: {item}")
115
  continue
basic_agent.py CHANGED
@@ -3,6 +3,7 @@ import logging
3
  import sys
4
  import time
5
 
 
6
  import smolagents
7
 
8
  # Logs appear to be swallowed.
@@ -23,9 +24,34 @@ Remember - The FINAL ANSWER must be a string, a number or a comma separated list
23
  """
24
 
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  class BasicAgent:
 
27
  def check_results(self, final_answer, agent_memory):
28
- if isinstance(final_answer, str) or isinstance(final_answer, int) or isinstance(final_answer, float):
 
29
  return True
30
  failure = "FAILED! The final answer must be a string, a number or a comma separated list of strings and numbers."
31
  print(f"Feedback: {failure}")
@@ -34,10 +60,10 @@ class BasicAgent:
34
  def __init__(self):
35
  print("BasicAgent initializing.")
36
 
37
- # too big
38
- # self.manager_model_id = "google/gemma-3-27B-it"
39
- # self.manager_model_id = "OpenGVLab/InternVL3-14B"
40
- # self.manager_model_id = "AIDC-AI/Ovis2-34B"
41
 
42
  self.manager_model_id = "meta-llama/Llama-3.3-70B-Instruct"
43
  self.manager_model = None
@@ -61,13 +87,32 @@ class BasicAgent:
61
  custom_role_conversions=None,
62
  )
63
 
64
- print(f"NEW4: BasicAgent {self.manager_model_id=} {self.code_model_id=}")
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  self.math_agent = smolagents.CodeAgent(
67
  name="date_time_math_agent",
68
  description="Handle date, time and math caclulations",
69
  model=self.code_model,
70
- tools=[],
71
  max_steps=6,
72
  verbosity_level=2,
73
  planning_interval=None,
@@ -117,10 +162,17 @@ class BasicAgent:
117
  max_steps=10,
118
  verbosity_level=2,
119
  planning_interval=None,
120
- additional_authorized_imports=["duckduckgo_search", "wikipedia-api"],
121
- managed_agents=[self.web_search_agent, self.wikipedia_search_agent, self.math_agent],
 
 
 
 
 
 
 
122
  final_answer_checks=[self.check_results],
123
- )
124
 
125
  def __call__(self, question: str) -> str:
126
  print(f"Agent received question (first 50 chars): {question[:50]}...")
 
3
  import sys
4
  import time
5
 
6
+ import markitdown
7
  import smolagents
8
 
9
  # Logs appear to be swallowed.
 
24
  """
25
 
26
 
27
+ @smolagents.tool
28
+ def convert_from_url(url: str) -> str:
29
+ """Convert a file at a url into a markdown string.
30
+
31
+ This method takes a path to a file and converts it into
32
+ a markdown string. It can handle a variety of file
33
+ types as input including pdf, excel, xlsx, mp3, csv,
34
+ powerpoint, etc.
35
+
36
+ Args:
37
+ url: the url to access the file. If the file is on the
38
+ local machine, the url should start with "file://"
39
+ instead of the traditional "http://" or "https://".
40
+
41
+ Returns:
42
+ string that is in the markdown format.
43
+ """
44
+ # Don't need third-party plugins.
45
+ md = markitdown.MarkItDown(enable_plugins=Disable)
46
+ result = md.convert(url)
47
+ return result.text_content
48
+
49
+
50
  class BasicAgent:
51
+
52
  def check_results(self, final_answer, agent_memory):
53
+ if isinstance(final_answer, str) or isinstance(
54
+ final_answer, int) or isinstance(final_answer, float):
55
  return True
56
  failure = "FAILED! The final answer must be a string, a number or a comma separated list of strings and numbers."
57
  print(f"Feedback: {failure}")
 
60
  def __init__(self):
61
  print("BasicAgent initializing.")
62
 
63
+ # too big
64
+ # self.manager_model_id = "google/gemma-3-27B-it"
65
+ # self.manager_model_id = "OpenGVLab/InternVL3-14B"
66
+ # self.manager_model_id = "AIDC-AI/Ovis2-34B"
67
 
68
  self.manager_model_id = "meta-llama/Llama-3.3-70B-Instruct"
69
  self.manager_model = None
 
87
  custom_role_conversions=None,
88
  )
89
 
90
+ print(f"NEW5: BasicAgent {self.manager_model_id=} {self.code_model_id=}")
91
 
92
+ file_convert_tool = [
93
+ convert_from_url,
94
+ smolagents.FinalAnswerTool(),
95
+ ]
96
+ self.convert_files_to_markdown = smolagents.CodeAgent(
97
+ name="convert_files_to_markdown",
98
+ description=
99
+ "Given a url, it converts the file from various formats (such as pdf, excel, powerpoint, audio, csv, etc) into the markdown format",
100
+ model=self.code_model,
101
+ tools=file_convert_tool,
102
+ max_steps=6,
103
+ verbosity_level=2,
104
+ planning_interval=None,
105
+ additional_authorized_imports=["markitdown"],
106
+ )
107
+
108
+ math_tools = [
109
+ smolagents.FinalAnswerTool(),
110
+ ]
111
  self.math_agent = smolagents.CodeAgent(
112
  name="date_time_math_agent",
113
  description="Handle date, time and math caclulations",
114
  model=self.code_model,
115
+ tools=math_tools,
116
  max_steps=6,
117
  verbosity_level=2,
118
  planning_interval=None,
 
162
  max_steps=10,
163
  verbosity_level=2,
164
  planning_interval=None,
165
+ additional_authorized_imports=[
166
+ "duckduckgo_search", "wikipedia-api", "markitdown"
167
+ ],
168
+ managed_agents=[
169
+ self.web_search_agent,
170
+ self.wikipedia_search_agent,
171
+ self.math_agent,
172
+ self.convert_files_to_markdown,
173
+ ],
174
  final_answer_checks=[self.check_results],
175
+ )
176
 
177
  def __call__(self, question: str) -> str:
178
  print(f"Agent received question (first 50 chars): {question[:50]}...")
basic_agent_test.py CHANGED
@@ -1,11 +1,13 @@
1
  #!/usr/bin/env python3
2
 
3
  import logging
 
4
 
5
  import basic_agent
6
 
7
  LOG = logging.getLogger(__name__)
8
 
 
9
 
10
  # Local:
11
  # https://huggingface.co/docs/smolagents/tutorials/inspect_runs
@@ -27,18 +29,44 @@ from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProces
27
 
28
  endpoint = "http://0.0.0.0:6006/v1/traces"
29
  trace_provider = TracerProvider()
30
- trace_provider.add_span_processor(SimpleSpanProcessor(OTLPSpanExporter(endpoint)))
 
31
 
32
  SmolagentsInstrumentor().instrument(tracer_provider=trace_provider)
33
 
34
  ba = basic_agent.BasicAgent()
35
 
36
- """
37
- answer = ba(
38
- "Who is the 47th president of the united states? If necessary, use a web search to get the most up to date information."
39
- )
40
- """
41
- answer = ba("What is the first name of the only Malko Competition recipient from the 20th Century (after 1977) whose nationality on record is a country that no longer exists?"
42
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
  LOG.warning(f"{answer=}")
 
1
  #!/usr/bin/env python3
2
 
3
  import logging
4
+ import json
5
 
6
  import basic_agent
7
 
8
  LOG = logging.getLogger(__name__)
9
 
10
+ QUESTIONS_PATH = "../questions.json"
11
 
12
  # Local:
13
  # https://huggingface.co/docs/smolagents/tutorials/inspect_runs
 
29
 
30
  endpoint = "http://0.0.0.0:6006/v1/traces"
31
  trace_provider = TracerProvider()
32
+ trace_provider.add_span_processor(
33
+ SimpleSpanProcessor(OTLPSpanExporter(endpoint)))
34
 
35
  SmolagentsInstrumentor().instrument(tracer_provider=trace_provider)
36
 
37
  ba = basic_agent.BasicAgent()
38
 
39
+ with open(QUESTIONS_PATH, "r") as fp:
40
+ questions = json.load(fp)
41
+
42
+ # Should be 20
43
+ print(f"{len(questions)=}")
44
+
45
+ # One question entry:
46
+ #
47
+ # {'Level': '1',
48
+ # 'file_name': '7bd855d8-463d-4ed5-93ca-5fe35145f733.xlsx',
49
+ # 'question': 'The attached Excel file contains the sales of menu items for a '
50
+ # 'local fast-food chain. What were the total sales that the chain '
51
+ # 'made from food (not including drinks)? Express your answer in '
52
+ # 'USD with two decimal places.',
53
+ # 'task_id': '7bd855d8-463d-4ed5-93ca-5fe35145f733'},
54
+ #
55
+
56
+ want = 7
57
+ question = questions[want]
58
+
59
+ q_task_id = question["task_id"]
60
+ q_text = question["question"]
61
+ q_filename = question.get("file_name", "")
62
+
63
+ if q_filename:
64
+ file_url = f"{api_url}/files/{task_id}"
65
+ print("Question {task_id=} has attachment: {file_url=}")
66
+ quest_with_url = f"{q_text}\nFile url: {file_url}"
67
+ else:
68
+ quest_with_url = q_text
69
+
70
+ answer = ba(question_text)
71
 
72
  LOG.warning(f"{answer=}")
requirements.txt CHANGED
@@ -1,6 +1,7 @@
1
  gradio
2
  requests
3
  huggingface_hub[hf_xet]
 
4
  smolagents
5
  smolagents[openai]
6
  wikipedia-api
 
1
  gradio
2
  requests
3
  huggingface_hub[hf_xet]
4
+ markitdown[all]
5
  smolagents
6
  smolagents[openai]
7
  wikipedia-api