Spaces:
Sleeping
Sleeping
Charles Azam
commited on
Commit
·
395c3d4
1
Parent(s):
1ea134d
feat: add draw image tool
Browse files- data/figure.png +0 -0
- pyproject.toml +5 -0
- src/deepengineer/deepsearch/draw_agent.py +71 -5
- tests/deepsearch/test_web_agent.py +4 -1
- tests/webcrawler/test_draw_agent.py +28 -0
- uv.lock +119 -0
data/figure.png
CHANGED
![]() |
![]() |
pyproject.toml
CHANGED
@@ -18,6 +18,11 @@ dependencies = [
|
|
18 |
"pypdf>=5.7.0",
|
19 |
"pytest-playwright>=0.7.0",
|
20 |
"matplotlib>=3.10.3",
|
|
|
|
|
|
|
|
|
|
|
21 |
]
|
22 |
|
23 |
[project.scripts]
|
|
|
18 |
"pypdf>=5.7.0",
|
19 |
"pytest-playwright>=0.7.0",
|
20 |
"matplotlib>=3.10.3",
|
21 |
+
"numpy>=2.3.1",
|
22 |
+
"pandas>=2.3.1",
|
23 |
+
"seaborn>=0.13.2",
|
24 |
+
"sympy>=1.14.0",
|
25 |
+
"scipy>=1.16.0",
|
26 |
]
|
27 |
|
28 |
[project.scripts]
|
src/deepengineer/deepsearch/draw_agent.py
CHANGED
@@ -12,8 +12,7 @@ from PIL import Image
|
|
12 |
|
13 |
from smolagents import CodeAgent, LiteLLMModel
|
14 |
from smolagents.agents import ActionStep
|
15 |
-
|
16 |
-
import base64, mimetypes
|
17 |
|
18 |
|
19 |
def save_fig(image_path: Path = Path("figure.png")) -> str:
|
@@ -28,6 +27,34 @@ def save_fig(image_path: Path = Path("figure.png")) -> str:
|
|
28 |
return f"Figure saved to {image_path}."
|
29 |
|
30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
def _capture_snapshot(
|
32 |
memory_step: ActionStep, agent: CodeAgent, image_path: Path = Path("figure.png")
|
33 |
) -> None:
|
@@ -59,7 +86,7 @@ def _capture_snapshot(
|
|
59 |
|
60 |
|
61 |
matplotlib_instructions_multiple_steps = r"""
|
62 |
-
You may use the entire **matplotlib** and **numpy** API. Do not worry about saving the image, it is done automatically and you can't access the os library.
|
63 |
|
64 |
Between each step, the image is provided in memory. From step 2, you can use it to pass additional instructions to the model to improve the image.
|
65 |
|
@@ -75,7 +102,7 @@ User instructions:
|
|
75 |
"""
|
76 |
|
77 |
matplotlib_instructions_single_step = r"""
|
78 |
-
You may use the entire **matplotlib** and **numpy** API. Do not worry about saving the image, it is done automatically and you can't access the os library.
|
79 |
|
80 |
Workflow
|
81 |
--------
|
@@ -99,7 +126,12 @@ def draw_image_agent(
|
|
99 |
agent = CodeAgent(
|
100 |
tools=[],
|
101 |
model=model,
|
102 |
-
additional_authorized_imports=[
|
|
|
|
|
|
|
|
|
|
|
103 |
step_callbacks=[
|
104 |
lambda memory_step, agent: _capture_snapshot(memory_step, agent, image_path)
|
105 |
],
|
@@ -115,6 +147,40 @@ def draw_image_agent(
|
|
115 |
return image_path
|
116 |
|
117 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
def multiple_steps_draw_image_agent(
|
119 |
prompt: str,
|
120 |
image_path: str = Path("figure.png"),
|
|
|
12 |
|
13 |
from smolagents import CodeAgent, LiteLLMModel
|
14 |
from smolagents.agents import ActionStep
|
15 |
+
from smolagents import tool, Tool
|
|
|
16 |
|
17 |
|
18 |
def save_fig(image_path: Path = Path("figure.png")) -> str:
|
|
|
27 |
return f"Figure saved to {image_path}."
|
28 |
|
29 |
|
30 |
+
class SaveMatplotlibFigTool(Tool):
|
31 |
+
name = "save_matplotlib_fig"
|
32 |
+
description = """Save the current matplotlib figure to the current directory. Then plt.close() is called to clear the figure. The image is returned as a markdown string, use this markdown inside the final answer to include the image.
|
33 |
+
"""
|
34 |
+
inputs = {
|
35 |
+
"image_name": {
|
36 |
+
"type": "string",
|
37 |
+
"description": "The name of the image to save.",
|
38 |
+
},
|
39 |
+
}
|
40 |
+
output_type = "string"
|
41 |
+
|
42 |
+
def __init__(self, output_dir: Path):
|
43 |
+
super().__init__()
|
44 |
+
self.output_dir: Path = output_dir
|
45 |
+
|
46 |
+
def forward(self, image_name: str) -> str:
|
47 |
+
if not image_name.endswith(".png"):
|
48 |
+
image_name = image_name + ".png"
|
49 |
+
output_path = self.output_dir / image_name
|
50 |
+
output_path.unlink(missing_ok=True)
|
51 |
+
save_fig(output_path)
|
52 |
+
if output_path.exists():
|
53 |
+
return f""
|
54 |
+
else:
|
55 |
+
return f"Error: The image {image_name} was not saved."
|
56 |
+
|
57 |
+
|
58 |
def _capture_snapshot(
|
59 |
memory_step: ActionStep, agent: CodeAgent, image_path: Path = Path("figure.png")
|
60 |
) -> None:
|
|
|
86 |
|
87 |
|
88 |
matplotlib_instructions_multiple_steps = r"""
|
89 |
+
You may use the entire **matplotlib** and **numpy** and **pandas** and **seaborn** API. Do not worry about saving the image, it is done automatically and you can't access the os library.
|
90 |
|
91 |
Between each step, the image is provided in memory. From step 2, you can use it to pass additional instructions to the model to improve the image.
|
92 |
|
|
|
102 |
"""
|
103 |
|
104 |
matplotlib_instructions_single_step = r"""
|
105 |
+
You may use the entire **matplotlib** and **numpy** and **pandas** and **seaborn** API. Do not worry about saving the image, it is done automatically and you can't access the os library.
|
106 |
|
107 |
Workflow
|
108 |
--------
|
|
|
126 |
agent = CodeAgent(
|
127 |
tools=[],
|
128 |
model=model,
|
129 |
+
additional_authorized_imports=[
|
130 |
+
"matplotlib.*",
|
131 |
+
"numpy.*",
|
132 |
+
"pandas.*",
|
133 |
+
"seaborn.*",
|
134 |
+
],
|
135 |
step_callbacks=[
|
136 |
lambda memory_step, agent: _capture_snapshot(memory_step, agent, image_path)
|
137 |
],
|
|
|
147 |
return image_path
|
148 |
|
149 |
|
150 |
+
class DrawImageTool(Tool):
|
151 |
+
name = "draw_image"
|
152 |
+
description = f"Draw an image based on a prompt. The image is saved in the current directory. The image is returned as a markdown image, use this markdown inside the final answer to include the image. You must be very specific in your prompt."
|
153 |
+
inputs = {
|
154 |
+
"prompt": {
|
155 |
+
"type": "string",
|
156 |
+
"description": """
|
157 |
+
Draw an image based on a prompt. The image is saved in the current directory. The image is returned as a markdown image, use this markdown inside the final answer to include the image.
|
158 |
+
|
159 |
+
You must be very specific in your prompt. This tool has access to matplotlib, numpy, pandas, seaborn.
|
160 |
+
|
161 |
+
""",
|
162 |
+
},
|
163 |
+
"image_name": {
|
164 |
+
"type": "string",
|
165 |
+
"description": "The name of the image to save.",
|
166 |
+
},
|
167 |
+
}
|
168 |
+
output_type = "string"
|
169 |
+
|
170 |
+
def __init__(self, output_dir: Path):
|
171 |
+
super().__init__()
|
172 |
+
self.output_dir: Path = output_dir
|
173 |
+
|
174 |
+
def forward(self, prompt: str, image_name: str) -> str:
|
175 |
+
if not image_name.endswith(".png"):
|
176 |
+
image_name = image_name + ".png"
|
177 |
+
output_path = draw_image_agent(prompt, self.output_dir / image_name)
|
178 |
+
if output_path.exists():
|
179 |
+
return f""
|
180 |
+
else:
|
181 |
+
return f"Error: The image {image_name} was not saved."
|
182 |
+
|
183 |
+
|
184 |
def multiple_steps_draw_image_agent(
|
185 |
prompt: str,
|
186 |
image_path: str = Path("figure.png"),
|
tests/deepsearch/test_web_agent.py
CHANGED
@@ -11,7 +11,10 @@ def test_run_web_search_agent():
|
|
11 |
agent = create_web_search_agent()
|
12 |
assert (
|
13 |
agent.run(
|
14 |
-
"
|
15 |
)
|
16 |
is not None
|
17 |
)
|
|
|
|
|
|
|
|
11 |
agent = create_web_search_agent()
|
12 |
assert (
|
13 |
agent.run(
|
14 |
+
'Search a paper called "High Energy Physics Opportunities Using Reactor Antineutrinos" on arXiv, download it and extract the table of contents'
|
15 |
)
|
16 |
is not None
|
17 |
)
|
18 |
+
|
19 |
+
|
20 |
+
test_run_web_search_agent()
|
tests/webcrawler/test_draw_agent.py
CHANGED
@@ -2,9 +2,11 @@ import pytest
|
|
2 |
from deepengineer.deepsearch.draw_agent import (
|
3 |
draw_image_agent,
|
4 |
multiple_steps_draw_image_agent,
|
|
|
5 |
)
|
6 |
from deepengineer.common_path import DATA_DIR
|
7 |
from pathlib import Path
|
|
|
8 |
|
9 |
|
10 |
@pytest.mark.expensive
|
@@ -16,6 +18,32 @@ def test_draw_image_agent():
|
|
16 |
assert output_path.exists()
|
17 |
|
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
@pytest.mark.skip(reason="This function is not working yet")
|
20 |
def test_run_agent_step_by_step():
|
21 |
prompt = """Propose moi un schéma très détaillé d'un réacteur nucléaire hélium graphite."""
|
|
|
2 |
from deepengineer.deepsearch.draw_agent import (
|
3 |
draw_image_agent,
|
4 |
multiple_steps_draw_image_agent,
|
5 |
+
SaveMatplotlibFigTool,
|
6 |
)
|
7 |
from deepengineer.common_path import DATA_DIR
|
8 |
from pathlib import Path
|
9 |
+
from smolagents import CodeAgent, LiteLLMModel
|
10 |
|
11 |
|
12 |
@pytest.mark.expensive
|
|
|
18 |
assert output_path.exists()
|
19 |
|
20 |
|
21 |
+
def test_save_matplotlib_fig_tool():
|
22 |
+
model = LiteLLMModel(model_id="mistral/mistral-medium-latest")
|
23 |
+
agent = CodeAgent(
|
24 |
+
tools=[SaveMatplotlibFigTool(output_dir=Path(DATA_DIR))],
|
25 |
+
model=model,
|
26 |
+
additional_authorized_imports=[
|
27 |
+
"matplotlib.*",
|
28 |
+
"numpy.*",
|
29 |
+
"pandas.*",
|
30 |
+
"seaborn.*",
|
31 |
+
],
|
32 |
+
max_steps=20,
|
33 |
+
verbosity_level=2,
|
34 |
+
)
|
35 |
+
agent.run(
|
36 |
+
"""
|
37 |
+
Propose moi un schéma très détaillé d'un réacteur nucléaire hélium graphite.
|
38 |
+
Save the figure as figure.png. Return a markdown string where you explain what you did and then include the image.
|
39 |
+
"""
|
40 |
+
)
|
41 |
+
assert (Path(DATA_DIR) / "figure.png").exists()
|
42 |
+
|
43 |
+
|
44 |
+
test_save_matplotlib_fig_tool()
|
45 |
+
|
46 |
+
|
47 |
@pytest.mark.skip(reason="This function is not working yet")
|
48 |
def test_run_agent_step_by_step():
|
49 |
prompt = """Propose moi un schéma très détaillé d'un réacteur nucléaire hélium graphite."""
|
uv.lock
CHANGED
@@ -388,10 +388,15 @@ dependencies = [
|
|
388 |
{ name = "litellm" },
|
389 |
{ name = "matplotlib" },
|
390 |
{ name = "mistralai" },
|
|
|
|
|
391 |
{ name = "pypdf" },
|
392 |
{ name = "pytest-asyncio" },
|
393 |
{ name = "pytest-playwright" },
|
|
|
|
|
394 |
{ name = "smolagents" },
|
|
|
395 |
{ name = "tavily-python" },
|
396 |
]
|
397 |
|
@@ -410,12 +415,17 @@ requires-dist = [
|
|
410 |
{ name = "litellm" },
|
411 |
{ name = "matplotlib", specifier = ">=3.10.3" },
|
412 |
{ name = "mistralai", specifier = ">=1.9.1" },
|
|
|
|
|
413 |
{ name = "pre-commit", marker = "extra == 'dev'", specifier = ">=3.6.0" },
|
414 |
{ name = "pypdf", specifier = ">=5.7.0" },
|
415 |
{ name = "pytest-asyncio", specifier = ">=1.0.0" },
|
416 |
{ name = "pytest-playwright", specifier = ">=0.7.0" },
|
417 |
{ name = "ruff", marker = "extra == 'dev'", specifier = ">=0.2.0" },
|
|
|
|
|
418 |
{ name = "smolagents", specifier = ">=1.19.0" },
|
|
|
419 |
{ name = "tavily-python", specifier = ">=0.7.9" },
|
420 |
]
|
421 |
provides-extras = ["dev"]
|
@@ -961,6 +971,15 @@ wheels = [
|
|
961 |
{ url = "https://files.pythonhosted.org/packages/10/a2/2e177165a24d978f07cf5d5841265ab399c187b0a44077d67502b8129b27/mistralai-1.9.1-py3-none-any.whl", hash = "sha256:250ec26534db6f4a4d5e6292b0801a64da2ab1f0d4c63a20d8ce27e3a427e402", size = 381773 },
|
962 |
]
|
963 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
964 |
[[package]]
|
965 |
name = "multidict"
|
966 |
version = "6.6.3"
|
@@ -1097,6 +1116,33 @@ wheels = [
|
|
1097 |
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469 },
|
1098 |
]
|
1099 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1100 |
[[package]]
|
1101 |
name = "pathspec"
|
1102 |
version = "0.12.1"
|
@@ -1432,6 +1478,15 @@ wheels = [
|
|
1432 |
{ url = "https://files.pythonhosted.org/packages/a4/62/02da182e544a51a5c3ccf4b03ab79df279f9c60c5e82d5e8bec7ca26ac11/python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8", size = 10051 },
|
1433 |
]
|
1434 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1435 |
[[package]]
|
1436 |
name = "pyyaml"
|
1437 |
version = "6.0.2"
|
@@ -1612,6 +1667,49 @@ wheels = [
|
|
1612 |
{ url = "https://files.pythonhosted.org/packages/e2/1f/72d2946e3cc7456bb837e88000eb3437e55f80db339c840c04015a11115d/ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12", size = 10735334 },
|
1613 |
]
|
1614 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1615 |
[[package]]
|
1616 |
name = "six"
|
1617 |
version = "1.17.0"
|
@@ -1665,6 +1763,18 @@ wheels = [
|
|
1665 |
{ url = "https://files.pythonhosted.org/packages/e7/9c/0e6afc12c269578be5c0c1c9f4b49a8d32770a080260c333ac04cc1c832d/soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4", size = 36677 },
|
1666 |
]
|
1667 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1668 |
[[package]]
|
1669 |
name = "tavily-python"
|
1670 |
version = "0.7.9"
|
@@ -1777,6 +1887,15 @@ wheels = [
|
|
1777 |
{ url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552 },
|
1778 |
]
|
1779 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1780 |
[[package]]
|
1781 |
name = "urllib3"
|
1782 |
version = "2.5.0"
|
|
|
388 |
{ name = "litellm" },
|
389 |
{ name = "matplotlib" },
|
390 |
{ name = "mistralai" },
|
391 |
+
{ name = "numpy" },
|
392 |
+
{ name = "pandas" },
|
393 |
{ name = "pypdf" },
|
394 |
{ name = "pytest-asyncio" },
|
395 |
{ name = "pytest-playwright" },
|
396 |
+
{ name = "scipy" },
|
397 |
+
{ name = "seaborn" },
|
398 |
{ name = "smolagents" },
|
399 |
+
{ name = "sympy" },
|
400 |
{ name = "tavily-python" },
|
401 |
]
|
402 |
|
|
|
415 |
{ name = "litellm" },
|
416 |
{ name = "matplotlib", specifier = ">=3.10.3" },
|
417 |
{ name = "mistralai", specifier = ">=1.9.1" },
|
418 |
+
{ name = "numpy", specifier = ">=2.3.1" },
|
419 |
+
{ name = "pandas", specifier = ">=2.3.1" },
|
420 |
{ name = "pre-commit", marker = "extra == 'dev'", specifier = ">=3.6.0" },
|
421 |
{ name = "pypdf", specifier = ">=5.7.0" },
|
422 |
{ name = "pytest-asyncio", specifier = ">=1.0.0" },
|
423 |
{ name = "pytest-playwright", specifier = ">=0.7.0" },
|
424 |
{ name = "ruff", marker = "extra == 'dev'", specifier = ">=0.2.0" },
|
425 |
+
{ name = "scipy", specifier = ">=1.16.0" },
|
426 |
+
{ name = "seaborn", specifier = ">=0.13.2" },
|
427 |
{ name = "smolagents", specifier = ">=1.19.0" },
|
428 |
+
{ name = "sympy", specifier = ">=1.14.0" },
|
429 |
{ name = "tavily-python", specifier = ">=0.7.9" },
|
430 |
]
|
431 |
provides-extras = ["dev"]
|
|
|
971 |
{ url = "https://files.pythonhosted.org/packages/10/a2/2e177165a24d978f07cf5d5841265ab399c187b0a44077d67502b8129b27/mistralai-1.9.1-py3-none-any.whl", hash = "sha256:250ec26534db6f4a4d5e6292b0801a64da2ab1f0d4c63a20d8ce27e3a427e402", size = 381773 },
|
972 |
]
|
973 |
|
974 |
+
[[package]]
|
975 |
+
name = "mpmath"
|
976 |
+
version = "1.3.0"
|
977 |
+
source = { registry = "https://pypi.org/simple" }
|
978 |
+
sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106 }
|
979 |
+
wheels = [
|
980 |
+
{ url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198 },
|
981 |
+
]
|
982 |
+
|
983 |
[[package]]
|
984 |
name = "multidict"
|
985 |
version = "6.6.3"
|
|
|
1116 |
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469 },
|
1117 |
]
|
1118 |
|
1119 |
+
[[package]]
|
1120 |
+
name = "pandas"
|
1121 |
+
version = "2.3.1"
|
1122 |
+
source = { registry = "https://pypi.org/simple" }
|
1123 |
+
dependencies = [
|
1124 |
+
{ name = "numpy" },
|
1125 |
+
{ name = "python-dateutil" },
|
1126 |
+
{ name = "pytz" },
|
1127 |
+
{ name = "tzdata" },
|
1128 |
+
]
|
1129 |
+
sdist = { url = "https://files.pythonhosted.org/packages/d1/6f/75aa71f8a14267117adeeed5d21b204770189c0a0025acbdc03c337b28fc/pandas-2.3.1.tar.gz", hash = "sha256:0a95b9ac964fe83ce317827f80304d37388ea77616b1425f0ae41c9d2d0d7bb2", size = 4487493 }
|
1130 |
+
wheels = [
|
1131 |
+
{ url = "https://files.pythonhosted.org/packages/32/ed/ff0a67a2c5505e1854e6715586ac6693dd860fbf52ef9f81edee200266e7/pandas-2.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9026bd4a80108fac2239294a15ef9003c4ee191a0f64b90f170b40cfb7cf2d22", size = 11531393 },
|
1132 |
+
{ url = "https://files.pythonhosted.org/packages/c7/db/d8f24a7cc9fb0972adab0cc80b6817e8bef888cfd0024eeb5a21c0bb5c4a/pandas-2.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6de8547d4fdb12421e2d047a2c446c623ff4c11f47fddb6b9169eb98ffba485a", size = 10668750 },
|
1133 |
+
{ url = "https://files.pythonhosted.org/packages/0f/b0/80f6ec783313f1e2356b28b4fd8d2148c378370045da918c73145e6aab50/pandas-2.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:782647ddc63c83133b2506912cc6b108140a38a37292102aaa19c81c83db2928", size = 11342004 },
|
1134 |
+
{ url = "https://files.pythonhosted.org/packages/e9/e2/20a317688435470872885e7fc8f95109ae9683dec7c50be29b56911515a5/pandas-2.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ba6aff74075311fc88504b1db890187a3cd0f887a5b10f5525f8e2ef55bfdb9", size = 12050869 },
|
1135 |
+
{ url = "https://files.pythonhosted.org/packages/55/79/20d746b0a96c67203a5bee5fb4e00ac49c3e8009a39e1f78de264ecc5729/pandas-2.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e5635178b387bd2ba4ac040f82bc2ef6e6b500483975c4ebacd34bec945fda12", size = 12750218 },
|
1136 |
+
{ url = "https://files.pythonhosted.org/packages/7c/0f/145c8b41e48dbf03dd18fdd7f24f8ba95b8254a97a3379048378f33e7838/pandas-2.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6f3bf5ec947526106399a9e1d26d40ee2b259c66422efdf4de63c848492d91bb", size = 13416763 },
|
1137 |
+
{ url = "https://files.pythonhosted.org/packages/b2/c0/54415af59db5cdd86a3d3bf79863e8cc3fa9ed265f0745254061ac09d5f2/pandas-2.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:1c78cf43c8fde236342a1cb2c34bcff89564a7bfed7e474ed2fffa6aed03a956", size = 10987482 },
|
1138 |
+
{ url = "https://files.pythonhosted.org/packages/48/64/2fd2e400073a1230e13b8cd604c9bc95d9e3b962e5d44088ead2e8f0cfec/pandas-2.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8dfc17328e8da77be3cf9f47509e5637ba8f137148ed0e9b5241e1baf526e20a", size = 12029159 },
|
1139 |
+
{ url = "https://files.pythonhosted.org/packages/d8/0a/d84fd79b0293b7ef88c760d7dca69828d867c89b6d9bc52d6a27e4d87316/pandas-2.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ec6c851509364c59a5344458ab935e6451b31b818be467eb24b0fe89bd05b6b9", size = 11393287 },
|
1140 |
+
{ url = "https://files.pythonhosted.org/packages/50/ae/ff885d2b6e88f3c7520bb74ba319268b42f05d7e583b5dded9837da2723f/pandas-2.3.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:911580460fc4884d9b05254b38a6bfadddfcc6aaef856fb5859e7ca202e45275", size = 11309381 },
|
1141 |
+
{ url = "https://files.pythonhosted.org/packages/85/86/1fa345fc17caf5d7780d2699985c03dbe186c68fee00b526813939062bb0/pandas-2.3.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f4d6feeba91744872a600e6edbbd5b033005b431d5ae8379abee5bcfa479fab", size = 11883998 },
|
1142 |
+
{ url = "https://files.pythonhosted.org/packages/81/aa/e58541a49b5e6310d89474333e994ee57fea97c8aaa8fc7f00b873059bbf/pandas-2.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:fe37e757f462d31a9cd7580236a82f353f5713a80e059a29753cf938c6775d96", size = 12704705 },
|
1143 |
+
{ url = "https://files.pythonhosted.org/packages/d5/f9/07086f5b0f2a19872554abeea7658200824f5835c58a106fa8f2ae96a46c/pandas-2.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5db9637dbc24b631ff3707269ae4559bce4b7fd75c1c4d7e13f40edc42df4444", size = 13189044 },
|
1144 |
+
]
|
1145 |
+
|
1146 |
[[package]]
|
1147 |
name = "pathspec"
|
1148 |
version = "0.12.1"
|
|
|
1478 |
{ url = "https://files.pythonhosted.org/packages/a4/62/02da182e544a51a5c3ccf4b03ab79df279f9c60c5e82d5e8bec7ca26ac11/python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8", size = 10051 },
|
1479 |
]
|
1480 |
|
1481 |
+
[[package]]
|
1482 |
+
name = "pytz"
|
1483 |
+
version = "2025.2"
|
1484 |
+
source = { registry = "https://pypi.org/simple" }
|
1485 |
+
sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884 }
|
1486 |
+
wheels = [
|
1487 |
+
{ url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225 },
|
1488 |
+
]
|
1489 |
+
|
1490 |
[[package]]
|
1491 |
name = "pyyaml"
|
1492 |
version = "6.0.2"
|
|
|
1667 |
{ url = "https://files.pythonhosted.org/packages/e2/1f/72d2946e3cc7456bb837e88000eb3437e55f80db339c840c04015a11115d/ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12", size = 10735334 },
|
1668 |
]
|
1669 |
|
1670 |
+
[[package]]
|
1671 |
+
name = "scipy"
|
1672 |
+
version = "1.16.0"
|
1673 |
+
source = { registry = "https://pypi.org/simple" }
|
1674 |
+
dependencies = [
|
1675 |
+
{ name = "numpy" },
|
1676 |
+
]
|
1677 |
+
sdist = { url = "https://files.pythonhosted.org/packages/81/18/b06a83f0c5ee8cddbde5e3f3d0bb9b702abfa5136ef6d4620ff67df7eee5/scipy-1.16.0.tar.gz", hash = "sha256:b5ef54021e832869c8cfb03bc3bf20366cbcd426e02a58e8a58d7584dfbb8f62", size = 30581216 }
|
1678 |
+
wheels = [
|
1679 |
+
{ url = "https://files.pythonhosted.org/packages/46/95/0746417bc24be0c2a7b7563946d61f670a3b491b76adede420e9d173841f/scipy-1.16.0-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:e9f414cbe9ca289a73e0cc92e33a6a791469b6619c240aa32ee18abdce8ab451", size = 36418162 },
|
1680 |
+
{ url = "https://files.pythonhosted.org/packages/19/5a/914355a74481b8e4bbccf67259bbde171348a3f160b67b4945fbc5f5c1e5/scipy-1.16.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:bbba55fb97ba3cdef9b1ee973f06b09d518c0c7c66a009c729c7d1592be1935e", size = 28465985 },
|
1681 |
+
{ url = "https://files.pythonhosted.org/packages/58/46/63477fc1246063855969cbefdcee8c648ba4b17f67370bd542ba56368d0b/scipy-1.16.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:58e0d4354eacb6004e7aa1cd350e5514bd0270acaa8d5b36c0627bb3bb486974", size = 20737961 },
|
1682 |
+
{ url = "https://files.pythonhosted.org/packages/93/86/0fbb5588b73555e40f9d3d6dde24ee6fac7d8e301a27f6f0cab9d8f66ff2/scipy-1.16.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:75b2094ec975c80efc273567436e16bb794660509c12c6a31eb5c195cbf4b6dc", size = 23377941 },
|
1683 |
+
{ url = "https://files.pythonhosted.org/packages/ca/80/a561f2bf4c2da89fa631b3cbf31d120e21ea95db71fd9ec00cb0247c7a93/scipy-1.16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6b65d232157a380fdd11a560e7e21cde34fdb69d65c09cb87f6cc024ee376351", size = 33196703 },
|
1684 |
+
{ url = "https://files.pythonhosted.org/packages/11/6b/3443abcd0707d52e48eb315e33cc669a95e29fc102229919646f5a501171/scipy-1.16.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1d8747f7736accd39289943f7fe53a8333be7f15a82eea08e4afe47d79568c32", size = 35083410 },
|
1685 |
+
{ url = "https://files.pythonhosted.org/packages/20/ab/eb0fc00e1e48961f1bd69b7ad7e7266896fe5bad4ead91b5fc6b3561bba4/scipy-1.16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:eb9f147a1b8529bb7fec2a85cf4cf42bdfadf9e83535c309a11fdae598c88e8b", size = 35387829 },
|
1686 |
+
{ url = "https://files.pythonhosted.org/packages/57/9e/d6fc64e41fad5d481c029ee5a49eefc17f0b8071d636a02ceee44d4a0de2/scipy-1.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d2b83c37edbfa837a8923d19c749c1935ad3d41cf196006a24ed44dba2ec4358", size = 37841356 },
|
1687 |
+
{ url = "https://files.pythonhosted.org/packages/7c/a7/4c94bbe91f12126b8bf6709b2471900577b7373a4fd1f431f28ba6f81115/scipy-1.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:79a3c13d43c95aa80b87328a46031cf52508cf5f4df2767602c984ed1d3c6bbe", size = 38403710 },
|
1688 |
+
{ url = "https://files.pythonhosted.org/packages/47/20/965da8497f6226e8fa90ad3447b82ed0e28d942532e92dd8b91b43f100d4/scipy-1.16.0-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:f91b87e1689f0370690e8470916fe1b2308e5b2061317ff76977c8f836452a47", size = 36813833 },
|
1689 |
+
{ url = "https://files.pythonhosted.org/packages/28/f4/197580c3dac2d234e948806e164601c2df6f0078ed9f5ad4a62685b7c331/scipy-1.16.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:88a6ca658fb94640079e7a50b2ad3b67e33ef0f40e70bdb7dc22017dae73ac08", size = 28974431 },
|
1690 |
+
{ url = "https://files.pythonhosted.org/packages/8a/fc/e18b8550048d9224426e76906694c60028dbdb65d28b1372b5503914b89d/scipy-1.16.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:ae902626972f1bd7e4e86f58fd72322d7f4ec7b0cfc17b15d4b7006efc385176", size = 21246454 },
|
1691 |
+
{ url = "https://files.pythonhosted.org/packages/8c/48/07b97d167e0d6a324bfd7484cd0c209cc27338b67e5deadae578cf48e809/scipy-1.16.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:8cb824c1fc75ef29893bc32b3ddd7b11cf9ab13c1127fe26413a05953b8c32ed", size = 23772979 },
|
1692 |
+
{ url = "https://files.pythonhosted.org/packages/4c/4f/9efbd3f70baf9582edf271db3002b7882c875ddd37dc97f0f675ad68679f/scipy-1.16.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:de2db7250ff6514366a9709c2cba35cb6d08498e961cba20d7cff98a7ee88938", size = 33341972 },
|
1693 |
+
{ url = "https://files.pythonhosted.org/packages/3f/dc/9e496a3c5dbe24e76ee24525155ab7f659c20180bab058ef2c5fa7d9119c/scipy-1.16.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e85800274edf4db8dd2e4e93034f92d1b05c9421220e7ded9988b16976f849c1", size = 35185476 },
|
1694 |
+
{ url = "https://files.pythonhosted.org/packages/ce/b3/21001cff985a122ba434c33f2c9d7d1dc3b669827e94f4fc4e1fe8b9dfd8/scipy-1.16.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4f720300a3024c237ace1cb11f9a84c38beb19616ba7c4cdcd771047a10a1706", size = 35570990 },
|
1695 |
+
{ url = "https://files.pythonhosted.org/packages/e5/d3/7ba42647d6709251cdf97043d0c107e0317e152fa2f76873b656b509ff55/scipy-1.16.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:aad603e9339ddb676409b104c48a027e9916ce0d2838830691f39552b38a352e", size = 37950262 },
|
1696 |
+
{ url = "https://files.pythonhosted.org/packages/eb/c4/231cac7a8385394ebbbb4f1ca662203e9d8c332825ab4f36ffc3ead09a42/scipy-1.16.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f56296fefca67ba605fd74d12f7bd23636267731a72cb3947963e76b8c0a25db", size = 38515076 },
|
1697 |
+
]
|
1698 |
+
|
1699 |
+
[[package]]
|
1700 |
+
name = "seaborn"
|
1701 |
+
version = "0.13.2"
|
1702 |
+
source = { registry = "https://pypi.org/simple" }
|
1703 |
+
dependencies = [
|
1704 |
+
{ name = "matplotlib" },
|
1705 |
+
{ name = "numpy" },
|
1706 |
+
{ name = "pandas" },
|
1707 |
+
]
|
1708 |
+
sdist = { url = "https://files.pythonhosted.org/packages/86/59/a451d7420a77ab0b98f7affa3a1d78a313d2f7281a57afb1a34bae8ab412/seaborn-0.13.2.tar.gz", hash = "sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7", size = 1457696 }
|
1709 |
+
wheels = [
|
1710 |
+
{ url = "https://files.pythonhosted.org/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987", size = 294914 },
|
1711 |
+
]
|
1712 |
+
|
1713 |
[[package]]
|
1714 |
name = "six"
|
1715 |
version = "1.17.0"
|
|
|
1763 |
{ url = "https://files.pythonhosted.org/packages/e7/9c/0e6afc12c269578be5c0c1c9f4b49a8d32770a080260c333ac04cc1c832d/soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4", size = 36677 },
|
1764 |
]
|
1765 |
|
1766 |
+
[[package]]
|
1767 |
+
name = "sympy"
|
1768 |
+
version = "1.14.0"
|
1769 |
+
source = { registry = "https://pypi.org/simple" }
|
1770 |
+
dependencies = [
|
1771 |
+
{ name = "mpmath" },
|
1772 |
+
]
|
1773 |
+
sdist = { url = "https://files.pythonhosted.org/packages/83/d3/803453b36afefb7c2bb238361cd4ae6125a569b4db67cd9e79846ba2d68c/sympy-1.14.0.tar.gz", hash = "sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517", size = 7793921 }
|
1774 |
+
wheels = [
|
1775 |
+
{ url = "https://files.pythonhosted.org/packages/a2/09/77d55d46fd61b4a135c444fc97158ef34a095e5681d0a6c10b75bf356191/sympy-1.14.0-py3-none-any.whl", hash = "sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5", size = 6299353 },
|
1776 |
+
]
|
1777 |
+
|
1778 |
[[package]]
|
1779 |
name = "tavily-python"
|
1780 |
version = "0.7.9"
|
|
|
1887 |
{ url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552 },
|
1888 |
]
|
1889 |
|
1890 |
+
[[package]]
|
1891 |
+
name = "tzdata"
|
1892 |
+
version = "2025.2"
|
1893 |
+
source = { registry = "https://pypi.org/simple" }
|
1894 |
+
sdist = { url = "https://files.pythonhosted.org/packages/95/32/1a225d6164441be760d75c2c42e2780dc0873fe382da3e98a2e1e48361e5/tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9", size = 196380 }
|
1895 |
+
wheels = [
|
1896 |
+
{ url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839 },
|
1897 |
+
]
|
1898 |
+
|
1899 |
[[package]]
|
1900 |
name = "urllib3"
|
1901 |
version = "2.5.0"
|