errchh commited on
Commit
a725b6b
·
1 Parent(s): 329c2f7

correcting tools

Browse files
__pycache__/agent.cpython-312.pyc CHANGED
Binary files a/__pycache__/agent.cpython-312.pyc and b/__pycache__/agent.cpython-312.pyc differ
 
__pycache__/agent.cpython-313.pyc ADDED
Binary file (6.91 kB). View file
 
__pycache__/prompts.cpython-312.pyc CHANGED
Binary files a/__pycache__/prompts.cpython-312.pyc and b/__pycache__/prompts.cpython-312.pyc differ
 
agent.py CHANGED
@@ -26,52 +26,103 @@ from prompts import system_prompt
26
  load_dotenv()
27
 
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  # wikipedia search tool
30
  @tool
31
- def search_wiki(query: str) -> str:
32
  """Search Wikipedia for a query and return maximum 2 results.
33
 
34
  Args:
35
  query: The search query."""
36
- search_docs = WikipediaLoader(query=query, load_max_docs=2).load()
37
- formatted_search_docs = "\n\n---\n\n".join(
38
- [
39
- f'<Document source="{doc.metadata["source"]}" page="{doc.metadata.get("page", "")}"/>\n{doc.page_content}\n</Document>'
40
- for doc in search_docs
41
- ])
42
- return {"wiki_results": formatted_search_docs}
 
 
 
 
 
 
 
 
 
43
 
44
 
45
  # internet search tool
46
  @tool
47
- def search_web(query: str) -> str:
48
  """Search Tavily for a query and return maximum 3 results.
49
 
50
  Args:
51
  query: The search query."""
52
- search_docs = TavilySearchResults(max_results=3).invoke(query=query)
53
- formatted_search_docs = "\n\n---\n\n".join(
54
- [
55
- f'<Document source="{doc.metadata["source"]}" page="{doc.metadata.get("page", "")}"/>\n{doc.page_content}\n</Document>'
56
- for doc in search_docs
57
- ])
58
- return {"web_results": formatted_search_docs}
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
 
61
  # ArXiv search tool
62
  @tool
63
- def search_arxiv(query: str) -> str:
64
  """Search Arxiv for a query and return maximum 3 result.
65
 
66
  Args:
67
  query: The search query."""
68
- search_docs = ArxivLoader(query=query, load_max_docs=3).load()
69
- formatted_search_docs = "\n\n---\n\n".join(
70
- [
71
- f'<Document source="{doc.metadata["source"]}" page="{doc.metadata.get("page", "")}"/>\n{doc.page_content[:1000]}\n</Document>'
72
- for doc in search_docs
73
- ])
74
- return {"arvix_results": formatted_search_docs}
 
 
 
 
 
 
 
 
 
 
 
75
 
76
 
77
  # build retriever
@@ -96,10 +147,6 @@ def build_graph():
96
  model="gemini-2.5-flash-preview-04-17",
97
  temperature=0
98
  )
99
- # llm = ChatGroq(
100
- # model="meta-llama/llama-4-scout-17b-16e-instruct",
101
- # temperature=0.1,
102
- # )
103
  print(f"DEBUG: llm object = {llm}")
104
 
105
  # bind tools to llm
@@ -149,9 +196,12 @@ def build_graph():
149
 
150
 
151
  if __name__ == "__main__":
152
- question = "When was a picture of St. Thomas Aquinas first added to the Wikipedia page on the Principle of double effect?"
 
153
  graph = build_graph()
154
  messages = [HumanMessage(content=question)]
 
155
  messages = graph.invoke({"messages": messages})
 
156
  for m in messages["messages"]:
157
  m.pretty_print()
 
26
  load_dotenv()
27
 
28
 
