Humanlearning commited on
Commit
49f76f6
·
1 Parent(s): df075f4

research agent

Browse files
.gitignore CHANGED
@@ -1,2 +1,4 @@
1
  env*
2
- .venv
 
 
 
1
  env*
2
+ .venv
3
+
4
+ .cursor/*
__pycache__/agent.cpython-313.pyc ADDED
Binary file (6.08 kB). View file
 
agent.py CHANGED
@@ -2,65 +2,8 @@ from llama_index.llms.openai import OpenAI
2
  from tools.tavily_search_tool import search_web, record_notes, write_report, review_report
3
  from dotenv import load_dotenv
4
  import os
5
- load_dotenv()
6
-
7
- llm = OpenAI(model="gpt-4o", api_key=os.getenv("OPENAI_API_KEY"))
8
-
9
- from llama_index.core.agent.workflow import FunctionAgent, ReActAgent
10
-
11
- research_agent = FunctionAgent(
12
- name="ResearchAgent",
13
- description="Useful for searching the web for information on a given topic and recording notes on the topic.",
14
- system_prompt=(
15
- "You are the ResearchAgent that can search the web for information on a given topic and record notes on the topic. "
16
- "Once notes are recorded and you are satisfied, you should hand off control to the WriteAgent to write a report on the topic. "
17
- "You should have at least some notes on a topic before handing off control to the WriteAgent."
18
- ),
19
- llm=llm,
20
- tools=[search_web, record_notes],
21
- can_handoff_to=["WriteAgent"],
22
- )
23
-
24
- write_agent = FunctionAgent(
25
- name="WriteAgent",
26
- description="Useful for writing a report on a given topic.",
27
- system_prompt=(
28
- "You are the WriteAgent that can write a report on a given topic. "
29
- "Your report should be in a markdown format. The content should be grounded in the research notes. "
30
- "Once the report is written, you should get feedback at least once from the ReviewAgent."
31
- ),
32
- llm=llm,
33
- tools=[write_report],
34
- can_handoff_to=["ReviewAgent", "ResearchAgent"],
35
- )
36
-
37
- review_agent = FunctionAgent(
38
- name="ReviewAgent",
39
- description="Useful for reviewing a report and providing feedback.",
40
- system_prompt=(
41
- "You are the ReviewAgent that can review the write report and provide feedback. "
42
- "Your review should either approve the current report or request changes for the WriteAgent to implement. "
43
- "If you have feedback that requires changes, you should hand off control to the WriteAgent to implement the changes after submitting the review."
44
- ),
45
- llm=llm,
46
- tools=[review_report],
47
- can_handoff_to=["WriteAgent"],
48
- )
49
-
50
  from llama_index.core.agent.workflow import AgentWorkflow
51
-
52
- agent_workflow = AgentWorkflow(
53
- agents=[research_agent, write_agent, review_agent],
54
- root_agent=research_agent.name,
55
- initial_state={
56
- "research_notes": {},
57
- "report_content": "Not written yet.",
58
- "review": "Review required.",
59
- },
60
- )
61
-
62
-
63
- # As the workflow is running, we will stream the events to get an idea of what is happening under the hood.
64
  from llama_index.core.agent.workflow import (
65
  AgentInput,
66
  AgentOutput,
@@ -69,43 +12,101 @@ from llama_index.core.agent.workflow import (
69
  AgentStream,
70
  )
71
 
72
- handler = agent_workflow.run(
73
- user_msg=(
74
- "Write me a report on the history of the internet. "
75
- "Briefly describe the history of the internet, including the development of the internet, the development of the web, "
76
- "and the development of the internet in the 21st century."
77
- )
78
- )
 
 
 
 
 
 
 
 
 
 
 
79
 
80
- current_agent = None
81
- current_tool_calls = ""
82
- async for event in handler.stream_events():
83
- if (
84
- hasattr(event, "current_agent_name")
85
- and event.current_agent_name != current_agent
86
- ):
87
- current_agent = event.current_agent_name
88
- print(f"\n{'='*50}")
89
- print(f"🤖 Agent: {current_agent}")
90
- print(f"{'='*50}\n")
 
91
 
92
- # if isinstance(event, AgentStream):
93
- # if event.delta:
94
- # print(event.delta, end="", flush=True)
95
- # elif isinstance(event, AgentInput):
96
- # print("📥 Input:", event.input)
97
- elif isinstance(event, AgentOutput):
98
- if event.response.content:
99
- print("📤 Output:", event.response.content)
100
- if event.tool_calls:
101
- print(
102
- "🛠️ Planning to use tools:",
103
- [call.tool_name for call in event.tool_calls],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  )
105
- elif isinstance(event, ToolCallResult):
106
- print(f"🔧 Tool Result ({event.tool_name}):")
107
- print(f" Arguments: {event.tool_kwargs}")
108
- print(f" Output: {event.tool_output}")
109
- elif isinstance(event, ToolCall):
110
- print(f"🔨 Calling Tool: {event.tool_name}")
111
- print(f" With arguments: {event.tool_kwargs}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  from tools.tavily_search_tool import search_web, record_notes, write_report, review_report
3
  from dotenv import load_dotenv
4
  import os
5
+ from llama_index.core.agent.workflow import FunctionAgent
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  from llama_index.core.agent.workflow import AgentWorkflow
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  from llama_index.core.agent.workflow import (
8
  AgentInput,
9
  AgentOutput,
 
12
  AgentStream,
13
  )
14
 
15
+ load_dotenv(os.path.join(os.path.dirname(__file__), 'env.local'))
16
+
17
+ class TeacherStudentAgentWorkflow:
18
+ def __init__(self):
19
+ self.llm = OpenAI(model="gpt-4o-mini", api_key=os.getenv("OPENAI_API_KEY"))
20
+
21
+ self.research_agent = FunctionAgent(
22
+ name="ResearchAgent",
23
+ description="Useful for searching the web for information on a given topic and recording notes on the topic.",
24
+ system_prompt=(
25
+ "You are the ResearchAgent that can search the web for information on a given topic and record notes on the topic. "
26
+ "Once notes are recorded and you are satisfied, you should hand off control to the WriteAgent to write a report on the topic. "
27
+ "You should have at least some notes on a topic before handing off control to the WriteAgent."
28
+ ),
29
+ llm=self.llm,
30
+ tools=[search_web, record_notes],
31
+ can_handoff_to=["WriteAgent"],
32
+ )
33
 
34
+ self.write_agent = FunctionAgent(
35
+ name="WriteAgent",
36
+ description="Useful for writing a report on a given topic.",
37
+ system_prompt=(
38
+ "You are the WriteAgent that can write a report on a given topic. "
39
+ "Your report should be in a markdown format. The content should be grounded in the research notes. "
40
+ "Once the report is written, you should get feedback at least once from the ReviewAgent."
41
+ ),
42
+ llm=self.llm,
43
+ tools=[write_report],
44
+ can_handoff_to=["ReviewAgent", "ResearchAgent"],
45
+ )
46
 
47
+ self.review_agent = FunctionAgent(
48
+ name="ReviewAgent",
49
+ description="Useful for reviewing a report and providing feedback.",
50
+ system_prompt=(
51
+ "You are the ReviewAgent that can review the write report and provide feedback. "
52
+ "Your review should either approve the current report or request changes for the WriteAgent to implement. "
53
+ "If you have feedback that requires changes, you should hand off control to the WriteAgent to implement the changes after submitting the review."
54
+ ),
55
+ llm=self.llm,
56
+ tools=[review_report],
57
+ can_handoff_to=["WriteAgent"],
58
+ )
59
+
60
+ self.agent_workflow = AgentWorkflow(
61
+ agents=[self.research_agent, self.write_agent, self.review_agent],
62
+ root_agent=self.research_agent.name,
63
+ initial_state={
64
+ "research_notes": {},
65
+ "report_content": "Not written yet.",
66
+ "review": "Review required.",
67
+ },
68
+ )
69
+
70
+ async def run_workflow(self, user_msg=None):
71
+ if user_msg is None:
72
+ user_msg = (
73
+ "Write me a report on the history of the internet. "
74
+ "Briefly describe the history of the internet, including the development of the internet, the development of the web, "
75
+ "and the development of the internet in the 21st century."
76
  )
77
+ handler = self.agent_workflow.run(user_msg=user_msg)
78
+
79
+ current_agent = None
80
+ async for event in handler.stream_events():
81
+ if (
82
+ hasattr(event, "current_agent_name")
83
+ and event.current_agent_name != current_agent
84
+ ):
85
+ current_agent = event.current_agent_name
86
+ print(f"\n{'='*50}")
87
+ print(f"🤖 Agent: {current_agent}")
88
+ print(f"{'='*50}\n")
89
+
90
+ if isinstance(event, AgentOutput):
91
+ if event.response.content:
92
+ print("📤 Output:", event.response.content)
93
+ if event.tool_calls:
94
+ print(
95
+ "🛠️ Planning to use tools:",
96
+ [call.tool_name for call in event.tool_calls],
97
+ )
98
+ elif isinstance(event, ToolCallResult):
99
+ print(f"🔧 Tool Result ({event.tool_name}):")
100
+ print(f" Arguments: {event.tool_kwargs}")
101
+ print(f" Output: {event.tool_output}")
102
+ elif isinstance(event, ToolCall):
103
+ print(f"🔨 Calling Tool: {event.tool_name}")
104
+ print(f" With arguments: {event.tool_kwargs}")
105
+
106
+ if __name__ == "__main__":
107
+ import asyncio
108
+ agent = TeacherStudentAgentWorkflow()
109
+ user_msg = input("Enter the topic or instructions for the report (leave blank for default): ").strip()
110
+ if not user_msg:
111
+ user_msg = None
112
+ asyncio.run(agent.run_workflow(user_msg=user_msg))
app.py CHANGED
@@ -1,79 +1,237 @@
1
  import gradio as gr
2
  from gradio import ChatMessage
3
- import time
 
 
 
 
 
 
 
 
4
 
5
- def generate_response(history):
6
- history.append(
7
- ChatMessage(
8
- role="user", content="What is the weather in San Francisco right now?"
9
- )
10
- )
11
- yield history
12
- time.sleep(0.25)
13
- history.append(
14
- ChatMessage(
15
- role="assistant",
16
- content="In order to find the current weather in San Francisco, I will need to use my weather tool.",
17
- )
18
- )
19
- yield history
20
- time.sleep(0.25)
21
 
22
- history.append(
23
- ChatMessage(
24
- role="assistant",
25
- content="API Error when connecting to weather service.",
26
- metadata={"title": "💥 Error using tool 'Weather'"},
27
- )
28
- )
29
- yield history
30
- time.sleep(0.25)
31
 
32
- history.append(
33
- ChatMessage(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  role="assistant",
35
- content="I will try again",
 
36
  )
37
- )
38
- yield history
39
- time.sleep(0.25)
40
-
41
- history.append(
42
- ChatMessage(
43
  role="assistant",
44
- content="Weather 72 degrees Fahrenheit with 20% chance of rain.",
45
- metadata={"title": "🛠️ Used tool 'Weather'"},
46
  )
47
- )
48
- yield history
49
- time.sleep(0.25)
50
 
51
- history.append(
52
- ChatMessage(
53
- role="assistant",
54
- content="Now that the API succeeded I can complete my task.",
55
- )
56
- )
57
- yield history
58
- time.sleep(0.25)
59
 
60
- history.append(
61
- ChatMessage(
62
- role="assistant",
63
- content="It's a sunny day in San Francisco with a current temperature of 72 degrees Fahrenheit and a 20% chance of rain. Enjoy the weather!",
64
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  )
66
- yield history
67
-
68
- def like(evt: gr.LikeData):
69
- print("User liked the response")
70
- print(evt.index, evt.liked, evt.value)
71
-
72
- with gr.Blocks() as demo:
73
- chatbot = gr.Chatbot(type="messages", height=500, show_copy_button=True)
74
- button = gr.Button("Get San Francisco Weather")
75
- button.click(generate_response, chatbot, chatbot)
76
- chatbot.like(like)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
 
78
  if __name__ == "__main__":
79
  demo.launch()
 
1
  import gradio as gr
2
  from gradio import ChatMessage
3
+ import asyncio
4
+ from agent import TeacherStudentAgentWorkflow
5
+ from llama_index.core.agent.workflow import (
6
+ AgentInput,
7
+ AgentOutput,
8
+ ToolCall,
9
+ ToolCallResult,
10
+ AgentStream,
11
+ )
12
 
13
+ # Initialize the agent workflow
14
+ agent_workflow = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ def get_agent_workflow():
17
+ global agent_workflow
18
+ if agent_workflow is None:
19
+ agent_workflow = TeacherStudentAgentWorkflow()
20
+ return agent_workflow
 
 
 
 
21
 
22
+ async def chat_with_agent(message, history):
23
+ """
24
+ Async chat function that runs the agent workflow and streams each step.
25
+ """
26
+ if not message.strip():
27
+ yield history, None
28
+ return
29
+
30
+ # Add user message to history
31
+ history.append(ChatMessage(role="user", content=message))
32
+ yield history, None
33
+
34
+ try:
35
+ # Get the agent workflow
36
+ workflow = get_agent_workflow()
37
+
38
+ # Run the workflow with the user message
39
+ handler = workflow.agent_workflow.run(user_msg=message)
40
+
41
+ current_agent = None
42
+ current_step_messages = []
43
+ final_report = None
44
+ workflow_state = {}
45
+
46
+ async for event in handler.stream_events():
47
+ # Check if we switched to a new agent
48
+ if (
49
+ hasattr(event, "current_agent_name")
50
+ and event.current_agent_name != current_agent
51
+ ):
52
+ current_agent = event.current_agent_name
53
+
54
+ # Add agent header message
55
+ agent_header = ChatMessage(
56
+ role="assistant",
57
+ content=f"🤖 **{current_agent}** is now working...",
58
+ metadata={"title": f"Agent: {current_agent}"}
59
+ )
60
+ history.append(agent_header)
61
+ yield history, final_report
62
+
63
+ # Handle different event types
64
+ if isinstance(event, AgentOutput):
65
+ if event.response.content:
66
+ # Add agent output
67
+ output_msg = ChatMessage(
68
+ role="assistant",
69
+ content=f"📤 **Output:** {event.response.content}",
70
+ metadata={"title": f"{current_agent} - Output"}
71
+ )
72
+ history.append(output_msg)
73
+ yield history, final_report
74
+
75
+ if event.tool_calls:
76
+ # Show planned tools
77
+ tools_list = [call.tool_name for call in event.tool_calls]
78
+ tools_msg = ChatMessage(
79
+ role="assistant",
80
+ content=f"🛠️ **Planning to use tools:** {', '.join(tools_list)}",
81
+ metadata={"title": f"{current_agent} - Tool Planning"}
82
+ )
83
+ history.append(tools_msg)
84
+ yield history, final_report
85
+
86
+ elif isinstance(event, ToolCall):
87
+ # Show tool being called
88
+ tool_msg = ChatMessage(
89
+ role="assistant",
90
+ content=f"🔨 **Calling Tool:** {event.tool_name}\n**Arguments:** {event.tool_kwargs}",
91
+ metadata={"title": f"{current_agent} - Tool Call"}
92
+ )
93
+ history.append(tool_msg)
94
+ yield history, final_report
95
+
96
+ elif isinstance(event, ToolCallResult):
97
+ # Show tool results
98
+ result_content = str(event.tool_output)
99
+ if len(result_content) > 500:
100
+ result_content = result_content[:500] + "..."
101
+
102
+ result_msg = ChatMessage(
103
+ role="assistant",
104
+ content=f"🔧 **Tool Result ({event.tool_name}):**\n{result_content}",
105
+ metadata={"title": f"{current_agent} - Tool Result"}
106
+ )
107
+ history.append(result_msg)
108
+
109
+ # Track tool results to detect report writing and review approval
110
+ if event.tool_name == "write_report":
111
+ workflow_state["has_report"] = True
112
+ elif event.tool_name == "review_report" and current_agent == "ReviewAgent":
113
+ workflow_state["has_review"] = True
114
+ # Check if review indicates approval
115
+ if any(word in result_content.lower() for word in ["approved", "ready", "good", "excellent"]):
116
+ workflow_state["review_approved"] = True
117
+
118
+ yield history, final_report
119
+
120
+ # Get the final state to extract the report
121
+ try:
122
+ final_state = await handler.ctx.get("state")
123
+ if final_state and "report_content" in final_state:
124
+ report_content = final_state["report_content"]
125
+ if report_content and report_content != "Not written yet.":
126
+ # Show the final report if we have one and it's been reviewed
127
+ if workflow_state.get("has_report") and workflow_state.get("has_review"):
128
+ final_report = gr.Markdown(report_content, visible=True)
129
+ elif workflow_state.get("has_report"):
130
+ # Show report even if not reviewed yet
131
+ final_report = gr.Markdown(report_content, visible=True)
132
+ except Exception as state_error:
133
+ print(f"Could not extract final state: {state_error}")
134
+ # Try to show any report that was generated during the conversation
135
+ if workflow_state.get("has_report"):
136
+ final_report = gr.Markdown("Report was generated but could not be extracted from final state.", visible=True)
137
+
138
+ # Add completion message
139
+ completion_msg = ChatMessage(
140
  role="assistant",
141
+ content=" **Workflow completed!** The agent collaboration has finished.",
142
+ metadata={"title": "Workflow Complete"}
143
  )
144
+ history.append(completion_msg)
145
+ yield history, final_report
146
+
147
+ except Exception as e:
148
+ # Handle errors gracefully
149
+ error_msg = ChatMessage(
150
  role="assistant",
151
+ content=f" **Error:** {str(e)}",
152
+ metadata={"title": "Error"}
153
  )
154
+ history.append(error_msg)
155
+ yield history, None
 
156
 
157
+ def like_feedback(evt: gr.LikeData):
158
+ """Handle user feedback on messages."""
159
+ print(f"User feedback - Index: {evt.index}, Liked: {evt.liked}, Value: {evt.value}")
 
 
 
 
 
160
 
161
+ # Create the Gradio interface
162
+ with gr.Blocks(title="Teacher-Student Agent Workflow", theme=gr.themes.Soft()) as demo:
163
+ gr.Markdown("""
164
+ # 🤖 Teacher-Student Agent Workflow
165
+
166
+ This demo showcases a multi-agent workflow with three specialized agents:
167
+ - **ResearchAgent**: Searches the web and records notes
168
+ - **WriteAgent**: Writes reports based on research
169
+ - **ReviewAgent**: Reviews and provides feedback on reports
170
+
171
+ Enter a topic or request below to see the agents collaborate step by step!
172
+ """)
173
+
174
+ chatbot = gr.Chatbot(
175
+ type="messages",
176
+ height=600,
177
+ show_copy_button=True,
178
+ placeholder="<strong>Welcome to the Teacher-Student Agent Workflow!</strong><br>Ask me to write a report on any topic and watch the agents collaborate.",
179
+ render_markdown=True
180
  )
181
+
182
+ textbox = gr.Textbox(
183
+ placeholder="Enter your request (e.g., 'Write a report on artificial intelligence')",
184
+ container=False,
185
+ scale=7
186
+ )
187
+
188
+ # Create the final report output component
189
+ final_report_output = gr.Markdown(
190
+ label="📄 Final Approved Report",
191
+ visible=False,
192
+ render=False
193
+ )
194
+
195
+ # Set up the chat interface with additional outputs
196
+ chat_interface = gr.ChatInterface(
197
+ fn=chat_with_agent,
198
+ chatbot=chatbot,
199
+ textbox=textbox,
200
+ type="messages",
201
+ examples=[
202
+ "Write a report on the history of artificial intelligence",
203
+ "Create a report about renewable energy technologies",
204
+ "Write a report on the impact of social media on society",
205
+ "Generate a report about space exploration achievements"
206
+ ],
207
+ example_labels=[
208
+ "AI History Report",
209
+ "Renewable Energy Report",
210
+ "Social Media Impact Report",
211
+ "Space Exploration Report"
212
+ ],
213
+ cache_examples=False,
214
+ additional_outputs=[final_report_output]
215
+ )
216
+
217
+ # Add feedback handling
218
+ chatbot.like(like_feedback)
219
+
220
+ # Render the final report output in a separate section
221
+ with gr.Row():
222
+ with gr.Column():
223
+ gr.Markdown("### 📋 Final Report")
224
+ final_report_output.render()
225
+
226
+ gr.Markdown("""
227
+ ### How it works:
228
+ 1. **ResearchAgent** searches for information and takes notes
229
+ 2. **WriteAgent** creates a report based on the research
230
+ 3. **ReviewAgent** reviews the report and provides feedback
231
+ 4. The process continues until the report is approved
232
+
233
+ Watch the real-time collaboration between agents as they work together!
234
+ """)
235
 
236
  if __name__ == "__main__":
237
  demo.launch()
pyproject.toml CHANGED
@@ -5,7 +5,9 @@ description = "Add your description here"
5
  readme = "README.md"
6
  requires-python = ">=3.13"
7
  dependencies = [
 
8
  "dotenv>=0.9.9",
 
9
  "llama-index>=0.12.40",
10
  "tavily-python>=0.7.5",
11
  ]
 
5
  readme = "README.md"
6
  requires-python = ">=3.13"
7
  dependencies = [
8
+ "asyncio>=3.4.3",
9
  "dotenv>=0.9.9",
10
+ "gradio>=5.33.0",
11
  "llama-index>=0.12.40",
12
  "tavily-python>=0.7.5",
13
  ]
tools/__pycache__/__init__.cpython-313.pyc ADDED
Binary file (197 Bytes). View file
 
tools/__pycache__/tavily_search_tool.cpython-313.pyc ADDED
Binary file (2.66 kB). View file
 
tools/tavily_search_tool.py CHANGED
@@ -1,10 +1,13 @@
1
  from tavily import AsyncTavilyClient
2
  from llama_index.core.workflow import Context
 
 
3
 
 
4
 
5
  async def search_web(query: str) -> str:
6
  """Useful for using the web to answer questions."""
7
- client = AsyncTavilyClient(api_key="tvly-...")
8
  return str(await client.search(query))
9
 
10
 
 
1
  from tavily import AsyncTavilyClient
2
  from llama_index.core.workflow import Context
3
+ from dotenv import load_dotenv
4
+ import os
5
 
6
+ load_dotenv(os.path.join(os.path.dirname(__file__), '../env.local'))
7
 
8
  async def search_web(query: str) -> str:
9
  """Useful for using the web to answer questions."""
10
+ client = AsyncTavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
11
  return str(await client.search(query))
12
 
13
 
uv.lock CHANGED
@@ -2,6 +2,15 @@ version = 1
2
  revision = 1
3
  requires-python = ">=3.13"
4
 
 
 
 
 
 
 
 
 
 
5
  [[package]]
6
  name = "aiohappyeyeballs"
7
  version = "2.6.1"
@@ -90,6 +99,15 @@ wheels = [
90
  { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916 },
91
  ]
92
 
 
 
 
 
 
 
 
 
 
93
  [[package]]
94
  name = "attrs"
95
  version = "25.3.0"
@@ -99,6 +117,46 @@ wheels = [
99
  { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815 },
100
  ]
101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  [[package]]
103
  name = "banks"
104
  version = "2.1.2"
@@ -234,6 +292,38 @@ wheels = [
234
  { url = "https://files.pythonhosted.org/packages/b2/b7/545d2c10c1fc15e48653c91efde329a790f2eecfbbf2bd16003b5db2bab0/dotenv-0.9.9-py2.py3-none-any.whl", hash = "sha256:29cf74a087b31dafdb5a446b6d7e11cbce8ed2741540e2339c69fbef92c94ce9", size = 1892 },
235
  ]
236
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  [[package]]
238
  name = "filetype"
239
  version = "1.2.0"
@@ -295,6 +385,63 @@ wheels = [
295
  { url = "https://files.pythonhosted.org/packages/bb/61/78c7b3851add1481b048b5fdc29067397a1784e2910592bc81bb3f608635/fsspec-2025.5.1-py3-none-any.whl", hash = "sha256:24d3a2e663d5fc735ab256263c4075f374a174c3410c0b25e5bd1970bceaa462", size = 199052 },
296
  ]
297
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
298
  [[package]]
299
  name = "greenlet"
300
  version = "3.2.3"
@@ -331,6 +478,15 @@ wheels = [
331
  { url = "https://files.pythonhosted.org/packages/58/c6/5c20af38c2a57c15d87f7f38bee77d63c1d2a3689f74fefaf35915dd12b2/griffe-1.7.3-py3-none-any.whl", hash = "sha256:c6b3ee30c2f0f17f30bcdef5068d6ab7a2a4f1b8bf1a3e74b56fffd21e1c5f75", size = 129303 },
332
  ]
333
 
 
 
 
 
 
 
 
 
 
334
  [[package]]
335
  name = "h11"
336
  version = "0.16.0"
@@ -340,6 +496,21 @@ wheels = [
340
  { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515 },
341
  ]
342
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
343
  [[package]]
344
  name = "httpcore"
345
  version = "1.0.9"
@@ -368,6 +539,25 @@ wheels = [
368
  { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 },
369
  ]
370
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
  [[package]]
372
  name = "idna"
373
  version = "3.10"
@@ -672,6 +862,18 @@ wheels = [
672
  { url = "https://files.pythonhosted.org/packages/f3/d9/a375fe968789c874b2b47afd505a0ac3cf225077fb417d00ac43baf6e07d/llama_parse-0.6.30-py3-none-any.whl", hash = "sha256:f5969510cf01c2fda9832acb32086dac781729bee5768c21ad9b444420173948", size = 4944 },
673
  ]
674
 
 
 
 
 
 
 
 
 
 
 
 
 
675
  [[package]]
676
  name = "markupsafe"
677
  version = "3.0.2"
@@ -712,6 +914,15 @@ wheels = [
712
  { url = "https://files.pythonhosted.org/packages/34/75/51952c7b2d3873b44a0028b1bd26a25078c18f92f256608e8d1dc61b39fd/marshmallow-3.26.1-py3-none-any.whl", hash = "sha256:3350409f20a70a7e4e11a27661187b77cdcaeb20abca41c1454fe33636bea09c", size = 50878 },
713
  ]
714
 
 
 
 
 
 
 
 
 
 
715
  [[package]]
716
  name = "multidict"
717
  version = "6.4.4"
@@ -844,6 +1055,29 @@ wheels = [
844
  { url = "https://files.pythonhosted.org/packages/2a/10/f245db006a860dbc1f2e2c8382e0a1762c7753e7971ba43a1dc3f3ec1404/openai-1.84.0-py3-none-any.whl", hash = "sha256:7ec4436c3c933d68dc0f5a0cef0cb3dbc0864a54d62bddaf2ed5f3d521844711", size = 725512 },
845
  ]
846
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
847
  [[package]]
848
  name = "packaging"
849
  version = "25.0"
@@ -1003,6 +1237,24 @@ wheels = [
1003
  { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777 },
1004
  ]
1005
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1006
  [[package]]
1007
  name = "pypdf"
1008
  version = "5.6.0"
@@ -1033,6 +1285,15 @@ wheels = [
1033
  { url = "https://files.pythonhosted.org/packages/1e/18/98a99ad95133c6a6e2005fe89faedf294a748bd5dc803008059409ac9b1e/python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d", size = 20256 },
1034
  ]
1035
 
 
 
 
 
 
 
 
 
 
1036
  [[package]]
1037
  name = "pytz"
1038
  version = "2025.2"
@@ -1097,6 +1358,74 @@ wheels = [
1097
  { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 },
1098
  ]
1099
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1100
  [[package]]
1101
  name = "six"
1102
  version = "1.17.0"
@@ -1150,6 +1479,18 @@ asyncio = [
1150
  { name = "greenlet" },
1151
  ]
1152
 
 
 
 
 
 
 
 
 
 
 
 
 
1153
  [[package]]
1154
  name = "striprtf"
1155
  version = "0.0.26"
@@ -1178,14 +1519,18 @@ name = "teacher-student-agent"
1178
  version = "0.1.0"
1179
  source = { virtual = "." }
1180
  dependencies = [
 
1181
  { name = "dotenv" },
 
1182
  { name = "llama-index" },
1183
  { name = "tavily-python" },
1184
  ]
1185
 
1186
  [package.metadata]
1187
  requires-dist = [
 
1188
  { name = "dotenv", specifier = ">=0.9.9" },
 
1189
  { name = "llama-index", specifier = ">=0.12.40" },
1190
  { name = "tavily-python", specifier = ">=0.7.5" },
1191
  ]
@@ -1217,6 +1562,15 @@ wheels = [
1217
  { url = "https://files.pythonhosted.org/packages/de/a8/8f499c179ec900783ffe133e9aab10044481679bb9aad78436d239eee716/tiktoken-0.9.0-cp313-cp313-win_amd64.whl", hash = "sha256:5ea0edb6f83dc56d794723286215918c1cde03712cbbafa0348b33448faf5b95", size = 894669 },
1218
  ]
1219
 
 
 
 
 
 
 
 
 
 
1220
  [[package]]
1221
  name = "tqdm"
1222
  version = "4.67.1"
@@ -1229,6 +1583,21 @@ wheels = [
1229
  { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540 },
1230
  ]
1231
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1232
  [[package]]
1233
  name = "typing-extensions"
1234
  version = "4.14.0"
@@ -1281,6 +1650,39 @@ wheels = [
1281
  { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680 },
1282
  ]
1283
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1284
  [[package]]
1285
  name = "wrapt"
1286
  version = "1.17.2"
 
2
  revision = 1
3
  requires-python = ">=3.13"
4
 
5
+ [[package]]
6
+ name = "aiofiles"
7
+ version = "24.1.0"
8
+ source = { registry = "https://pypi.org/simple" }
9
+ sdist = { url = "https://files.pythonhosted.org/packages/0b/03/a88171e277e8caa88a4c77808c20ebb04ba74cc4681bf1e9416c862de237/aiofiles-24.1.0.tar.gz", hash = "sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c", size = 30247 }
10
+ wheels = [
11
+ { url = "https://files.pythonhosted.org/packages/a5/45/30bb92d442636f570cb5651bc661f52b610e2eec3f891a5dc3a4c3667db0/aiofiles-24.1.0-py3-none-any.whl", hash = "sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5", size = 15896 },
12
+ ]
13
+
14
  [[package]]
15
  name = "aiohappyeyeballs"
16
  version = "2.6.1"
 
99
  { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916 },
100
  ]
101
 
102
+ [[package]]
103
+ name = "asyncio"
104
+ version = "3.4.3"
105
+ source = { registry = "https://pypi.org/simple" }
106
+ sdist = { url = "https://files.pythonhosted.org/packages/da/54/054bafaf2c0fb8473d423743e191fcdf49b2c1fd5e9af3524efbe097bafd/asyncio-3.4.3.tar.gz", hash = "sha256:83360ff8bc97980e4ff25c964c7bd3923d333d177aa4f7fb736b019f26c7cb41", size = 204411 }
107
+ wheels = [
108
+ { url = "https://files.pythonhosted.org/packages/22/74/07679c5b9f98a7cb0fc147b1ef1cc1853bc07a4eb9cb5731e24732c5f773/asyncio-3.4.3-py3-none-any.whl", hash = "sha256:c4d18b22701821de07bd6aea8b53d21449ec0ec5680645e5317062ea21817d2d", size = 101767 },
109
+ ]
110
+
111
  [[package]]
112
  name = "attrs"
113
  version = "25.3.0"
 
117
  { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815 },
118
  ]
119
 
120
+ [[package]]
121
+ name = "audioop-lts"
122
+ version = "0.2.1"
123
+ source = { registry = "https://pypi.org/simple" }
124
+ sdist = { url = "https://files.pythonhosted.org/packages/dd/3b/69ff8a885e4c1c42014c2765275c4bd91fe7bc9847e9d8543dbcbb09f820/audioop_lts-0.2.1.tar.gz", hash = "sha256:e81268da0baa880431b68b1308ab7257eb33f356e57a5f9b1f915dfb13dd1387", size = 30204 }
125
+ wheels = [
126
+ { url = "https://files.pythonhosted.org/packages/01/91/a219253cc6e92db2ebeaf5cf8197f71d995df6f6b16091d1f3ce62cb169d/audioop_lts-0.2.1-cp313-abi3-macosx_10_13_universal2.whl", hash = "sha256:fd1345ae99e17e6910f47ce7d52673c6a1a70820d78b67de1b7abb3af29c426a", size = 46252 },
127
+ { url = "https://files.pythonhosted.org/packages/ec/f6/3cb21e0accd9e112d27cee3b1477cd04dafe88675c54ad8b0d56226c1e0b/audioop_lts-0.2.1-cp313-abi3-macosx_10_13_x86_64.whl", hash = "sha256:e175350da05d2087e12cea8e72a70a1a8b14a17e92ed2022952a4419689ede5e", size = 27183 },
128
+ { url = "https://files.pythonhosted.org/packages/ea/7e/f94c8a6a8b2571694375b4cf94d3e5e0f529e8e6ba280fad4d8c70621f27/audioop_lts-0.2.1-cp313-abi3-macosx_11_0_arm64.whl", hash = "sha256:4a8dd6a81770f6ecf019c4b6d659e000dc26571b273953cef7cd1d5ce2ff3ae6", size = 26726 },
129
+ { url = "https://files.pythonhosted.org/packages/ef/f8/a0e8e7a033b03fae2b16bc5aa48100b461c4f3a8a38af56d5ad579924a3a/audioop_lts-0.2.1-cp313-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1cd3c0b6f2ca25c7d2b1c3adeecbe23e65689839ba73331ebc7d893fcda7ffe", size = 80718 },
130
+ { url = "https://files.pythonhosted.org/packages/8f/ea/a98ebd4ed631c93b8b8f2368862cd8084d75c77a697248c24437c36a6f7e/audioop_lts-0.2.1-cp313-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff3f97b3372c97782e9c6d3d7fdbe83bce8f70de719605bd7ee1839cd1ab360a", size = 88326 },
131
+ { url = "https://files.pythonhosted.org/packages/33/79/e97a9f9daac0982aa92db1199339bd393594d9a4196ad95ae088635a105f/audioop_lts-0.2.1-cp313-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a351af79edefc2a1bd2234bfd8b339935f389209943043913a919df4b0f13300", size = 80539 },
132
+ { url = "https://files.pythonhosted.org/packages/b2/d3/1051d80e6f2d6f4773f90c07e73743a1e19fcd31af58ff4e8ef0375d3a80/audioop_lts-0.2.1-cp313-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aeb6f96f7f6da80354330470b9134d81b4cf544cdd1c549f2f45fe964d28059", size = 78577 },
133
+ { url = "https://files.pythonhosted.org/packages/7a/1d/54f4c58bae8dc8c64a75071c7e98e105ddaca35449376fcb0180f6e3c9df/audioop_lts-0.2.1-cp313-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c589f06407e8340e81962575fcffbba1e92671879a221186c3d4662de9fe804e", size = 82074 },
134
+ { url = "https://files.pythonhosted.org/packages/36/89/2e78daa7cebbea57e72c0e1927413be4db675548a537cfba6a19040d52fa/audioop_lts-0.2.1-cp313-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fbae5d6925d7c26e712f0beda5ed69ebb40e14212c185d129b8dfbfcc335eb48", size = 84210 },
135
+ { url = "https://files.pythonhosted.org/packages/a5/57/3ff8a74df2ec2fa6d2ae06ac86e4a27d6412dbb7d0e0d41024222744c7e0/audioop_lts-0.2.1-cp313-abi3-musllinux_1_2_i686.whl", hash = "sha256:d2d5434717f33117f29b5691fbdf142d36573d751716249a288fbb96ba26a281", size = 85664 },
136
+ { url = "https://files.pythonhosted.org/packages/16/01/21cc4e5878f6edbc8e54be4c108d7cb9cb6202313cfe98e4ece6064580dd/audioop_lts-0.2.1-cp313-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:f626a01c0a186b08f7ff61431c01c055961ee28769591efa8800beadd27a2959", size = 93255 },
137
+ { url = "https://files.pythonhosted.org/packages/3e/28/7f7418c362a899ac3b0bf13b1fde2d4ffccfdeb6a859abd26f2d142a1d58/audioop_lts-0.2.1-cp313-abi3-musllinux_1_2_s390x.whl", hash = "sha256:05da64e73837f88ee5c6217d732d2584cf638003ac72df124740460531e95e47", size = 87760 },
138
+ { url = "https://files.pythonhosted.org/packages/6d/d8/577a8be87dc7dd2ba568895045cee7d32e81d85a7e44a29000fe02c4d9d4/audioop_lts-0.2.1-cp313-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:56b7a0a4dba8e353436f31a932f3045d108a67b5943b30f85a5563f4d8488d77", size = 84992 },
139
+ { url = "https://files.pythonhosted.org/packages/ef/9a/4699b0c4fcf89936d2bfb5425f55f1a8b86dff4237cfcc104946c9cd9858/audioop_lts-0.2.1-cp313-abi3-win32.whl", hash = "sha256:6e899eb8874dc2413b11926b5fb3857ec0ab55222840e38016a6ba2ea9b7d5e3", size = 26059 },
140
+ { url = "https://files.pythonhosted.org/packages/3a/1c/1f88e9c5dd4785a547ce5fd1eb83fff832c00cc0e15c04c1119b02582d06/audioop_lts-0.2.1-cp313-abi3-win_amd64.whl", hash = "sha256:64562c5c771fb0a8b6262829b9b4f37a7b886c01b4d3ecdbae1d629717db08b4", size = 30412 },
141
+ { url = "https://files.pythonhosted.org/packages/c4/e9/c123fd29d89a6402ad261516f848437472ccc602abb59bba522af45e281b/audioop_lts-0.2.1-cp313-abi3-win_arm64.whl", hash = "sha256:c45317debeb64002e980077642afbd977773a25fa3dfd7ed0c84dccfc1fafcb0", size = 23578 },
142
+ { url = "https://files.pythonhosted.org/packages/7a/99/bb664a99561fd4266687e5cb8965e6ec31ba4ff7002c3fce3dc5ef2709db/audioop_lts-0.2.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:3827e3fce6fee4d69d96a3d00cd2ab07f3c0d844cb1e44e26f719b34a5b15455", size = 46827 },
143
+ { url = "https://files.pythonhosted.org/packages/c4/e3/f664171e867e0768ab982715e744430cf323f1282eb2e11ebfb6ee4c4551/audioop_lts-0.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:161249db9343b3c9780ca92c0be0d1ccbfecdbccac6844f3d0d44b9c4a00a17f", size = 27479 },
144
+ { url = "https://files.pythonhosted.org/packages/a6/0d/2a79231ff54eb20e83b47e7610462ad6a2bea4e113fae5aa91c6547e7764/audioop_lts-0.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5b7b4ff9de7a44e0ad2618afdc2ac920b91f4a6d3509520ee65339d4acde5abf", size = 27056 },
145
+ { url = "https://files.pythonhosted.org/packages/86/46/342471398283bb0634f5a6df947806a423ba74b2e29e250c7ec0e3720e4f/audioop_lts-0.2.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72e37f416adb43b0ced93419de0122b42753ee74e87070777b53c5d2241e7fab", size = 87802 },
146
+ { url = "https://files.pythonhosted.org/packages/56/44/7a85b08d4ed55517634ff19ddfbd0af05bf8bfd39a204e4445cd0e6f0cc9/audioop_lts-0.2.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:534ce808e6bab6adb65548723c8cbe189a3379245db89b9d555c4210b4aaa9b6", size = 95016 },
147
+ { url = "https://files.pythonhosted.org/packages/a8/2a/45edbca97ea9ee9e6bbbdb8d25613a36e16a4d1e14ae01557392f15cc8d3/audioop_lts-0.2.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2de9b6fb8b1cf9f03990b299a9112bfdf8b86b6987003ca9e8a6c4f56d39543", size = 87394 },
148
+ { url = "https://files.pythonhosted.org/packages/14/ae/832bcbbef2c510629593bf46739374174606e25ac7d106b08d396b74c964/audioop_lts-0.2.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f24865991b5ed4b038add5edbf424639d1358144f4e2a3e7a84bc6ba23e35074", size = 84874 },
149
+ { url = "https://files.pythonhosted.org/packages/26/1c/8023c3490798ed2f90dfe58ec3b26d7520a243ae9c0fc751ed3c9d8dbb69/audioop_lts-0.2.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bdb3b7912ccd57ea53197943f1bbc67262dcf29802c4a6df79ec1c715d45a78", size = 88698 },
150
+ { url = "https://files.pythonhosted.org/packages/2c/db/5379d953d4918278b1f04a5a64b2c112bd7aae8f81021009da0dcb77173c/audioop_lts-0.2.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:120678b208cca1158f0a12d667af592e067f7a50df9adc4dc8f6ad8d065a93fb", size = 90401 },
151
+ { url = "https://files.pythonhosted.org/packages/99/6e/3c45d316705ab1aec2e69543a5b5e458d0d112a93d08994347fafef03d50/audioop_lts-0.2.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:54cd4520fc830b23c7d223693ed3e1b4d464997dd3abc7c15dce9a1f9bd76ab2", size = 91864 },
152
+ { url = "https://files.pythonhosted.org/packages/08/58/6a371d8fed4f34debdb532c0b00942a84ebf3e7ad368e5edc26931d0e251/audioop_lts-0.2.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:d6bd20c7a10abcb0fb3d8aaa7508c0bf3d40dfad7515c572014da4b979d3310a", size = 98796 },
153
+ { url = "https://files.pythonhosted.org/packages/ee/77/d637aa35497e0034ff846fd3330d1db26bc6fd9dd79c406e1341188b06a2/audioop_lts-0.2.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:f0ed1ad9bd862539ea875fb339ecb18fcc4148f8d9908f4502df28f94d23491a", size = 94116 },
154
+ { url = "https://files.pythonhosted.org/packages/1a/60/7afc2abf46bbcf525a6ebc0305d85ab08dc2d1e2da72c48dbb35eee5b62c/audioop_lts-0.2.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e1af3ff32b8c38a7d900382646e91f2fc515fd19dea37e9392275a5cbfdbff63", size = 91520 },
155
+ { url = "https://files.pythonhosted.org/packages/65/6d/42d40da100be1afb661fd77c2b1c0dfab08af1540df57533621aea3db52a/audioop_lts-0.2.1-cp313-cp313t-win32.whl", hash = "sha256:f51bb55122a89f7a0817d7ac2319744b4640b5b446c4c3efcea5764ea99ae509", size = 26482 },
156
+ { url = "https://files.pythonhosted.org/packages/01/09/f08494dca79f65212f5b273aecc5a2f96691bf3307cac29acfcf84300c01/audioop_lts-0.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f0f2f336aa2aee2bce0b0dcc32bbba9178995454c7b979cf6ce086a8801e14c7", size = 30780 },
157
+ { url = "https://files.pythonhosted.org/packages/5d/35/be73b6015511aa0173ec595fc579133b797ad532996f2998fd6b8d1bbe6b/audioop_lts-0.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:78bfb3703388c780edf900be66e07de5a3d4105ca8e8720c5c4d67927e0b15d0", size = 23918 },
158
+ ]
159
+
160
  [[package]]
161
  name = "banks"
162
  version = "2.1.2"
 
292
  { url = "https://files.pythonhosted.org/packages/b2/b7/545d2c10c1fc15e48653c91efde329a790f2eecfbbf2bd16003b5db2bab0/dotenv-0.9.9-py2.py3-none-any.whl", hash = "sha256:29cf74a087b31dafdb5a446b6d7e11cbce8ed2741540e2339c69fbef92c94ce9", size = 1892 },
293
  ]
294
 
295
+ [[package]]
296
+ name = "fastapi"
297
+ version = "0.115.12"
298
+ source = { registry = "https://pypi.org/simple" }
299
+ dependencies = [
300
+ { name = "pydantic" },
301
+ { name = "starlette" },
302
+ { name = "typing-extensions" },
303
+ ]
304
+ sdist = { url = "https://files.pythonhosted.org/packages/f4/55/ae499352d82338331ca1e28c7f4a63bfd09479b16395dce38cf50a39e2c2/fastapi-0.115.12.tar.gz", hash = "sha256:1e2c2a2646905f9e83d32f04a3f86aff4a286669c6c950ca95b5fd68c2602681", size = 295236 }
305
+ wheels = [
306
+ { url = "https://files.pythonhosted.org/packages/50/b3/b51f09c2ba432a576fe63758bddc81f78f0c6309d9e5c10d194313bf021e/fastapi-0.115.12-py3-none-any.whl", hash = "sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d", size = 95164 },
307
+ ]
308
+
309
+ [[package]]
310
+ name = "ffmpy"
311
+ version = "0.6.0"
312
+ source = { registry = "https://pypi.org/simple" }
313
+ sdist = { url = "https://files.pythonhosted.org/packages/38/0d/5d2411c1db5d734fbbc547d1049c679536513cea2c97124b3b90228dfb41/ffmpy-0.6.0.tar.gz", hash = "sha256:332dd93198a162db61e527e866a04578d3713e577bfe68f2ed26ba9d09dbc948", size = 4955 }
314
+ wheels = [
315
+ { url = "https://files.pythonhosted.org/packages/cb/2f/932f05d6c63e206baf1cb8ad6034f6eac6fe8dfdae86a74044216d4987fc/ffmpy-0.6.0-py3-none-any.whl", hash = "sha256:c8369bf45f8bd5285ebad94c4a789a79e7af86eded74c1f8c36eccf57aaea58c", size = 5513 },
316
+ ]
317
+
318
+ [[package]]
319
+ name = "filelock"
320
+ version = "3.18.0"
321
+ source = { registry = "https://pypi.org/simple" }
322
+ sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075 }
323
+ wheels = [
324
+ { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215 },
325
+ ]
326
+
327
  [[package]]
328
  name = "filetype"
329
  version = "1.2.0"
 
385
  { url = "https://files.pythonhosted.org/packages/bb/61/78c7b3851add1481b048b5fdc29067397a1784e2910592bc81bb3f608635/fsspec-2025.5.1-py3-none-any.whl", hash = "sha256:24d3a2e663d5fc735ab256263c4075f374a174c3410c0b25e5bd1970bceaa462", size = 199052 },
386
  ]
387
 
388
+ [[package]]
389
+ name = "gradio"
390
+ version = "5.33.0"
391
+ source = { registry = "https://pypi.org/simple" }
392
+ dependencies = [
393
+ { name = "aiofiles" },
394
+ { name = "anyio" },
395
+ { name = "audioop-lts" },
396
+ { name = "fastapi" },
397
+ { name = "ffmpy" },
398
+ { name = "gradio-client" },
399
+ { name = "groovy" },
400
+ { name = "httpx" },
401
+ { name = "huggingface-hub" },
402
+ { name = "jinja2" },
403
+ { name = "markupsafe" },
404
+ { name = "numpy" },
405
+ { name = "orjson" },
406
+ { name = "packaging" },
407
+ { name = "pandas" },
408
+ { name = "pillow" },
409
+ { name = "pydantic" },
410
+ { name = "pydub" },
411
+ { name = "python-multipart" },
412
+ { name = "pyyaml" },
413
+ { name = "ruff", marker = "sys_platform != 'emscripten'" },
414
+ { name = "safehttpx" },
415
+ { name = "semantic-version" },
416
+ { name = "starlette", marker = "sys_platform != 'emscripten'" },
417
+ { name = "tomlkit" },
418
+ { name = "typer", marker = "sys_platform != 'emscripten'" },
419
+ { name = "typing-extensions" },
420
+ { name = "urllib3", marker = "sys_platform == 'emscripten'" },
421
+ { name = "uvicorn", marker = "sys_platform != 'emscripten'" },
422
+ ]
423
+ sdist = { url = "https://files.pythonhosted.org/packages/b0/97/908eb543fbce7c69250d6fbe87b6ccf4ce397d31bceb360b40316357c68c/gradio-5.33.0.tar.gz", hash = "sha256:0cba3a1596fda6cb0048dd7ddc2d57e6238a047c0df9dee5a4a0e5c2a74e8e50", size = 64888401 }
424
+ wheels = [
425
+ { url = "https://files.pythonhosted.org/packages/4f/c3/c9b09b8d7efd63d83a9c8d9c53b02e1b77238e14305a7ee561e0a8990465/gradio-5.33.0-py3-none-any.whl", hash = "sha256:165e412e1510a22471901744722f99a52cb56465a7e9609f1e400cac9999e9d8", size = 54208887 },
426
+ ]
427
+
428
+ [[package]]
429
+ name = "gradio-client"
430
+ version = "1.10.2"
431
+ source = { registry = "https://pypi.org/simple" }
432
+ dependencies = [
433
+ { name = "fsspec" },
434
+ { name = "httpx" },
435
+ { name = "huggingface-hub" },
436
+ { name = "packaging" },
437
+ { name = "typing-extensions" },
438
+ { name = "websockets" },
439
+ ]
440
+ sdist = { url = "https://files.pythonhosted.org/packages/d2/86/6684afe8691b024200fdc8983924f04b5f76bb401b9c700e5752a23595a0/gradio_client-1.10.2.tar.gz", hash = "sha256:bf71ba95714784fa77ca0cfb20189ad91c55e563c2dc71722d023a97f1815d7f", size = 321294 }
441
+ wheels = [
442
+ { url = "https://files.pythonhosted.org/packages/9b/1b/b372308c263379ae3ebc440512432979458330113bdee26cef86c89bf48e/gradio_client-1.10.2-py3-none-any.whl", hash = "sha256:6de67b6224123d264c7887caa0586b2a9e2c369ec32ca38927cf8a841694edcd", size = 323311 },
443
+ ]
444
+
445
  [[package]]
446
  name = "greenlet"
447
  version = "3.2.3"
 
478
  { url = "https://files.pythonhosted.org/packages/58/c6/5c20af38c2a57c15d87f7f38bee77d63c1d2a3689f74fefaf35915dd12b2/griffe-1.7.3-py3-none-any.whl", hash = "sha256:c6b3ee30c2f0f17f30bcdef5068d6ab7a2a4f1b8bf1a3e74b56fffd21e1c5f75", size = 129303 },
479
  ]
480
 
481
+ [[package]]
482
+ name = "groovy"
483
+ version = "0.1.2"
484
+ source = { registry = "https://pypi.org/simple" }
485
+ sdist = { url = "https://files.pythonhosted.org/packages/52/36/bbdede67400277bef33d3ec0e6a31750da972c469f75966b4930c753218f/groovy-0.1.2.tar.gz", hash = "sha256:25c1dc09b3f9d7e292458aa762c6beb96ea037071bf5e917fc81fb78d2231083", size = 17325 }
486
+ wheels = [
487
+ { url = "https://files.pythonhosted.org/packages/28/27/3d6dcadc8a3214d8522c1e7f6a19554e33659be44546d44a2f7572ac7d2a/groovy-0.1.2-py3-none-any.whl", hash = "sha256:7f7975bab18c729a257a8b1ae9dcd70b7cafb1720481beae47719af57c35fa64", size = 14090 },
488
+ ]
489
+
490
  [[package]]
491
  name = "h11"
492
  version = "0.16.0"
 
496
  { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515 },
497
  ]
498
 
499
+ [[package]]
500
+ name = "hf-xet"
501
+ version = "1.1.3"
502
+ source = { registry = "https://pypi.org/simple" }
503
+ sdist = { url = "https://files.pythonhosted.org/packages/75/dc/dc091aeeb671e71cbec30e84963f9c0202c17337b24b0a800e7d205543e8/hf_xet-1.1.3.tar.gz", hash = "sha256:a5f09b1dd24e6ff6bcedb4b0ddab2d81824098bb002cf8b4ffa780545fa348c3", size = 488127 }
504
+ wheels = [
505
+ { url = "https://files.pythonhosted.org/packages/9b/1f/bc01a4c0894973adebbcd4aa338a06815c76333ebb3921d94dcbd40dae6a/hf_xet-1.1.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:c3b508b5f583a75641aebf732853deb058953370ce8184f5dabc49f803b0819b", size = 2256929 },
506
+ { url = "https://files.pythonhosted.org/packages/78/07/6ef50851b5c6b45b77a6e018fa299c69a2db3b8bbd0d5af594c0238b1ceb/hf_xet-1.1.3-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:b788a61977fbe6b5186e66239e2a329a3f0b7e7ff50dad38984c0c74f44aeca1", size = 2153719 },
507
+ { url = "https://files.pythonhosted.org/packages/52/48/e929e6e3db6e4758c2adf0f2ca2c59287f1b76229d8bdc1a4c9cfc05212e/hf_xet-1.1.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd2da210856444a34aad8ada2fc12f70dabed7cc20f37e90754d1d9b43bc0534", size = 4820519 },
508
+ { url = "https://files.pythonhosted.org/packages/28/2e/03f89c5014a5aafaa9b150655f811798a317036646623bdaace25f485ae8/hf_xet-1.1.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8203f52827e3df65981984936654a5b390566336956f65765a8aa58c362bb841", size = 4964121 },
509
+ { url = "https://files.pythonhosted.org/packages/47/8b/5cd399a92b47d98086f55fc72d69bc9ea5e5c6f27a9ed3e0cdd6be4e58a3/hf_xet-1.1.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:30c575a5306f8e6fda37edb866762140a435037365eba7a17ce7bd0bc0216a8b", size = 5283017 },
510
+ { url = "https://files.pythonhosted.org/packages/53/e3/2fcec58d2fcfd25ff07feb876f466cfa11f8dcf9d3b742c07fe9dd51ee0a/hf_xet-1.1.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7c1a6aa6abed1f696f8099aa9796ca04c9ee778a58728a115607de9cc4638ff1", size = 4970349 },
511
+ { url = "https://files.pythonhosted.org/packages/53/bf/10ca917e335861101017ff46044c90e517b574fbb37219347b83be1952f6/hf_xet-1.1.3-cp37-abi3-win_amd64.whl", hash = "sha256:b578ae5ac9c056296bb0df9d018e597c8dc6390c5266f35b5c44696003cde9f3", size = 2310934 },
512
+ ]
513
+
514
  [[package]]
515
  name = "httpcore"
516
  version = "1.0.9"
 
539
  { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 },
540
  ]
541
 
542
+ [[package]]
543
+ name = "huggingface-hub"
544
+ version = "0.32.4"
545
+ source = { registry = "https://pypi.org/simple" }
546
+ dependencies = [
547
+ { name = "filelock" },
548
+ { name = "fsspec" },
549
+ { name = "hf-xet", marker = "platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" },
550
+ { name = "packaging" },
551
+ { name = "pyyaml" },
552
+ { name = "requests" },
553
+ { name = "tqdm" },
554
+ { name = "typing-extensions" },
555
+ ]
556
+ sdist = { url = "https://files.pythonhosted.org/packages/60/c8/4f7d270285c46324fd66f62159eb16739aa5696f422dba57678a8c6b78e9/huggingface_hub-0.32.4.tar.gz", hash = "sha256:f61d45cd338736f59fb0e97550b74c24ee771bcc92c05ae0766b9116abe720be", size = 424494 }
557
+ wheels = [
558
+ { url = "https://files.pythonhosted.org/packages/67/8b/222140f3cfb6f17b0dd8c4b9a0b36bd4ebefe9fb0098ba35d6960abcda0f/huggingface_hub-0.32.4-py3-none-any.whl", hash = "sha256:37abf8826b38d971f60d3625229221c36e53fe58060286db9baf619cfbf39767", size = 512101 },
559
+ ]
560
+
561
  [[package]]
562
  name = "idna"
563
  version = "3.10"
 
862
  { url = "https://files.pythonhosted.org/packages/f3/d9/a375fe968789c874b2b47afd505a0ac3cf225077fb417d00ac43baf6e07d/llama_parse-0.6.30-py3-none-any.whl", hash = "sha256:f5969510cf01c2fda9832acb32086dac781729bee5768c21ad9b444420173948", size = 4944 },
863
  ]
864
 
865
+ [[package]]
866
+ name = "markdown-it-py"
867
+ version = "3.0.0"
868
+ source = { registry = "https://pypi.org/simple" }
869
+ dependencies = [
870
+ { name = "mdurl" },
871
+ ]
872
+ sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 }
873
+ wheels = [
874
+ { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 },
875
+ ]
876
+
877
  [[package]]
878
  name = "markupsafe"
879
  version = "3.0.2"
 
914
  { url = "https://files.pythonhosted.org/packages/34/75/51952c7b2d3873b44a0028b1bd26a25078c18f92f256608e8d1dc61b39fd/marshmallow-3.26.1-py3-none-any.whl", hash = "sha256:3350409f20a70a7e4e11a27661187b77cdcaeb20abca41c1454fe33636bea09c", size = 50878 },
915
  ]
916
 
917
+ [[package]]
918
+ name = "mdurl"
919
+ version = "0.1.2"
920
+ source = { registry = "https://pypi.org/simple" }
921
+ sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 }
922
+ wheels = [
923
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 },
924
+ ]
925
+
926
  [[package]]
927
  name = "multidict"
928
  version = "6.4.4"
 
1055
  { url = "https://files.pythonhosted.org/packages/2a/10/f245db006a860dbc1f2e2c8382e0a1762c7753e7971ba43a1dc3f3ec1404/openai-1.84.0-py3-none-any.whl", hash = "sha256:7ec4436c3c933d68dc0f5a0cef0cb3dbc0864a54d62bddaf2ed5f3d521844711", size = 725512 },
1056
  ]
1057
 
1058
+ [[package]]
1059
+ name = "orjson"
1060
+ version = "3.10.18"
1061
+ source = { registry = "https://pypi.org/simple" }
1062
+ sdist = { url = "https://files.pythonhosted.org/packages/81/0b/fea456a3ffe74e70ba30e01ec183a9b26bec4d497f61dcfce1b601059c60/orjson-3.10.18.tar.gz", hash = "sha256:e8da3947d92123eda795b68228cafe2724815621fe35e8e320a9e9593a4bcd53", size = 5422810 }
1063
+ wheels = [
1064
+ { url = "https://files.pythonhosted.org/packages/04/f0/8aedb6574b68096f3be8f74c0b56d36fd94bcf47e6c7ed47a7bd1474aaa8/orjson-3.10.18-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:69c34b9441b863175cc6a01f2935de994025e773f814412030f269da4f7be147", size = 249087 },
1065
+ { url = "https://files.pythonhosted.org/packages/bc/f7/7118f965541aeac6844fcb18d6988e111ac0d349c9b80cda53583e758908/orjson-3.10.18-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:1ebeda919725f9dbdb269f59bc94f861afbe2a27dce5608cdba2d92772364d1c", size = 133273 },
1066
+ { url = "https://files.pythonhosted.org/packages/fb/d9/839637cc06eaf528dd8127b36004247bf56e064501f68df9ee6fd56a88ee/orjson-3.10.18-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5adf5f4eed520a4959d29ea80192fa626ab9a20b2ea13f8f6dc58644f6927103", size = 136779 },
1067
+ { url = "https://files.pythonhosted.org/packages/2b/6d/f226ecfef31a1f0e7d6bf9a31a0bbaf384c7cbe3fce49cc9c2acc51f902a/orjson-3.10.18-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7592bb48a214e18cd670974f289520f12b7aed1fa0b2e2616b8ed9e069e08595", size = 132811 },
1068
+ { url = "https://files.pythonhosted.org/packages/73/2d/371513d04143c85b681cf8f3bce743656eb5b640cb1f461dad750ac4b4d4/orjson-3.10.18-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f872bef9f042734110642b7a11937440797ace8c87527de25e0c53558b579ccc", size = 137018 },
1069
+ { url = "https://files.pythonhosted.org/packages/69/cb/a4d37a30507b7a59bdc484e4a3253c8141bf756d4e13fcc1da760a0b00cb/orjson-3.10.18-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0315317601149c244cb3ecef246ef5861a64824ccbcb8018d32c66a60a84ffbc", size = 138368 },
1070
+ { url = "https://files.pythonhosted.org/packages/1e/ae/cd10883c48d912d216d541eb3db8b2433415fde67f620afe6f311f5cd2ca/orjson-3.10.18-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0da26957e77e9e55a6c2ce2e7182a36a6f6b180ab7189315cb0995ec362e049", size = 142840 },
1071
+ { url = "https://files.pythonhosted.org/packages/6d/4c/2bda09855c6b5f2c055034c9eda1529967b042ff8d81a05005115c4e6772/orjson-3.10.18-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb70d489bc79b7519e5803e2cc4c72343c9dc1154258adf2f8925d0b60da7c58", size = 133135 },
1072
+ { url = "https://files.pythonhosted.org/packages/13/4a/35971fd809a8896731930a80dfff0b8ff48eeb5d8b57bb4d0d525160017f/orjson-3.10.18-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e9e86a6af31b92299b00736c89caf63816f70a4001e750bda179e15564d7a034", size = 134810 },
1073
+ { url = "https://files.pythonhosted.org/packages/99/70/0fa9e6310cda98365629182486ff37a1c6578e34c33992df271a476ea1cd/orjson-3.10.18-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:c382a5c0b5931a5fc5405053d36c1ce3fd561694738626c77ae0b1dfc0242ca1", size = 413491 },
1074
+ { url = "https://files.pythonhosted.org/packages/32/cb/990a0e88498babddb74fb97855ae4fbd22a82960e9b06eab5775cac435da/orjson-3.10.18-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8e4b2ae732431127171b875cb2668f883e1234711d3c147ffd69fe5be51a8012", size = 153277 },
1075
+ { url = "https://files.pythonhosted.org/packages/92/44/473248c3305bf782a384ed50dd8bc2d3cde1543d107138fd99b707480ca1/orjson-3.10.18-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d808e34ddb24fc29a4d4041dcfafbae13e129c93509b847b14432717d94b44f", size = 137367 },
1076
+ { url = "https://files.pythonhosted.org/packages/ad/fd/7f1d3edd4ffcd944a6a40e9f88af2197b619c931ac4d3cfba4798d4d3815/orjson-3.10.18-cp313-cp313-win32.whl", hash = "sha256:ad8eacbb5d904d5591f27dee4031e2c1db43d559edb8f91778efd642d70e6bea", size = 142687 },
1077
+ { url = "https://files.pythonhosted.org/packages/4b/03/c75c6ad46be41c16f4cfe0352a2d1450546f3c09ad2c9d341110cd87b025/orjson-3.10.18-cp313-cp313-win_amd64.whl", hash = "sha256:aed411bcb68bf62e85588f2a7e03a6082cc42e5a2796e06e72a962d7c6310b52", size = 134794 },
1078
+ { url = "https://files.pythonhosted.org/packages/c2/28/f53038a5a72cc4fd0b56c1eafb4ef64aec9685460d5ac34de98ca78b6e29/orjson-3.10.18-cp313-cp313-win_arm64.whl", hash = "sha256:f54c1385a0e6aba2f15a40d703b858bedad36ded0491e55d35d905b2c34a4cc3", size = 131186 },
1079
+ ]
1080
+
1081
  [[package]]
1082
  name = "packaging"
1083
  version = "25.0"
 
1237
  { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777 },
1238
  ]
1239
 
1240
+ [[package]]
1241
+ name = "pydub"
1242
+ version = "0.25.1"
1243
+ source = { registry = "https://pypi.org/simple" }
1244
+ sdist = { url = "https://files.pythonhosted.org/packages/fe/9a/e6bca0eed82db26562c73b5076539a4a08d3cffd19c3cc5913a3e61145fd/pydub-0.25.1.tar.gz", hash = "sha256:980a33ce9949cab2a569606b65674d748ecbca4f0796887fd6f46173a7b0d30f", size = 38326 }
1245
+ wheels = [
1246
+ { url = "https://files.pythonhosted.org/packages/a6/53/d78dc063216e62fc55f6b2eebb447f6a4b0a59f55c8406376f76bf959b08/pydub-0.25.1-py2.py3-none-any.whl", hash = "sha256:65617e33033874b59d87db603aa1ed450633288aefead953b30bded59cb599a6", size = 32327 },
1247
+ ]
1248
+
1249
+ [[package]]
1250
+ name = "pygments"
1251
+ version = "2.19.1"
1252
+ source = { registry = "https://pypi.org/simple" }
1253
+ sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 }
1254
+ wheels = [
1255
+ { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 },
1256
+ ]
1257
+
1258
  [[package]]
1259
  name = "pypdf"
1260
  version = "5.6.0"
 
1285
  { url = "https://files.pythonhosted.org/packages/1e/18/98a99ad95133c6a6e2005fe89faedf294a748bd5dc803008059409ac9b1e/python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d", size = 20256 },
1286
  ]
1287
 
1288
+ [[package]]
1289
+ name = "python-multipart"
1290
+ version = "0.0.20"
1291
+ source = { registry = "https://pypi.org/simple" }
1292
+ sdist = { url = "https://files.pythonhosted.org/packages/f3/87/f44d7c9f274c7ee665a29b885ec97089ec5dc034c7f3fafa03da9e39a09e/python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13", size = 37158 }
1293
+ wheels = [
1294
+ { url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546 },
1295
+ ]
1296
+
1297
  [[package]]
1298
  name = "pytz"
1299
  version = "2025.2"
 
1358
  { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 },
1359
  ]
1360
 
1361
+ [[package]]
1362
+ name = "rich"
1363
+ version = "14.0.0"
1364
+ source = { registry = "https://pypi.org/simple" }
1365
+ dependencies = [
1366
+ { name = "markdown-it-py" },
1367
+ { name = "pygments" },
1368
+ ]
1369
+ sdist = { url = "https://files.pythonhosted.org/packages/a1/53/830aa4c3066a8ab0ae9a9955976fb770fe9c6102117c8ec4ab3ea62d89e8/rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725", size = 224078 }
1370
+ wheels = [
1371
+ { url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229 },
1372
+ ]
1373
+
1374
+ [[package]]
1375
+ name = "ruff"
1376
+ version = "0.11.13"
1377
+ source = { registry = "https://pypi.org/simple" }
1378
+ sdist = { url = "https://files.pythonhosted.org/packages/ed/da/9c6f995903b4d9474b39da91d2d626659af3ff1eeb43e9ae7c119349dba6/ruff-0.11.13.tar.gz", hash = "sha256:26fa247dc68d1d4e72c179e08889a25ac0c7ba4d78aecfc835d49cbfd60bf514", size = 4282054 }
1379
+ wheels = [
1380
+ { url = "https://files.pythonhosted.org/packages/7d/ce/a11d381192966e0b4290842cc8d4fac7dc9214ddf627c11c1afff87da29b/ruff-0.11.13-py3-none-linux_armv6l.whl", hash = "sha256:4bdfbf1240533f40042ec00c9e09a3aade6f8c10b6414cf11b519488d2635d46", size = 10292516 },
1381
+ { url = "https://files.pythonhosted.org/packages/78/db/87c3b59b0d4e753e40b6a3b4a2642dfd1dcaefbff121ddc64d6c8b47ba00/ruff-0.11.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aef9c9ed1b5ca28bb15c7eac83b8670cf3b20b478195bd49c8d756ba0a36cf48", size = 11106083 },
1382
+ { url = "https://files.pythonhosted.org/packages/77/79/d8cec175856ff810a19825d09ce700265f905c643c69f45d2b737e4a470a/ruff-0.11.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:53b15a9dfdce029c842e9a5aebc3855e9ab7771395979ff85b7c1dedb53ddc2b", size = 10436024 },
1383
+ { url = "https://files.pythonhosted.org/packages/8b/5b/f6d94f2980fa1ee854b41568368a2e1252681b9238ab2895e133d303538f/ruff-0.11.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab153241400789138d13f362c43f7edecc0edfffce2afa6a68434000ecd8f69a", size = 10646324 },
1384
+ { url = "https://files.pythonhosted.org/packages/6c/9c/b4c2acf24ea4426016d511dfdc787f4ce1ceb835f3c5fbdbcb32b1c63bda/ruff-0.11.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6c51f93029d54a910d3d24f7dd0bb909e31b6cd989a5e4ac513f4eb41629f0dc", size = 10174416 },
1385
+ { url = "https://files.pythonhosted.org/packages/f3/10/e2e62f77c65ede8cd032c2ca39c41f48feabedb6e282bfd6073d81bb671d/ruff-0.11.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1808b3ed53e1a777c2ef733aca9051dc9bf7c99b26ece15cb59a0320fbdbd629", size = 11724197 },
1386
+ { url = "https://files.pythonhosted.org/packages/bb/f0/466fe8469b85c561e081d798c45f8a1d21e0b4a5ef795a1d7f1a9a9ec182/ruff-0.11.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d28ce58b5ecf0f43c1b71edffabe6ed7f245d5336b17805803312ec9bc665933", size = 12511615 },
1387
+ { url = "https://files.pythonhosted.org/packages/17/0e/cefe778b46dbd0cbcb03a839946c8f80a06f7968eb298aa4d1a4293f3448/ruff-0.11.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55e4bc3a77842da33c16d55b32c6cac1ec5fb0fbec9c8c513bdce76c4f922165", size = 12117080 },
1388
+ { url = "https://files.pythonhosted.org/packages/5d/2c/caaeda564cbe103bed145ea557cb86795b18651b0f6b3ff6a10e84e5a33f/ruff-0.11.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:633bf2c6f35678c56ec73189ba6fa19ff1c5e4807a78bf60ef487b9dd272cc71", size = 11326315 },
1389
+ { url = "https://files.pythonhosted.org/packages/75/f0/782e7d681d660eda8c536962920c41309e6dd4ebcea9a2714ed5127d44bd/ruff-0.11.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ffbc82d70424b275b089166310448051afdc6e914fdab90e08df66c43bb5ca9", size = 11555640 },
1390
+ { url = "https://files.pythonhosted.org/packages/5d/d4/3d580c616316c7f07fb3c99dbecfe01fbaea7b6fd9a82b801e72e5de742a/ruff-0.11.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4a9ddd3ec62a9a89578c85842b836e4ac832d4a2e0bfaad3b02243f930ceafcc", size = 10507364 },
1391
+ { url = "https://files.pythonhosted.org/packages/5a/dc/195e6f17d7b3ea6b12dc4f3e9de575db7983db187c378d44606e5d503319/ruff-0.11.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d237a496e0778d719efb05058c64d28b757c77824e04ffe8796c7436e26712b7", size = 10141462 },
1392
+ { url = "https://files.pythonhosted.org/packages/f4/8e/39a094af6967faa57ecdeacb91bedfb232474ff8c3d20f16a5514e6b3534/ruff-0.11.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:26816a218ca6ef02142343fd24c70f7cd8c5aa6c203bca284407adf675984432", size = 11121028 },
1393
+ { url = "https://files.pythonhosted.org/packages/5a/c0/b0b508193b0e8a1654ec683ebab18d309861f8bd64e3a2f9648b80d392cb/ruff-0.11.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:51c3f95abd9331dc5b87c47ac7f376db5616041173826dfd556cfe3d4977f492", size = 11602992 },
1394
+ { url = "https://files.pythonhosted.org/packages/7c/91/263e33ab93ab09ca06ce4f8f8547a858cc198072f873ebc9be7466790bae/ruff-0.11.13-py3-none-win32.whl", hash = "sha256:96c27935418e4e8e77a26bb05962817f28b8ef3843a6c6cc49d8783b5507f250", size = 10474944 },
1395
+ { url = "https://files.pythonhosted.org/packages/46/f4/7c27734ac2073aae8efb0119cae6931b6fb48017adf048fdf85c19337afc/ruff-0.11.13-py3-none-win_amd64.whl", hash = "sha256:29c3189895a8a6a657b7af4e97d330c8a3afd2c9c8f46c81e2fc5a31866517e3", size = 11548669 },
1396
+ { url = "https://files.pythonhosted.org/packages/ec/bf/b273dd11673fed8a6bd46032c0ea2a04b2ac9bfa9c628756a5856ba113b0/ruff-0.11.13-py3-none-win_arm64.whl", hash = "sha256:b4385285e9179d608ff1d2fb9922062663c658605819a6876d8beef0c30b7f3b", size = 10683928 },
1397
+ ]
1398
+
1399
+ [[package]]
1400
+ name = "safehttpx"
1401
+ version = "0.1.6"
1402
+ source = { registry = "https://pypi.org/simple" }
1403
+ dependencies = [
1404
+ { name = "httpx" },
1405
+ ]
1406
+ sdist = { url = "https://files.pythonhosted.org/packages/67/4c/19db75e6405692b2a96af8f06d1258f8aa7290bdc35ac966f03e207f6d7f/safehttpx-0.1.6.tar.gz", hash = "sha256:b356bfc82cee3a24c395b94a2dbeabbed60aff1aa5fa3b5fe97c4f2456ebce42", size = 9987 }
1407
+ wheels = [
1408
+ { url = "https://files.pythonhosted.org/packages/4d/c0/1108ad9f01567f66b3154063605b350b69c3c9366732e09e45f9fd0d1deb/safehttpx-0.1.6-py3-none-any.whl", hash = "sha256:407cff0b410b071623087c63dd2080c3b44dc076888d8c5823c00d1e58cb381c", size = 8692 },
1409
+ ]
1410
+
1411
+ [[package]]
1412
+ name = "semantic-version"
1413
+ version = "2.10.0"
1414
+ source = { registry = "https://pypi.org/simple" }
1415
+ sdist = { url = "https://files.pythonhosted.org/packages/7d/31/f2289ce78b9b473d582568c234e104d2a342fd658cc288a7553d83bb8595/semantic_version-2.10.0.tar.gz", hash = "sha256:bdabb6d336998cbb378d4b9db3a4b56a1e3235701dc05ea2690d9a997ed5041c", size = 52289 }
1416
+ wheels = [
1417
+ { url = "https://files.pythonhosted.org/packages/6a/23/8146aad7d88f4fcb3a6218f41a60f6c2d4e3a72de72da1825dc7c8f7877c/semantic_version-2.10.0-py2.py3-none-any.whl", hash = "sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177", size = 15552 },
1418
+ ]
1419
+
1420
+ [[package]]
1421
+ name = "shellingham"
1422
+ version = "1.5.4"
1423
+ source = { registry = "https://pypi.org/simple" }
1424
+ sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310 }
1425
+ wheels = [
1426
+ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 },
1427
+ ]
1428
+
1429
  [[package]]
1430
  name = "six"
1431
  version = "1.17.0"
 
1479
  { name = "greenlet" },
1480
  ]
1481
 
1482
+ [[package]]
1483
+ name = "starlette"
1484
+ version = "0.46.2"
1485
+ source = { registry = "https://pypi.org/simple" }
1486
+ dependencies = [
1487
+ { name = "anyio" },
1488
+ ]
1489
+ sdist = { url = "https://files.pythonhosted.org/packages/ce/20/08dfcd9c983f6a6f4a1000d934b9e6d626cff8d2eeb77a89a68eef20a2b7/starlette-0.46.2.tar.gz", hash = "sha256:7f7361f34eed179294600af672f565727419830b54b7b084efe44bb82d2fccd5", size = 2580846 }
1490
+ wheels = [
1491
+ { url = "https://files.pythonhosted.org/packages/8b/0c/9d30a4ebeb6db2b25a841afbb80f6ef9a854fc3b41be131d249a977b4959/starlette-0.46.2-py3-none-any.whl", hash = "sha256:595633ce89f8ffa71a015caed34a5b2dc1c0cdb3f0f1fbd1e69339cf2abeec35", size = 72037 },
1492
+ ]
1493
+
1494
  [[package]]
1495
  name = "striprtf"
1496
  version = "0.0.26"
 
1519
  version = "0.1.0"
1520
  source = { virtual = "." }
1521
  dependencies = [
1522
+ { name = "asyncio" },
1523
  { name = "dotenv" },
1524
+ { name = "gradio" },
1525
  { name = "llama-index" },
1526
  { name = "tavily-python" },
1527
  ]
1528
 
1529
  [package.metadata]
1530
  requires-dist = [
1531
+ { name = "asyncio", specifier = ">=3.4.3" },
1532
  { name = "dotenv", specifier = ">=0.9.9" },
1533
+ { name = "gradio", specifier = ">=5.33.0" },
1534
  { name = "llama-index", specifier = ">=0.12.40" },
1535
  { name = "tavily-python", specifier = ">=0.7.5" },
1536
  ]
 
1562
  { url = "https://files.pythonhosted.org/packages/de/a8/8f499c179ec900783ffe133e9aab10044481679bb9aad78436d239eee716/tiktoken-0.9.0-cp313-cp313-win_amd64.whl", hash = "sha256:5ea0edb6f83dc56d794723286215918c1cde03712cbbafa0348b33448faf5b95", size = 894669 },
1563
  ]
1564
 
1565
+ [[package]]
1566
+ name = "tomlkit"
1567
+ version = "0.13.3"
1568
+ source = { registry = "https://pypi.org/simple" }
1569
+ sdist = { url = "https://files.pythonhosted.org/packages/cc/18/0bbf3884e9eaa38819ebe46a7bd25dcd56b67434402b66a58c4b8e552575/tomlkit-0.13.3.tar.gz", hash = "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1", size = 185207 }
1570
+ wheels = [
1571
+ { url = "https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl", hash = "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0", size = 38901 },
1572
+ ]
1573
+
1574
  [[package]]
1575
  name = "tqdm"
1576
  version = "4.67.1"
 
1583
  { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540 },
1584
  ]
1585
 
1586
+ [[package]]
1587
+ name = "typer"
1588
+ version = "0.16.0"
1589
+ source = { registry = "https://pypi.org/simple" }
1590
+ dependencies = [
1591
+ { name = "click" },
1592
+ { name = "rich" },
1593
+ { name = "shellingham" },
1594
+ { name = "typing-extensions" },
1595
+ ]
1596
+ sdist = { url = "https://files.pythonhosted.org/packages/c5/8c/7d682431efca5fd290017663ea4588bf6f2c6aad085c7f108c5dbc316e70/typer-0.16.0.tar.gz", hash = "sha256:af377ffaee1dbe37ae9440cb4e8f11686ea5ce4e9bae01b84ae7c63b87f1dd3b", size = 102625 }
1597
+ wheels = [
1598
+ { url = "https://files.pythonhosted.org/packages/76/42/3efaf858001d2c2913de7f354563e3a3a2f0decae3efe98427125a8f441e/typer-0.16.0-py3-none-any.whl", hash = "sha256:1f79bed11d4d02d4310e3c1b7ba594183bcedb0ac73b27a9e5f28f6fb5b98855", size = 46317 },
1599
+ ]
1600
+
1601
  [[package]]
1602
  name = "typing-extensions"
1603
  version = "4.14.0"
 
1650
  { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680 },
1651
  ]
1652
 
1653
+ [[package]]
1654
+ name = "uvicorn"
1655
+ version = "0.34.3"
1656
+ source = { registry = "https://pypi.org/simple" }
1657
+ dependencies = [
1658
+ { name = "click" },
1659
+ { name = "h11" },
1660
+ ]
1661
+ sdist = { url = "https://files.pythonhosted.org/packages/de/ad/713be230bcda622eaa35c28f0d328c3675c371238470abdea52417f17a8e/uvicorn-0.34.3.tar.gz", hash = "sha256:35919a9a979d7a59334b6b10e05d77c1d0d574c50e0fc98b8b1a0f165708b55a", size = 76631 }
1662
+ wheels = [
1663
+ { url = "https://files.pythonhosted.org/packages/6d/0d/8adfeaa62945f90d19ddc461c55f4a50c258af7662d34b6a3d5d1f8646f6/uvicorn-0.34.3-py3-none-any.whl", hash = "sha256:16246631db62bdfbf069b0645177d6e8a77ba950cfedbfd093acef9444e4d885", size = 62431 },
1664
+ ]
1665
+
1666
+ [[package]]
1667
+ name = "websockets"
1668
+ version = "15.0.1"
1669
+ source = { registry = "https://pypi.org/simple" }
1670
+ sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016 }
1671
+ wheels = [
1672
+ { url = "https://files.pythonhosted.org/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440 },
1673
+ { url = "https://files.pythonhosted.org/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098 },
1674
+ { url = "https://files.pythonhosted.org/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329 },
1675
+ { url = "https://files.pythonhosted.org/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111 },
1676
+ { url = "https://files.pythonhosted.org/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054 },
1677
+ { url = "https://files.pythonhosted.org/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496 },
1678
+ { url = "https://files.pythonhosted.org/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829 },
1679
+ { url = "https://files.pythonhosted.org/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217 },
1680
+ { url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195 },
1681
+ { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393 },
1682
+ { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837 },
1683
+ { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743 },
1684
+ ]
1685
+
1686
  [[package]]
1687
  name = "wrapt"
1688
  version = "1.17.2"