29
+ # Helper function to extract Arxiv URL
30
+ def get_arxiv_url(content: str) -> str:
31
+ """Extract arXiv ID from text content and format as a URL."""
32
+ lines = content.split('\n')
33
+ for line in lines:
34
+ if line.strip().startswith('arXiv:'):
35
+ parts = line.strip().split()
36
+ if parts:
37
+ arxiv_id_with_prefix = parts[0] # e.g., 'arXiv:2302.00001v1'
38
+ # Remove 'arXiv:' prefix
39
+ arxiv_id = arxiv_id_with_prefix.replace('arXiv:', '').strip()
40
+ # The standard URL format is https://arxiv.org/abs/YYYY.NNNNN
41
+ # Extract just the base ID before any version indicator 'v'
42
+ base_arxiv_id = arxiv_id.split('v')[0]
43
+ return f"https://arxiv.org/abs/{base_arxiv_id}"
44
+ return "unknown" # Fallback if ID is not found
45
+
46
+
47
  # wikipedia search tool
48
  @tool
49
+ def search_wiki(query: str) -> Dict[str, str]:
50
  """Search Wikipedia for a query and return maximum 2 results.
51
 
52
  Args:
53
  query: The search query."""
54
+ print(f" executing search_wiki with query: {query}") # Added debug
55
+ try:
56
+ search_docs = WikipediaLoader(query=query, load_max_docs=2).load()
57
+ print(f"Found {len(search_docs)} documents for query '{query}'") # Added debug
58
+ formatted_search_docs = "\n\n---\n\n".join(
59
+ [
60
+ f'<Document source="{doc.metadata.get("source", "unknown")}" page="{doc.metadata.get("page", "")}"/>\n{doc.page_content}\n</Document>'
61
+ for doc in search_docs
62
+ ]
63
+ )
64
+ if not formatted_search_docs:
65
+ print ("Empty search results") # Added debug
66
+ return {"wiki_results": formatted_search_docs}
67
+ except Exception as e:
68
+ print(f"Error in search_wiki: {e}") # Added debug
69
+ return {"wiki_results": f"Search error: {str(e)}"}
70
 
71
 
72
  # internet search tool
73
  @tool
74
+ def search_web(query: str) -> Dict[str, str]:
75
  """Search Tavily for a query and return maximum 3 results.
76
 
77
  Args:
78
  query: The search query."""
79
+ print(f" executing search_web with query: {query}") # Added debug
80
+ # Use run() instead of invoke() for tool execution
81
+ try:
82
+ search_docs = TavilySearchResults(max_results=3).run(query)
83
+ print(f"DEBUG: search_docs type: {type(search_docs)}") # Added debug
84
+ print(f"DEBUG: search_docs content: {search_docs}") # Added debug
85
+ print(f"Found {len(search_docs)} documents for query '{query}'")
86
+ # Formatted search results
87
+ formatted_search_docs = "\n\n---\n\n".join(
88
+ [
89
+ f'<Document source="{doc.get("url", "unknown")}" page="{doc.get("page", "N/A")}"/>\n{doc.get("content", "")}\n</Document>'
90
+ for doc in search_docs
91
+ ]
92
+ )
93
+ if not formatted_search_docs:
94
+ print ("Empty search results")
95
+ return {"web_results": formatted_search_docs}
96
+ except Exception as e:
97
+ print(f"Error in search_web: {e}")
98
+ return {"web_results": f"Search error: {str(e)}"}
99
 
100
 
101
  # ArXiv search tool
102
  @tool
103
+ def search_arxiv(query: str) -> Dict[str, str]:
104
  """Search Arxiv for a query and return maximum 3 result.
105
 
106
  Args:
107
  query: The search query."""
108
+ print(f" executing search_arxiv with query: {query}") # Added debug
109
+ try:
110
+ search_docs = ArxivLoader(query=query, load_max_docs=3).load()
111
+ print(f"DEBUG: search_docs type: {type(search_docs)}") # Added debug
112
+ print(f"DEBUG: search_docs content: {search_docs}") # Added debug
113
+ print(f"Found {len(search_docs)} documents for query '{query}'") # Added debug
114
+ formatted_search_docs = "\n\n---\n\n".join(
115
+ [
116
+ f'<Document source="{get_arxiv_url(doc.page_content)}" page="{doc.metadata.get("page", "N/A")}"/>\n{doc.page_content[:1000]}\n</Document>'
117
+ for doc in search_docs
118
+ ]
119
+ )
120
+ if not formatted_search_docs:
121
+ print ("Empty search results") # Added debug
122
+ return {"arxiv_results": formatted_search_docs}
123
+ except Exception as e:
124
+ print(f"Error in search_arxiv: {e}") # Added debug
125
+ return {"arxiv_results": f"Search error: {str(e)}"}
126
 
127
 
128
  # build retriever
 
147
  model="gemini-2.5-flash-preview-04-17",
148
  temperature=0
149
  )
 
 
 
 
150
  print(f"DEBUG: llm object = {llm}")
151
 
152
  # bind tools to llm
 
196
 
197
 
198
  if __name__ == "__main__":
199
+ # Test query for search_arxiv tool
200
+ question = "latest research on quantum computing"
201
  graph = build_graph()
202
  messages = [HumanMessage(content=question)]
203
+ print(f"Running graph with question: {question}") # Added debug print
204
  messages = graph.invoke({"messages": messages})
205
+ print("Graph execution finished. Messages:") # Added debug print
206
  for m in messages["messages"]:
207
  m.pretty_print()
prompts.py CHANGED
@@ -1,19 +1,18 @@
1
  system_prompt = """You are a helpful assistant tasked with answering questions using a set of tools.
2
 
3
- Your final response must be presented in one single line, strictly following this exact format:
4
- FINAL ANSWER: [The concise answer to the user's question]
5
 
6
  Include only this line and nothing else in your final output.
7
 
8
- Examples of valid final responses:
9
- FINAL ANSWER: FunkMonk
10
- FINAL ANSWER: Paris
11
- FINAL ANSWER: 128
12
- FINAL ANSWER: 15 January 2001
13
 
14
- If the current question is identical to a question you have already answered, you must provide the stored final answer in the required "FINAL ANSWER: [ANSWER]" format. Do not use tools in this case.
15
 
16
- If the question is new or different, use your available tools to determine the answer, and then format that answer into the required "FINAL ANSWER: [ANSWER]" format.
17
 
18
- Strict adherence to the "FINAL ANSWER: [ANSWER]" format is mandatory for your response.
19
  """
 
1
  system_prompt = """You are a helpful assistant tasked with answering questions using a set of tools.
2
 
3
+ Your final response must be presented in one single line containing only the answer (no prefixes or formatting).
 
4
 
5
  Include only this line and nothing else in your final output.
6
 
7
+ Examples of valid responses:
8
+ FunkMonk
9
+ Paris
10
+ 128
11
+ 15 January 2001
12
 
13
+ If the current question is identical to a question you have already answered, return the stored answer directly without modification.
14
 
15
+ If the question is new or different, use your available tools to determine the answer, then return only the answer text.
16
 
17
+ Your answer must be concise and in the format requested, with no additional text or explanation.
18
  """
pyproject.toml CHANGED
@@ -5,6 +5,7 @@ description = "Huggingface agents course -- Final assignment"
5
  readme = "README.md"
6
  requires-python = ">=3.12"
7
  dependencies = [
 
8
  "dotenv>=0.9.9",
9
  "duckduckgo-search>=8.0.1",
10
  "gradio>=5.29.0",
@@ -16,6 +17,7 @@ dependencies = [
16
  "langchain-tools>=0.1.34",
17
  "langgraph>=0.4.3",
18
  "pandas>=2.2.3",
 
19
  "rank-bm25>=0.2.2",
20
  "requests>=2.32.3",
21
  "tavily-python>=0.7.2",
 
5
  readme = "README.md"
6
  requires-python = ">=3.12"
7
  dependencies = [
8
+ "arxiv>=2.2.0",
9
  "dotenv>=0.9.9",
10
  "duckduckgo-search>=8.0.1",
11
  "gradio>=5.29.0",
 
17
  "langchain-tools>=0.1.34",
18
  "langgraph>=0.4.3",
19
  "pandas>=2.2.3",
20
+ "pymupdf>=1.25.5",
21
  "rank-bm25>=0.2.2",
22
  "requests>=2.32.3",
23
  "tavily-python>=0.7.2",
uv.lock CHANGED
@@ -109,6 +109,19 @@ wheels = [
109
  { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916, upload-time = "2025-03-17T00:02:52.713Z" },
110
  ]
111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  [[package]]
113
  name = "attrs"
114
  version = "25.3.0"
@@ -339,6 +352,18 @@ wheels = [
339
  { url = "https://files.pythonhosted.org/packages/50/b3/b51f09c2ba432a576fe63758bddc81f78f0c6309d9e5c10d194313bf021e/fastapi-0.115.12-py3-none-any.whl", hash = "sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d", size = 95164, upload-time = "2025-03-23T22:55:42.101Z" },
340
  ]
341
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  [[package]]
343
  name = "ffmpy"
344
  version = "0.5.0"
@@ -686,6 +711,7 @@ name = "hfagentscourse-finalassignment"
686
  version = "0.1.0"
687
  source = { virtual = "." }
688
  dependencies = [
 
689
  { name = "dotenv" },
690
  { name = "duckduckgo-search" },
691
  { name = "gradio" },
@@ -697,6 +723,7 @@ dependencies = [
697
  { name = "langchain-tools" },
698
  { name = "langgraph" },
699
  { name = "pandas" },
 
700
  { name = "rank-bm25" },
701
  { name = "requests" },
702
  { name = "tavily-python" },
@@ -705,6 +732,7 @@ dependencies = [
705
 
706
  [package.metadata]
707
  requires-dist = [
 
708
  { name = "dotenv", specifier = ">=0.9.9" },
709
  { name = "duckduckgo-search", specifier = ">=8.0.1" },
710
  { name = "gradio", specifier = ">=5.29.0" },
@@ -716,6 +744,7 @@ requires-dist = [
716
  { name = "langchain-tools", specifier = ">=0.1.34" },
717
  { name = "langgraph", specifier = ">=0.4.3" },
718
  { name = "pandas", specifier = ">=2.2.3" },
 
719
  { name = "rank-bm25", specifier = ">=0.2.2" },
720
  { name = "requests", specifier = ">=2.32.3" },
721
  { name = "tavily-python", specifier = ">=0.7.2" },
@@ -1835,6 +1864,21 @@ wheels = [
1835
  { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" },
1836
  ]
1837
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1838
  [[package]]
1839
  name = "python-dateutil"
1840
  version = "2.9.0.post0"
@@ -2164,6 +2208,12 @@ wheels = [
2164
  { url = "https://files.pythonhosted.org/packages/b1/93/dba5ed08c2e31ec7cdc2ce75705a484ef0be1a2fecac8a58272489349de8/setuptools-80.4.0-py3-none-any.whl", hash = "sha256:6cdc8cb9a7d590b237dbe4493614a9b75d0559b888047c1f67d49ba50fc3edb2", size = 1200812, upload-time = "2025-05-09T20:42:25.325Z" },
2165
  ]
2166
 
 
 
 
 
 
 
2167
  [[package]]
2168
  name = "shellingham"
2169
  version = "1.5.4"
 
109
  { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916, upload-time = "2025-03-17T00:02:52.713Z" },
110
  ]
111
 
112
+ [[package]]
113
+ name = "arxiv"
114
+ version = "2.2.0"
115
+ source = { registry = "https://pypi.org/simple" }
116
+ dependencies = [
117
+ { name = "feedparser" },
118
+ { name = "requests" },
119
+ ]
120
+ sdist = { url = "https://files.pythonhosted.org/packages/0b/16/3d72446400a59d1fbda24fed2289661398994164e07d72cfa85e43ce5e36/arxiv-2.2.0.tar.gz", hash = "sha256:6072a2211e95697092ef32acde0144d7de2cfa71208e2751724316c9df322cc0", size = 16910, upload-time = "2025-04-08T06:16:09.824Z" }
121
+ wheels = [
122
+ { url = "https://files.pythonhosted.org/packages/71/1e/e7f0393e836b5347605fc356c24d9f9ae9b26e0f7e52573b80e3d28335eb/arxiv-2.2.0-py3-none-any.whl", hash = "sha256:545b8af5ab301efff7697cd112b5189e631b80521ccbc33fbc1e1f9cff63ca4d", size = 11696, upload-time = "2025-04-08T06:16:08.844Z" },
123
+ ]
124
+
125
  [[package]]
126
  name = "attrs"
127
  version = "25.3.0"
 
352
  { url = "https://files.pythonhosted.org/packages/50/b3/b51f09c2ba432a576fe63758bddc81f78f0c6309d9e5c10d194313bf021e/fastapi-0.115.12-py3-none-any.whl", hash = "sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d", size = 95164, upload-time = "2025-03-23T22:55:42.101Z" },
353
  ]
354
 
355
+ [[package]]
356
+ name = "feedparser"
357
+ version = "6.0.11"
358
+ source = { registry = "https://pypi.org/simple" }
359
+ dependencies = [
360
+ { name = "sgmllib3k" },
361
+ ]
362
+ sdist = { url = "https://files.pythonhosted.org/packages/ff/aa/7af346ebeb42a76bf108027fe7f3328bb4e57a3a96e53e21fd9ef9dd6dd0/feedparser-6.0.11.tar.gz", hash = "sha256:c9d0407b64c6f2a065d0ebb292c2b35c01050cc0dc33757461aaabdc4c4184d5", size = 286197, upload-time = "2023-12-10T16:03:20.854Z" }
363
+ wheels = [
364
+ { url = "https://files.pythonhosted.org/packages/7c/d4/8c31aad9cc18f451c49f7f9cfb5799dadffc88177f7917bc90a66459b1d7/feedparser-6.0.11-py3-none-any.whl", hash = "sha256:0be7ee7b395572b19ebeb1d6aafb0028dee11169f1c934e0ed67d54992f4ad45", size = 81343, upload-time = "2023-12-10T16:03:19.484Z" },
365
+ ]
366
+
367
  [[package]]
368
  name = "ffmpy"
369
  version = "0.5.0"
 
711
  version = "0.1.0"
712
  source = { virtual = "." }
713
  dependencies = [
714
+ { name = "arxiv" },
715
  { name = "dotenv" },
716
  { name = "duckduckgo-search" },
717
  { name = "gradio" },
 
723
  { name = "langchain-tools" },
724
  { name = "langgraph" },
725
  { name = "pandas" },
726
+ { name = "pymupdf" },
727
  { name = "rank-bm25" },
728
  { name = "requests" },
729
  { name = "tavily-python" },
 
732
 
733
  [package.metadata]
734
  requires-dist = [
735
+ { name = "arxiv", specifier = ">=2.2.0" },
736
  { name = "dotenv", specifier = ">=0.9.9" },
737
  { name = "duckduckgo-search", specifier = ">=8.0.1" },
738
  { name = "gradio", specifier = ">=5.29.0" },
 
744
  { name = "langchain-tools", specifier = ">=0.1.34" },
745
  { name = "langgraph", specifier = ">=0.4.3" },
746
  { name = "pandas", specifier = ">=2.2.3" },
747
+ { name = "pymupdf", specifier = ">=1.25.5" },
748
  { name = "rank-bm25", specifier = ">=0.2.2" },
749
  { name = "requests", specifier = ">=2.32.3" },
750
  { name = "tavily-python", specifier = ">=0.7.2" },
 
1864
  { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" },
1865
  ]
1866
 
1867
+ [[package]]
1868
+ name = "pymupdf"
1869
+ version = "1.25.5"
1870
+ source = { registry = "https://pypi.org/simple" }
1871
+ sdist = { url = "https://files.pythonhosted.org/packages/f9/af/3d5d363241b9a74470273cf1534436f13a0a61fc5ef6efd19e5afe9de812/pymupdf-1.25.5.tar.gz", hash = "sha256:5f96311cacd13254c905f6654a004a0a2025b71cabc04fda667f5472f72c15a0", size = 69812626, upload-time = "2025-03-31T23:22:13.891Z" }
1872
+ wheels = [
1873
+ { url = "https://files.pythonhosted.org/packages/85/5f/153d6c338291448e182648844849d13938a62a82a3e4a9b0907d9b381148/pymupdf-1.25.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cde4e1c9cfb09c0e1e9c2b7f4b787dd6bb34a32cfe141a4675e24af7c0c25dd3", size = 19364722, upload-time = "2025-03-31T23:18:04.729Z" },
1874
+ { url = "https://files.pythonhosted.org/packages/4e/55/43b64fa6cd048d2ea4574c045b5ac05d023254b91c2c703185f6f8a77b30/pymupdf-1.25.5-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:5a35e2725fae0ab57f058dff77615c15eb5961eac50ba04f41ebc792cd8facad", size = 18606161, upload-time = "2025-03-31T23:18:28.707Z" },
1875
+ { url = "https://files.pythonhosted.org/packages/8b/22/29edb3236aed2f99a7922699fd71183e2f6cdde3c3884670158ae4dcf3ea/pymupdf-1.25.5-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d94b800e9501929c42283d39bc241001dd87fdeea297b5cb40d5b5714534452f", size = 19467121, upload-time = "2025-04-01T09:31:13.172Z" },
1876
+ { url = "https://files.pythonhosted.org/packages/18/12/95e2ebe2933f94800fdeafd87bc281a790e1dc947b147c3d101df4f73703/pymupdf-1.25.5-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ee22155d3a634642d76553204867d862ae1bdd9f7cf70c0797d8127ebee6bed5", size = 20030310, upload-time = "2025-03-31T23:19:03.607Z" },
1877
+ { url = "https://files.pythonhosted.org/packages/bd/db/b4edec9e731ea7c2b74bf28b9091ed4e919d5c7f889ef86352b7fd416197/pymupdf-1.25.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6ed7fc25271004d6d3279c20a80cb2bb4cda3efa9f9088dcc07cd790eca0bc63", size = 21293562, upload-time = "2025-03-31T23:19:34.612Z" },
1878
+ { url = "https://files.pythonhosted.org/packages/ec/47/682a8ddce650e09f5de6809c9bce926b2493a19b7f9537d80d4646989670/pymupdf-1.25.5-cp39-abi3-win32.whl", hash = "sha256:65e18ddb37fe8ec4edcdbebe9be3a8486b6a2f42609d0a142677e42f3a0614f8", size = 15110464, upload-time = "2025-03-31T23:20:02.136Z" },
1879
+ { url = "https://files.pythonhosted.org/packages/71/c2/a9059607f80dcaf2392f991748cfc53456820392c0220cff02572653512a/pymupdf-1.25.5-cp39-abi3-win_amd64.whl", hash = "sha256:7f44bc3d03ea45b2f68c96464f96105e8c7908896f2fb5e8c04f1fb8dae7981e", size = 16579671, upload-time = "2025-03-31T23:20:25.793Z" },
1880
+ ]
1881
+
1882
  [[package]]
1883
  name = "python-dateutil"
1884
  version = "2.9.0.post0"
 
2208
  { url = "https://files.pythonhosted.org/packages/b1/93/dba5ed08c2e31ec7cdc2ce75705a484ef0be1a2fecac8a58272489349de8/setuptools-80.4.0-py3-none-any.whl", hash = "sha256:6cdc8cb9a7d590b237dbe4493614a9b75d0559b888047c1f67d49ba50fc3edb2", size = 1200812, upload-time = "2025-05-09T20:42:25.325Z" },
2209
  ]
2210
 
2211
+ [[package]]
2212
+ name = "sgmllib3k"
2213
+ version = "1.0.0"
2214
+ source = { registry = "https://pypi.org/simple" }
2215
+ sdist = { url = "https://files.pythonhosted.org/packages/9e/bd/3704a8c3e0942d711c1299ebf7b9091930adae6675d7c8f476a7ce48653c/sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9", size = 5750, upload-time = "2010-08-24T14:33:52.445Z" }
2216
+
2217
  [[package]]
2218
  name = "shellingham"
2219
  version = "1.5.4"