From e2dba7fb29b4a3d14e295763b24cfeec227c07ec Mon Sep 17 00:00:00 2001 From: Mac Wilkinson Date: Thu, 30 May 2024 20:09:40 -0700 Subject: [PATCH 01/25] Update Readme with Preview Info (#1) * Update Readme with Preview Info * We're not quite that far along * Update Structure to be more Pleasing to the Eyes * Add changelog to readme --------- Co-authored-by: srhinos <6531393+srhinos@users.noreply.github.com> Co-authored-by: Adnaan Sachidanandan --- README.md | 225 ++++++++++++++++++------------------------------------ 1 file changed, 73 insertions(+), 152 deletions(-) diff --git a/README.md b/README.md index a01434cdf..d02598156 100644 --- a/README.md +++ b/README.md @@ -1,152 +1,73 @@ -
- -![Hero](https://user-images.githubusercontent.com/6234599/228337850-e32bb01d-3701-47ef-a433-3221c9e0e56e.png) - -[![Twitter](https://img.shields.io/twitter/url/https/twitter.com/vocodehq.svg?style=social&label=Follow%20%40vocodehq)](https://twitter.com/vocodehq) [![GitHub Repo stars](https://img.shields.io/github/stars/vocodedev/vocode-python?style=social)](https://github.com/vocodedev/vocode-python) -[![Downloads](https://static.pepy.tech/badge/vocode/month)](https://pepy.tech/project/vocode) - -[Community](https://discord.gg/NaU4mMgcnC) | [Docs](https://docs.vocode.dev) | [Dashboard](https://app.vocode.dev) - -
- -#   vocode - -### **Build voice-based LLM apps in minutes** - -Vocode is an open source library that makes it easy to build voice-based LLM apps. Using Vocode, you can build real-time streaming conversations with LLMs and deploy them to phone calls, Zoom meetings, and more. You can also build personal assistants or apps like voice-based chess. Vocode provides easy abstractions and integrations so that everything you need is in a single library. - -We're actively looking for community maintainers, so please reach out if interested! - -# ⭐️ Features - -- 🗣 [Spin up a conversation with your system audio](https://docs.vocode.dev/python-quickstart) -- ➡️ 📞 [Set up a phone number that responds with a LLM-based agent](https://docs.vocode.dev/telephony#inbound-calls) -- 📞 ➡️ [Send out phone calls from your phone number managed by an LLM-based agent](https://docs.vocode.dev/telephony#outbound-calls) -- 🧑‍💻 [Dial into a Zoom call](https://github.com/vocodedev/vocode-python/blob/main/vocode/streaming/telephony/hosted/zoom_dial_in.py) -- 🤖 [Use an outbound call to a real phone number in a Langchain agent](https://docs.vocode.dev/langchain-agent) -- Out of the box integrations with: - - Transcription services, including: - - [AssemblyAI](https://www.assemblyai.com/) - - [Deepgram](https://deepgram.com/) - - [Gladia](https://gladia.io) - - [Google Cloud](https://cloud.google.com/speech-to-text) - - [Microsoft Azure](https://azure.microsoft.com/en-us/products/cognitive-services/speech-to-text) - - [RevAI](https://www.rev.ai/) - - [Whisper](https://openai.com/blog/introducing-chatgpt-and-whisper-apis) - - [Whisper.cpp](https://github.com/ggerganov/whisper.cpp) - - - LLMs, including: - - [ChatGPT](https://openai.com/blog/chatgpt) - - [GPT-4](https://platform.openai.com/docs/models/gpt-4) - - [Anthropic](https://www.anthropic.com/) - - [GPT4All](https://github.com/nomic-ai/gpt4all) - - Synthesis services, including: - - [Rime.ai](https://rime.ai) - - [Microsoft Azure](https://azure.microsoft.com/en-us/products/cognitive-services/text-to-speech/) - - [Google Cloud](https://cloud.google.com/text-to-speech) - - [Play.ht](https://play.ht) - - [Eleven Labs](https://elevenlabs.io/) - - [Coqui](https://coqui.ai/) - - [Coqui (OSS)](https://github.com/coqui-ai/TTS) - - [gTTS](https://gtts.readthedocs.io/) - - [StreamElements](https://streamelements.com/) - - [Bark](https://github.com/suno-ai/bark) - - [AWS Polly](https://aws.amazon.com/polly/) - -Check out our React SDK [here](https://github.com/vocodedev/vocode-react-sdk)! - -# 🫂 Contribution and Roadmap - -We're an open source project and are extremely open to contributors adding new features, integrations, and documentation! Please don't hesitate to reach out and get started building with us. - -For more information on contributing, see our [Contribution Guide](https://github.com/vocodedev/vocode-python/blob/main/contributing.md). - -And check out our [Roadmap](https://github.com/vocodedev/vocode-python/blob/main/roadmap.md). - -We'd love to talk to you on [Discord](https://discord.gg/NaU4mMgcnC) about new ideas and contributing! - -# 🚀 Quickstart - -```bash -pip install 'vocode' -``` - -```python -import asyncio -import logging -import signal -from vocode.streaming.streaming_conversation import StreamingConversation -from vocode.helpers import create_streaming_microphone_input_and_speaker_output -from vocode.streaming.transcriber import * -from vocode.streaming.agent import * -from vocode.streaming.synthesizer import * -from vocode.streaming.models.transcriber import * -from vocode.streaming.models.agent import * -from vocode.streaming.models.synthesizer import * -from vocode.streaming.models.message import BaseMessage -import vocode - -# these can also be set as environment variables -vocode.setenv( - OPENAI_API_KEY="", - DEEPGRAM_API_KEY="", - AZURE_SPEECH_KEY="", - AZURE_SPEECH_REGION="", -) - - -logging.basicConfig() -logger = logging.getLogger(__name__) -logger.setLevel(logging.DEBUG) - - -async def main(): - ( - microphone_input, - speaker_output, - ) = create_streaming_microphone_input_and_speaker_output( - use_default_devices=False, - logger=logger, - use_blocking_speaker_output=True - ) - - conversation = StreamingConversation( - output_device=speaker_output, - transcriber=DeepgramTranscriber( - DeepgramTranscriberConfig.from_input_device( - microphone_input, - endpointing_config=PunctuationEndpointingConfig(), - ) - ), - agent=ChatGPTAgent( - ChatGPTAgentConfig( - initial_message=BaseMessage(text="What up"), - prompt_preamble="""The AI is having a pleasant conversation about life""", - ) - ), - synthesizer=AzureSynthesizer( - AzureSynthesizerConfig.from_output_device(speaker_output) - ), - logger=logger, - ) - await conversation.start() - print("Conversation started, press Ctrl+C to end") - signal.signal( - signal.SIGINT, lambda _0, _1: asyncio.create_task(conversation.terminate()) - ) - while conversation.is_active(): - chunk = await microphone_input.get_audio() - conversation.receive_audio(chunk) - - -if __name__ == "__main__": - asyncio.run(main()) -``` - -# 📞 Phone call quickstarts - -- [Telephony Server - Self-hosted](https://docs.vocode.dev/telephony) - -# 🌱 Documentation - -[docs.vocode.dev](https://docs.vocode.dev/) +# 🤫 Vocode 0.0.112 Early Preview + +👋 Hey there, Vocode Explorer! + +Congratulations! You've stumbled upon the Vocode 0.0.112 Early Preview Repo! Whether we (the Vocode team) sent you this link or you found it through your own detective work, we want to celebrate your awesomeness in the Vocode community with this exclusive sneak peek of our latest work! + +## 🎉 What's Next? + +We'd love to invite you to our private channel on Discord! [(Join us here!)](https://discord.gg/MVQD5bmf49) This is your VIP pass to chat with Vocode team members, get help, ask questions, and maybe even contribute to the 0.0.112 release! + +## 🚨 Need Access? + +If you can see this but don't have access to the new channels, just reach out to Mac, Ajay, George, or any other Vocode team member. We'll make sure you get in! + +## 🤐 Keep It Under Wraps + +We’re super excited to share this with you, but we’d appreciate it if you could keep this on the down-low for now. While we know you might share this with close friends, please avoid posting it in public places. We're still polishing things up for the big public launch! + +## 📝 Brief Changelog + +### 🧱Vocode Core Abstractions Revamp + +- Improved Abstractions to enable faster customization of: + - Agents + - Transcribers + - Synthesizers + - Telephony Providers + +### 👥 Conversation Mechanics + +- Better endpointing (agnostic of transcribers) +- Better interruption handling + +### 🕵️ Agents + +- ✨NEW✨ Anthropic-based Agent + - Supports all Claude 3 Models +- OpenAI GPT-4o Support +- Azure OpenAI revamp + +### 💪 Actions + +- ✨NEW✨ External Actions +- Improved Call Transfer +- ✨NEW✨ Wait Actions (IVR Navigation) +- ✨NEW✨ Phrase triggers for actions (instead of function calls) + +### 🗣️ Synthesizers + +- ElevenLabs + - ✨NEW✨ Websocket-based Client + - Updated RESTful client +- ✨NEW✨ PlayHT Synthesizer “v2” with [PlayHT On-Prem](https://docs.play.ht/reference/on-prem) Support +- [Rime Mist](https://rimelabs.mintlify.app/api-reference/models) support + +### ✍️ Transcribers + +- ✨NEW✨ Deepgram [built-in endpointing](https://developers.deepgram.com/docs/endpointing) + +### 📞 Telephony + +- Twilio + - Stronger interruption handling by [clearing audio queues](https://www.twilio.com/docs/voice/media-streams/websocket-messages#send-a-clear-message) +- Vonage + - Koala Noise Suppression + +### 🎉 Miscellaneous + +- ✨NEW✨  Loguru for improved logging formatting + - Some new utilities to make setting up loguru in your projects fast and easy 😉 +- Sentry for Metric / Error Collection +- Clean handling of content filters in ChatGPT agents +- Redis Message Queue for tracking mid-call events across different instances From 1aeddcdbbace5f391998fc37752dcdfaaab89059 Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Thu, 30 May 2024 20:26:31 -0700 Subject: [PATCH 02/25] The Big Diff (#2) * The Big Diff * remove tests on 3.8 and 3.9 --- .github/workflows/test.yml | 2 - apps/client_backend/Dockerfile | 2 +- apps/client_backend/main.py | 17 +- apps/client_backend/poetry.lock | 3373 +++++++---- apps/client_backend/pyproject.toml | 8 +- apps/telephony_app/Dockerfile | 2 +- apps/telephony_app/docker-compose.yml | 10 +- apps/telephony_app/main.py | 42 +- apps/telephony_app/outbound_call.py | 25 +- apps/telephony_app/poetry.lock | 3594 ++++++++---- apps/telephony_app/pyproject.toml | 11 +- apps/telephony_app/speller_agent.py | 18 +- playground/streaming/agent/chat.py | 135 +- .../agent/restful_user_implemented_agent.py | 1 + .../agent/websocket_user_implemented_agent.py | 1 + playground/streaming/benchmark.py | 246 +- .../streaming/synthesizer/synthesize.py | 53 +- playground/streaming/tracing_utils.py | 38 +- .../streaming/transcriber/transcribe.py | 31 +- poetry.lock | 4994 ++++++++++------- pyproject.toml | 173 +- quickstarts/streaming_conversation.py | 35 +- quickstarts/turn_based_conversation.py | 9 +- tests/conftest.py | 66 + tests/fakedata/conversation.py | 85 + tests/fakedata/id.py | 5 + tests/streaming/__init__.py | 0 tests/streaming/action/conftest.py | 31 + tests/streaming/action/test_dtmf.py | 77 + .../streaming/action/test_end_conversation.py | 132 + .../streaming/action/test_external_actions.py | 122 + .../action/test_external_actions_requester.py | 82 + tests/streaming/action/test_record_email.py | 77 + tests/streaming/action/test_transfer_call.py | 222 + tests/streaming/action/test_wait.py | 23 + tests/streaming/agent/test_base_agent.py | 179 + tests/streaming/agent/test_openai_utils.py | 303 + ...{test_utils.py => test_streaming_utils.py} | 237 +- tests/streaming/data/__init__.py | 0 tests/streaming/data/fake_audio.mp3 | Bin 11593 -> 0 bytes tests/streaming/data/fake_audio.wav | Bin 63564 -> 0 bytes tests/streaming/data/loader.py | 5 - tests/streaming/fixtures/__init__.py | 0 tests/streaming/fixtures/output_device.py | 6 - tests/streaming/fixtures/synthesizer.py | 36 - tests/streaming/fixtures/transcriber.py | 26 - tests/streaming/models/test_transcript.py | 96 - tests/streaming/synthesizer/conftest.py | 26 + .../streaming/synthesizer/test_audio_cache.py | 61 + tests/streaming/synthesizer/test_factory.py | 87 + .../streaming/test_streaming_conversation.py | 490 +- tests/streaming/utils/test_events_manager.py | 28 +- tests/streaming/utils/test_phone_numbers.py | 49 + tests/streaming/utils/test_utils.py | 54 + tests/synthesizer/conftest.py | 128 - tests/synthesizer/test_eleven_labs.py | 51 - tests/synthesizer/test_play_ht.py | 61 - vocode/__init__.py | 65 + vocode/helpers.py | 51 +- vocode/logging.py | 185 + vocode/streaming/action/abstract_factory.py | 10 + .../action/{utils.py => action_utils.py} | 0 vocode/streaming/action/base_action.py | 56 +- vocode/streaming/action/default_factory.py | 47 + vocode/streaming/action/dtmf.py | 83 + vocode/streaming/action/end_conversation.py | 89 + .../action/execute_external_action.py | 110 + .../action/external_actions_requester.py | 134 + vocode/streaming/action/factory.py | 17 - vocode/streaming/action/nylas_send_email.py | 62 - vocode/streaming/action/phone_call_action.py | 40 +- vocode/streaming/action/record_email.py | 76 + vocode/streaming/action/transfer_call.py | 172 +- vocode/streaming/action/wait.py | 52 + vocode/streaming/action/worker.py | 21 +- vocode/streaming/agent/__init__.py | 8 - vocode/streaming/agent/abstract_factory.py | 10 + vocode/streaming/agent/anthropic_agent.py | 213 +- vocode/streaming/agent/anthropic_utils.py | 29 + vocode/streaming/agent/base_agent.py | 467 +- .../streaming/agent/bot_sentiment_analyser.py | 58 - vocode/streaming/agent/chat_gpt_agent.py | 269 +- vocode/streaming/agent/default_factory.py | 27 + vocode/streaming/agent/echo_agent.py | 11 +- vocode/streaming/agent/factory.py | 45 - vocode/streaming/agent/goodbye.py | 13 + vocode/streaming/agent/gpt4all_agent.py | 9 +- .../agent/information_retrieval_agent.py | 34 - vocode/streaming/agent/llamacpp_agent.py | 44 +- vocode/streaming/agent/llm_agent.py | 156 - vocode/streaming/agent/openai_utils.py | 179 + vocode/streaming/agent/phrase_trigger.py | 21 + .../streaming/agent/prompts/action_prompt.py | 24 - .../agent/restful_user_implemented_agent.py | 23 +- vocode/streaming/agent/streaming_utils.py | 139 + vocode/streaming/agent/token_utils.py | 252 + vocode/streaming/agent/utils.py | 182 - vocode/streaming/agent/vertex_ai_agent.py | 30 +- .../agent/websocket_user_implemented_agent.py | 71 +- .../streaming/client_backend/conversation.py | 35 +- vocode/streaming/constants.py | 9 +- .../input_device/base_input_device.py | 7 +- .../input_device/file_input_device.py | 10 +- .../input_device/microphone_input.py | 17 +- vocode/streaming/models/actions.py | 90 +- vocode/streaming/models/agent.py | 89 +- vocode/streaming/models/audio.py | 15 + vocode/streaming/models/audio_encoding.py | 6 - vocode/streaming/models/client_backend.py | 3 +- vocode/streaming/models/events.py | 15 +- vocode/streaming/models/message.py | 24 +- vocode/streaming/models/model.py | 13 +- vocode/streaming/models/synthesizer.py | 90 +- vocode/streaming/models/telephony.py | 40 +- vocode/streaming/models/transcriber.py | 58 +- vocode/streaming/models/transcript.py | 163 +- vocode/streaming/models/vector_db.py | 9 +- vocode/streaming/models/websocket.py | 23 +- vocode/streaming/models/websocket_agent.py | 10 +- .../output_device/base_output_device.py | 5 +- .../output_device/blocking_speaker_output.py | 7 +- .../output_device/file_output_device.py | 5 +- .../streaming/output_device/speaker_output.py | 5 +- .../output_device/twilio_output_device.py | 39 +- .../output_device/vonage_output_device.py | 16 +- .../output_device/websocket_output_device.py | 16 +- vocode/streaming/streaming_conversation.py | 788 ++- vocode/streaming/synthesizer/__init__.py | 14 - .../streaming/synthesizer/abstract_factory.py | 15 + vocode/streaming/synthesizer/audio_cache.py | 47 + .../synthesizer/azure_synthesizer.py | 113 +- .../streaming/synthesizer/bark_synthesizer.py | 38 +- .../streaming/synthesizer/base_synthesizer.py | 259 +- .../synthesizer/coqui_synthesizer.py | 32 +- .../synthesizer/coqui_tts_synthesizer.py | 44 +- .../streaming/synthesizer/default_factory.py | 37 + .../synthesizer/eleven_labs_synthesizer.py | 174 +- .../eleven_labs_websocket_synthesizer.py | 340 ++ vocode/streaming/synthesizer/factory.py | 76 - .../synthesizer/google_synthesizer.py | 54 +- .../streaming/synthesizer/gtts_synthesizer.py | 43 +- .../input_streaming_synthesizer.py | 16 + .../streaming/synthesizer/miniaudio_worker.py | 12 +- .../synthesizer/play_ht_synthesizer.py | 115 +- .../synthesizer/play_ht_synthesizer_v2.py | 300 + .../synthesizer/polly_synthesizer.py | 27 +- .../streaming/synthesizer/rime_synthesizer.py | 172 +- .../stream_elements_synthesizer.py | 36 +- .../synthesizer/synthesizer_utils.py | 50 + .../client/abstract_telephony_client.py | 29 + .../telephony/client/base_telephony_client.py | 32 - .../telephony/client/twilio_client.py | 128 +- .../telephony/client/vonage_client.py | 190 +- .../in_memory_config_manager.py | 5 +- .../config_manager/redis_config_manager.py | 37 +- vocode/streaming/telephony/constants.py | 8 +- .../abstract_phone_conversation.py | 90 + .../streaming/telephony/conversation/call.py | 83 - .../conversation/mark_message_queue.py | 46 + .../telephony/conversation/outbound_call.py | 92 +- .../telephony/conversation/twilio_call.py | 161 - .../conversation/twilio_phone_conversation.py | 273 + .../telephony/conversation/vonage_call.py | 131 - .../conversation/vonage_phone_conversation.py | 139 + .../telephony/conversation/zoom_dial_in.py | 13 +- vocode/streaming/telephony/server/base.py | 88 +- .../telephony/server/router/calls.py | 65 +- vocode/streaming/telephony/templater.py | 37 +- ...nnect_call.xml => twilio_connect_call.xml} | 2 +- vocode/streaming/transcriber/__init__.py | 7 - .../streaming/transcriber/abstract_factory.py | 16 + .../transcriber/assembly_ai_transcriber.py | 82 +- .../transcriber/azure_transcriber.py | 39 +- .../streaming/transcriber/base_transcriber.py | 79 +- .../transcriber/deepgram_transcriber.py | 750 ++- .../{factory.py => default_factory.py} | 24 +- .../transcriber/gladia_transcriber.py | 27 +- .../transcriber/google_transcriber.py | 31 +- .../transcriber/rev_ai_transcriber.py | 37 +- .../transcriber/whisper_cpp_transcriber.py | 28 +- .../user_implemented_agent/base_agent.py | 2 +- .../user_implemented_agent/restful_agent.py | 12 +- vocode/streaming/utils/__init__.py | 77 +- vocode/streaming/utils/async_requester.py | 25 + .../utils/conversation_logger_adapter.py | 15 - vocode/streaming/utils/create_task.py | 30 + vocode/streaming/utils/events_manager.py | 38 +- vocode/streaming/utils/goodbye_model.py | 93 - vocode/streaming/utils/mp3_helper.py | 1 + vocode/streaming/utils/phone_numbers.py | 42 + vocode/streaming/utils/redis.py | 79 + .../utils/redis_conversation_message_queue.py | 35 + vocode/streaming/utils/singleton.py | 14 + vocode/streaming/utils/speed_manager.py | 44 + vocode/streaming/utils/state_manager.py | 158 +- vocode/streaming/utils/worker.py | 55 +- vocode/streaming/vector_db/base_vector_db.py | 31 +- vocode/streaming/vector_db/factory.py | 3 +- vocode/streaming/vector_db/pinecone.py | 20 +- vocode/turn_based/agent/chat_gpt_agent.py | 65 +- vocode/turn_based/agent/gpt4all_agent.py | 22 +- .../input_device/microphone_input.py | 7 +- .../output_device/speaker_output.py | 3 +- vocode/turn_based/synthesizer/__init__.py | 14 - .../synthesizer/azure_synthesizer.py | 3 +- .../synthesizer/bark_synthesizer.py | 16 +- .../synthesizer/coqui_synthesizer.py | 17 +- .../synthesizer/coqui_tts_synthesizer.py | 5 +- .../synthesizer/eleven_labs_synthesizer.py | 22 +- .../synthesizer/google_synthesizer.py | 8 +- .../synthesizer/gtts_synthesizer.py | 4 +- .../synthesizer/play_ht_synthesizer.py | 13 +- .../synthesizer/polly_synthesizer.py | 5 +- .../synthesizer/rime_synthesizer.py | 5 +- .../stream_elements_synthesizer.py | 6 +- .../turn_based/transcriber/sr_transcriber.py | 22 +- .../transcriber/whisper_cpp_transcriber.py | 1 + .../transcriber/whisper_transcriber.py | 10 +- vocode/turn_based/turn_based_conversation.py | 18 +- vocode/utils/sentry_utils.py | 243 + vocode/utils/whisper_cpp/helpers.py | 11 +- vocode/utils/whisper_cpp/whisper_params.py | 14 +- 222 files changed, 17886 insertions(+), 9061 deletions(-) create mode 100644 tests/conftest.py create mode 100644 tests/fakedata/conversation.py create mode 100644 tests/fakedata/id.py delete mode 100644 tests/streaming/__init__.py create mode 100644 tests/streaming/action/conftest.py create mode 100644 tests/streaming/action/test_dtmf.py create mode 100644 tests/streaming/action/test_end_conversation.py create mode 100644 tests/streaming/action/test_external_actions.py create mode 100644 tests/streaming/action/test_external_actions_requester.py create mode 100644 tests/streaming/action/test_record_email.py create mode 100644 tests/streaming/action/test_transfer_call.py create mode 100644 tests/streaming/action/test_wait.py create mode 100644 tests/streaming/agent/test_base_agent.py create mode 100644 tests/streaming/agent/test_openai_utils.py rename tests/streaming/agent/{test_utils.py => test_streaming_utils.py} (71%) delete mode 100644 tests/streaming/data/__init__.py delete mode 100644 tests/streaming/data/fake_audio.mp3 delete mode 100644 tests/streaming/data/fake_audio.wav delete mode 100644 tests/streaming/data/loader.py delete mode 100644 tests/streaming/fixtures/__init__.py delete mode 100644 tests/streaming/fixtures/output_device.py delete mode 100644 tests/streaming/fixtures/synthesizer.py delete mode 100644 tests/streaming/fixtures/transcriber.py delete mode 100644 tests/streaming/models/test_transcript.py create mode 100644 tests/streaming/synthesizer/conftest.py create mode 100644 tests/streaming/synthesizer/test_audio_cache.py create mode 100644 tests/streaming/synthesizer/test_factory.py create mode 100644 tests/streaming/utils/test_phone_numbers.py create mode 100644 tests/streaming/utils/test_utils.py delete mode 100644 tests/synthesizer/conftest.py delete mode 100644 tests/synthesizer/test_eleven_labs.py delete mode 100644 tests/synthesizer/test_play_ht.py create mode 100644 vocode/logging.py create mode 100644 vocode/streaming/action/abstract_factory.py rename vocode/streaming/action/{utils.py => action_utils.py} (100%) create mode 100644 vocode/streaming/action/default_factory.py create mode 100644 vocode/streaming/action/dtmf.py create mode 100644 vocode/streaming/action/end_conversation.py create mode 100644 vocode/streaming/action/execute_external_action.py create mode 100644 vocode/streaming/action/external_actions_requester.py delete mode 100644 vocode/streaming/action/factory.py delete mode 100644 vocode/streaming/action/nylas_send_email.py create mode 100644 vocode/streaming/action/record_email.py create mode 100644 vocode/streaming/action/wait.py create mode 100644 vocode/streaming/agent/abstract_factory.py create mode 100644 vocode/streaming/agent/anthropic_utils.py delete mode 100644 vocode/streaming/agent/bot_sentiment_analyser.py create mode 100644 vocode/streaming/agent/default_factory.py delete mode 100644 vocode/streaming/agent/factory.py create mode 100644 vocode/streaming/agent/goodbye.py delete mode 100644 vocode/streaming/agent/information_retrieval_agent.py delete mode 100644 vocode/streaming/agent/llm_agent.py create mode 100644 vocode/streaming/agent/openai_utils.py create mode 100644 vocode/streaming/agent/phrase_trigger.py delete mode 100644 vocode/streaming/agent/prompts/action_prompt.py create mode 100644 vocode/streaming/agent/streaming_utils.py create mode 100644 vocode/streaming/agent/token_utils.py delete mode 100644 vocode/streaming/agent/utils.py create mode 100644 vocode/streaming/models/audio.py delete mode 100644 vocode/streaming/models/audio_encoding.py create mode 100644 vocode/streaming/synthesizer/abstract_factory.py create mode 100644 vocode/streaming/synthesizer/audio_cache.py create mode 100644 vocode/streaming/synthesizer/default_factory.py create mode 100644 vocode/streaming/synthesizer/eleven_labs_websocket_synthesizer.py delete mode 100644 vocode/streaming/synthesizer/factory.py create mode 100644 vocode/streaming/synthesizer/input_streaming_synthesizer.py create mode 100644 vocode/streaming/synthesizer/play_ht_synthesizer_v2.py create mode 100644 vocode/streaming/synthesizer/synthesizer_utils.py create mode 100644 vocode/streaming/telephony/client/abstract_telephony_client.py delete mode 100644 vocode/streaming/telephony/client/base_telephony_client.py create mode 100644 vocode/streaming/telephony/conversation/abstract_phone_conversation.py delete mode 100644 vocode/streaming/telephony/conversation/call.py create mode 100644 vocode/streaming/telephony/conversation/mark_message_queue.py delete mode 100644 vocode/streaming/telephony/conversation/twilio_call.py create mode 100644 vocode/streaming/telephony/conversation/twilio_phone_conversation.py delete mode 100644 vocode/streaming/telephony/conversation/vonage_call.py create mode 100644 vocode/streaming/telephony/conversation/vonage_phone_conversation.py rename vocode/streaming/telephony/templates/{connect_call.xml => twilio_connect_call.xml} (92%) delete mode 100644 vocode/streaming/transcriber/__init__.py create mode 100644 vocode/streaming/transcriber/abstract_factory.py rename vocode/streaming/transcriber/{factory.py => default_factory.py} (63%) create mode 100644 vocode/streaming/utils/async_requester.py delete mode 100644 vocode/streaming/utils/conversation_logger_adapter.py create mode 100644 vocode/streaming/utils/create_task.py delete mode 100644 vocode/streaming/utils/goodbye_model.py create mode 100644 vocode/streaming/utils/phone_numbers.py create mode 100644 vocode/streaming/utils/redis.py create mode 100644 vocode/streaming/utils/redis_conversation_message_queue.py create mode 100644 vocode/streaming/utils/singleton.py create mode 100644 vocode/streaming/utils/speed_manager.py delete mode 100644 vocode/turn_based/synthesizer/__init__.py create mode 100644 vocode/utils/sentry_utils.py diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f415eba8d..609b85d67 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,8 +12,6 @@ jobs: fail-fast: false matrix: python-version: - - "3.8" - - "3.9" - "3.10" - "3.11" poetry-version: diff --git a/apps/client_backend/Dockerfile b/apps/client_backend/Dockerfile index acaa62aa7..87c26c8ab 100644 --- a/apps/client_backend/Dockerfile +++ b/apps/client_backend/Dockerfile @@ -15,4 +15,4 @@ RUN poetry config virtualenvs.create false RUN poetry install --no-dev --no-interaction --no-ansi COPY main.py /code/main.py -CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "3000"] \ No newline at end of file +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "3000"] diff --git a/apps/client_backend/main.py b/apps/client_backend/main.py index c004d4726..0495705b0 100644 --- a/apps/client_backend/main.py +++ b/apps/client_backend/main.py @@ -1,23 +1,19 @@ -import logging +from dotenv import load_dotenv from fastapi import FastAPI -from vocode.streaming.models.agent import ChatGPTAgentConfig -from vocode.streaming.models.synthesizer import AzureSynthesizerConfig -from vocode.streaming.synthesizer.azure_synthesizer import AzureSynthesizer - +from vocode.logging import configure_pretty_logging from vocode.streaming.agent.chat_gpt_agent import ChatGPTAgent from vocode.streaming.client_backend.conversation import ConversationRouter +from vocode.streaming.models.agent import ChatGPTAgentConfig from vocode.streaming.models.message import BaseMessage - -from dotenv import load_dotenv +from vocode.streaming.models.synthesizer import AzureSynthesizerConfig +from vocode.streaming.synthesizer.azure_synthesizer import AzureSynthesizer load_dotenv() app = FastAPI(docs_url=None) -logging.basicConfig() -logger = logging.getLogger(__name__) -logger.setLevel(logging.DEBUG) +configure_pretty_logging() conversation_router = ConversationRouter( agent_thunk=lambda: ChatGPTAgent( @@ -31,7 +27,6 @@ output_audio_config, voice_name="en-US-SteffanNeural" ) ), - logger=logger, ) app.include_router(conversation_router.get_router()) diff --git a/apps/client_backend/poetry.lock b/apps/client_backend/poetry.lock index ce04d94f4..914efb029 100644 --- a/apps/client_backend/poetry.lock +++ b/apps/client_backend/poetry.lock @@ -1,93 +1,92 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. [[package]] name = "aiohttp" -version = "3.9.1" +version = "3.9.5" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.8" files = [ - {file = "aiohttp-3.9.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e1f80197f8b0b846a8d5cf7b7ec6084493950d0882cc5537fb7b96a69e3c8590"}, - {file = "aiohttp-3.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c72444d17777865734aa1a4d167794c34b63e5883abb90356a0364a28904e6c0"}, - {file = "aiohttp-3.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9b05d5cbe9dafcdc733262c3a99ccf63d2f7ce02543620d2bd8db4d4f7a22f83"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c4fa235d534b3547184831c624c0b7c1e262cd1de847d95085ec94c16fddcd5"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:289ba9ae8e88d0ba16062ecf02dd730b34186ea3b1e7489046fc338bdc3361c4"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bff7e2811814fa2271be95ab6e84c9436d027a0e59665de60edf44e529a42c1f"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81b77f868814346662c96ab36b875d7814ebf82340d3284a31681085c051320f"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b9c7426923bb7bd66d409da46c41e3fb40f5caf679da624439b9eba92043fa6"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8d44e7bf06b0c0a70a20f9100af9fcfd7f6d9d3913e37754c12d424179b4e48f"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22698f01ff5653fe66d16ffb7658f582a0ac084d7da1323e39fd9eab326a1f26"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ca7ca5abfbfe8d39e653870fbe8d7710be7a857f8a8386fc9de1aae2e02ce7e4"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:8d7f98fde213f74561be1d6d3fa353656197f75d4edfbb3d94c9eb9b0fc47f5d"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5216b6082c624b55cfe79af5d538e499cd5f5b976820eac31951fb4325974501"}, - {file = "aiohttp-3.9.1-cp310-cp310-win32.whl", hash = "sha256:0e7ba7ff228c0d9a2cd66194e90f2bca6e0abca810b786901a569c0de082f489"}, - {file = "aiohttp-3.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:c7e939f1ae428a86e4abbb9a7c4732bf4706048818dfd979e5e2839ce0159f23"}, - {file = "aiohttp-3.9.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:df9cf74b9bc03d586fc53ba470828d7b77ce51b0582d1d0b5b2fb673c0baa32d"}, - {file = "aiohttp-3.9.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ecca113f19d5e74048c001934045a2b9368d77b0b17691d905af18bd1c21275e"}, - {file = "aiohttp-3.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8cef8710fb849d97c533f259103f09bac167a008d7131d7b2b0e3a33269185c0"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bea94403a21eb94c93386d559bce297381609153e418a3ffc7d6bf772f59cc35"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91c742ca59045dce7ba76cab6e223e41d2c70d79e82c284a96411f8645e2afff"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6c93b7c2e52061f0925c3382d5cb8980e40f91c989563d3d32ca280069fd6a87"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee2527134f95e106cc1653e9ac78846f3a2ec1004cf20ef4e02038035a74544d"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11ff168d752cb41e8492817e10fb4f85828f6a0142b9726a30c27c35a1835f01"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b8c3a67eb87394386847d188996920f33b01b32155f0a94f36ca0e0c635bf3e3"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c7b5d5d64e2a14e35a9240b33b89389e0035e6de8dbb7ffa50d10d8b65c57449"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:69985d50a2b6f709412d944ffb2e97d0be154ea90600b7a921f95a87d6f108a2"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:c9110c06eaaac7e1f5562caf481f18ccf8f6fdf4c3323feab28a93d34cc646bd"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d737e69d193dac7296365a6dcb73bbbf53bb760ab25a3727716bbd42022e8d7a"}, - {file = "aiohttp-3.9.1-cp311-cp311-win32.whl", hash = "sha256:4ee8caa925aebc1e64e98432d78ea8de67b2272252b0a931d2ac3bd876ad5544"}, - {file = "aiohttp-3.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:a34086c5cc285be878622e0a6ab897a986a6e8bf5b67ecb377015f06ed316587"}, - {file = "aiohttp-3.9.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f800164276eec54e0af5c99feb9494c295118fc10a11b997bbb1348ba1a52065"}, - {file = "aiohttp-3.9.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:500f1c59906cd142d452074f3811614be04819a38ae2b3239a48b82649c08821"}, - {file = "aiohttp-3.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0b0a6a36ed7e164c6df1e18ee47afbd1990ce47cb428739d6c99aaabfaf1b3af"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69da0f3ed3496808e8cbc5123a866c41c12c15baaaead96d256477edf168eb57"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:176df045597e674fa950bf5ae536be85699e04cea68fa3a616cf75e413737eb5"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b796b44111f0cab6bbf66214186e44734b5baab949cb5fb56154142a92989aeb"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f27fdaadce22f2ef950fc10dcdf8048407c3b42b73779e48a4e76b3c35bca26c"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcb6532b9814ea7c5a6a3299747c49de30e84472fa72821b07f5a9818bce0f66"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:54631fb69a6e44b2ba522f7c22a6fb2667a02fd97d636048478db2fd8c4e98fe"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4b4c452d0190c5a820d3f5c0f3cd8a28ace48c54053e24da9d6041bf81113183"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:cae4c0c2ca800c793cae07ef3d40794625471040a87e1ba392039639ad61ab5b"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:565760d6812b8d78d416c3c7cfdf5362fbe0d0d25b82fed75d0d29e18d7fc30f"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54311eb54f3a0c45efb9ed0d0a8f43d1bc6060d773f6973efd90037a51cd0a3f"}, - {file = "aiohttp-3.9.1-cp312-cp312-win32.whl", hash = "sha256:85c3e3c9cb1d480e0b9a64c658cd66b3cfb8e721636ab8b0e746e2d79a7a9eed"}, - {file = "aiohttp-3.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:11cb254e397a82efb1805d12561e80124928e04e9c4483587ce7390b3866d213"}, - {file = "aiohttp-3.9.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8a22a34bc594d9d24621091d1b91511001a7eea91d6652ea495ce06e27381f70"}, - {file = "aiohttp-3.9.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:598db66eaf2e04aa0c8900a63b0101fdc5e6b8a7ddd805c56d86efb54eb66672"}, - {file = "aiohttp-3.9.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c9376e2b09895c8ca8b95362283365eb5c03bdc8428ade80a864160605715f1"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41473de252e1797c2d2293804e389a6d6986ef37cbb4a25208de537ae32141dd"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9c5857612c9813796960c00767645cb5da815af16dafb32d70c72a8390bbf690"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffcd828e37dc219a72c9012ec44ad2e7e3066bec6ff3aaa19e7d435dbf4032ca"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:219a16763dc0294842188ac8a12262b5671817042b35d45e44fd0a697d8c8361"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f694dc8a6a3112059258a725a4ebe9acac5fe62f11c77ac4dcf896edfa78ca28"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bcc0ea8d5b74a41b621ad4a13d96c36079c81628ccc0b30cfb1603e3dfa3a014"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:90ec72d231169b4b8d6085be13023ece8fa9b1bb495e4398d847e25218e0f431"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:cf2a0ac0615842b849f40c4d7f304986a242f1e68286dbf3bd7a835e4f83acfd"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:0e49b08eafa4f5707ecfb321ab9592717a319e37938e301d462f79b4e860c32a"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2c59e0076ea31c08553e868cec02d22191c086f00b44610f8ab7363a11a5d9d8"}, - {file = "aiohttp-3.9.1-cp38-cp38-win32.whl", hash = "sha256:4831df72b053b1eed31eb00a2e1aff6896fb4485301d4ccb208cac264b648db4"}, - {file = "aiohttp-3.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:3135713c5562731ee18f58d3ad1bf41e1d8883eb68b363f2ffde5b2ea4b84cc7"}, - {file = "aiohttp-3.9.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cfeadf42840c1e870dc2042a232a8748e75a36b52d78968cda6736de55582766"}, - {file = "aiohttp-3.9.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:70907533db712f7aa791effb38efa96f044ce3d4e850e2d7691abd759f4f0ae0"}, - {file = "aiohttp-3.9.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cdefe289681507187e375a5064c7599f52c40343a8701761c802c1853a504558"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7481f581251bb5558ba9f635db70908819caa221fc79ee52a7f58392778c636"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49f0c1b3c2842556e5de35f122fc0f0b721334ceb6e78c3719693364d4af8499"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d406b01a9f5a7e232d1b0d161b40c05275ffbcbd772dc18c1d5a570961a1ca4"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d8e4450e7fe24d86e86b23cc209e0023177b6d59502e33807b732d2deb6975f"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c0266cd6f005e99f3f51e583012de2778e65af6b73860038b968a0a8888487a"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab221850108a4a063c5b8a70f00dd7a1975e5a1713f87f4ab26a46e5feac5a0e"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c88a15f272a0ad3d7773cf3a37cc7b7d077cbfc8e331675cf1346e849d97a4e5"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:237533179d9747080bcaad4d02083ce295c0d2eab3e9e8ce103411a4312991a0"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:02ab6006ec3c3463b528374c4cdce86434e7b89ad355e7bf29e2f16b46c7dd6f"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04fa38875e53eb7e354ece1607b1d2fdee2d175ea4e4d745f6ec9f751fe20c7c"}, - {file = "aiohttp-3.9.1-cp39-cp39-win32.whl", hash = "sha256:82eefaf1a996060602f3cc1112d93ba8b201dbf5d8fd9611227de2003dddb3b7"}, - {file = "aiohttp-3.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:9b05d33ff8e6b269e30a7957bd3244ffbce2a7a35a81b81c382629b80af1a8bf"}, - {file = "aiohttp-3.9.1.tar.gz", hash = "sha256:8fc49a87ac269d4529da45871e2ffb6874e87779c3d0e2ccd813c0899221239d"}, + {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fcde4c397f673fdec23e6b05ebf8d4751314fa7c24f93334bf1f1364c1c69ac7"}, + {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d6b3f1fabe465e819aed2c421a6743d8debbde79b6a8600739300630a01bf2c"}, + {file = "aiohttp-3.9.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ae79c1bc12c34082d92bf9422764f799aee4746fd7a392db46b7fd357d4a17a"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d3ebb9e1316ec74277d19c5f482f98cc65a73ccd5430540d6d11682cd857430"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84dabd95154f43a2ea80deffec9cb44d2e301e38a0c9d331cc4aa0166fe28ae3"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8a02fbeca6f63cb1f0475c799679057fc9268b77075ab7cf3f1c600e81dd46b"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c26959ca7b75ff768e2776d8055bf9582a6267e24556bb7f7bd29e677932be72"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:714d4e5231fed4ba2762ed489b4aec07b2b9953cf4ee31e9871caac895a839c0"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7a6a8354f1b62e15d48e04350f13e726fa08b62c3d7b8401c0a1314f02e3558"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c413016880e03e69d166efb5a1a95d40f83d5a3a648d16486592c49ffb76d0db"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ff84aeb864e0fac81f676be9f4685f0527b660f1efdc40dcede3c251ef1e867f"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ad7f2919d7dac062f24d6f5fe95d401597fbb015a25771f85e692d043c9d7832"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:702e2c7c187c1a498a4e2b03155d52658fdd6fda882d3d7fbb891a5cf108bb10"}, + {file = "aiohttp-3.9.5-cp310-cp310-win32.whl", hash = "sha256:67c3119f5ddc7261d47163ed86d760ddf0e625cd6246b4ed852e82159617b5fb"}, + {file = "aiohttp-3.9.5-cp310-cp310-win_amd64.whl", hash = "sha256:471f0ef53ccedec9995287f02caf0c068732f026455f07db3f01a46e49d76bbb"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ae53e33ee7476dd3d1132f932eeb39bf6125083820049d06edcdca4381f342"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c088c4d70d21f8ca5c0b8b5403fe84a7bc8e024161febdd4ef04575ef35d474d"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:639d0042b7670222f33b0028de6b4e2fad6451462ce7df2af8aee37dcac55424"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f26383adb94da5e7fb388d441bf09c61e5e35f455a3217bfd790c6b6bc64b2ee"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66331d00fb28dc90aa606d9a54304af76b335ae204d1836f65797d6fe27f1ca2"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ff550491f5492ab5ed3533e76b8567f4b37bd2995e780a1f46bca2024223233"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f22eb3a6c1080d862befa0a89c380b4dafce29dc6cd56083f630073d102eb595"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a81b1143d42b66ffc40a441379387076243ef7b51019204fd3ec36b9f69e77d6"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f64fd07515dad67f24b6ea4a66ae2876c01031de91c93075b8093f07c0a2d93d"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:93e22add827447d2e26d67c9ac0161756007f152fdc5210277d00a85f6c92323"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:55b39c8684a46e56ef8c8d24faf02de4a2b2ac60d26cee93bc595651ff545de9"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4715a9b778f4293b9f8ae7a0a7cef9829f02ff8d6277a39d7f40565c737d3771"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:afc52b8d969eff14e069a710057d15ab9ac17cd4b6753042c407dcea0e40bf75"}, + {file = "aiohttp-3.9.5-cp311-cp311-win32.whl", hash = "sha256:b3df71da99c98534be076196791adca8819761f0bf6e08e07fd7da25127150d6"}, + {file = "aiohttp-3.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:88e311d98cc0bf45b62fc46c66753a83445f5ab20038bcc1b8a1cc05666f428a"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c7a4b7a6cf5b6eb11e109a9755fd4fda7d57395f8c575e166d363b9fc3ec4678"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0a158704edf0abcac8ac371fbb54044f3270bdbc93e254a82b6c82be1ef08f3c"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d153f652a687a8e95ad367a86a61e8d53d528b0530ef382ec5aaf533140ed00f"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82a6a97d9771cb48ae16979c3a3a9a18b600a8505b1115cfe354dfb2054468b4"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60cdbd56f4cad9f69c35eaac0fbbdf1f77b0ff9456cebd4902f3dd1cf096464c"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8676e8fd73141ded15ea586de0b7cda1542960a7b9ad89b2b06428e97125d4fa"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da00da442a0e31f1c69d26d224e1efd3a1ca5bcbf210978a2ca7426dfcae9f58"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18f634d540dd099c262e9f887c8bbacc959847cfe5da7a0e2e1cf3f14dbf2daf"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:320e8618eda64e19d11bdb3bd04ccc0a816c17eaecb7e4945d01deee2a22f95f"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:2faa61a904b83142747fc6a6d7ad8fccff898c849123030f8e75d5d967fd4a81"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:8c64a6dc3fe5db7b1b4d2b5cb84c4f677768bdc340611eca673afb7cf416ef5a"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:393c7aba2b55559ef7ab791c94b44f7482a07bf7640d17b341b79081f5e5cd1a"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c671dc117c2c21a1ca10c116cfcd6e3e44da7fcde37bf83b2be485ab377b25da"}, + {file = "aiohttp-3.9.5-cp312-cp312-win32.whl", hash = "sha256:5a7ee16aab26e76add4afc45e8f8206c95d1d75540f1039b84a03c3b3800dd59"}, + {file = "aiohttp-3.9.5-cp312-cp312-win_amd64.whl", hash = "sha256:5ca51eadbd67045396bc92a4345d1790b7301c14d1848feaac1d6a6c9289e888"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:694d828b5c41255e54bc2dddb51a9f5150b4eefa9886e38b52605a05d96566e8"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0605cc2c0088fcaae79f01c913a38611ad09ba68ff482402d3410bf59039bfb8"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4558e5012ee03d2638c681e156461d37b7a113fe13970d438d95d10173d25f78"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dbc053ac75ccc63dc3a3cc547b98c7258ec35a215a92bd9f983e0aac95d3d5b"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4109adee842b90671f1b689901b948f347325045c15f46b39797ae1bf17019de"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6ea1a5b409a85477fd8e5ee6ad8f0e40bf2844c270955e09360418cfd09abac"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3c2890ca8c59ee683fd09adf32321a40fe1cf164e3387799efb2acebf090c11"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3916c8692dbd9d55c523374a3b8213e628424d19116ac4308e434dbf6d95bbdd"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8d1964eb7617907c792ca00b341b5ec3e01ae8c280825deadbbd678447b127e1"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5ab8e1f6bee051a4bf6195e38a5c13e5e161cb7bad83d8854524798bd9fcd6e"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:52c27110f3862a1afbcb2af4281fc9fdc40327fa286c4625dfee247c3ba90156"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:7f64cbd44443e80094309875d4f9c71d0401e966d191c3d469cde4642bc2e031"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8b4f72fbb66279624bfe83fd5eb6aea0022dad8eec62b71e7bf63ee1caadeafe"}, + {file = "aiohttp-3.9.5-cp38-cp38-win32.whl", hash = "sha256:6380c039ec52866c06d69b5c7aad5478b24ed11696f0e72f6b807cfb261453da"}, + {file = "aiohttp-3.9.5-cp38-cp38-win_amd64.whl", hash = "sha256:da22dab31d7180f8c3ac7c7635f3bcd53808f374f6aa333fe0b0b9e14b01f91a"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1732102949ff6087589408d76cd6dea656b93c896b011ecafff418c9661dc4ed"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c6021d296318cb6f9414b48e6a439a7f5d1f665464da507e8ff640848ee2a58a"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:239f975589a944eeb1bad26b8b140a59a3a320067fb3cd10b75c3092405a1372"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b7b30258348082826d274504fbc7c849959f1989d86c29bc355107accec6cfb"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd2adf5c87ff6d8b277814a28a535b59e20bfea40a101db6b3bdca7e9926bc24"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9a3d838441bebcf5cf442700e3963f58b5c33f015341f9ea86dcd7d503c07e2"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e3a1ae66e3d0c17cf65c08968a5ee3180c5a95920ec2731f53343fac9bad106"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c69e77370cce2d6df5d12b4e12bdcca60c47ba13d1cbbc8645dd005a20b738b"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf56238f4bbf49dab8c2dc2e6b1b68502b1e88d335bea59b3f5b9f4c001475"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d1469f228cd9ffddd396d9948b8c9cd8022b6d1bf1e40c6f25b0fb90b4f893ed"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:45731330e754f5811c314901cebdf19dd776a44b31927fa4b4dbecab9e457b0c"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3fcb4046d2904378e3aeea1df51f697b0467f2aac55d232c87ba162709478c46"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8cf142aa6c1a751fcb364158fd710b8a9be874b81889c2bd13aa8893197455e2"}, + {file = "aiohttp-3.9.5-cp39-cp39-win32.whl", hash = "sha256:7b179eea70833c8dee51ec42f3b4097bd6370892fa93f510f76762105568cf09"}, + {file = "aiohttp-3.9.5-cp39-cp39-win_amd64.whl", hash = "sha256:38d80498e2e169bc61418ff36170e0aad0cd268da8b38a17c4cf29d254a8b3f1"}, + {file = "aiohttp-3.9.5.tar.gz", hash = "sha256:edea7d15772ceeb29db4aff55e482d4bcfb6ae160ce144f2682de02f6d693551"}, ] [package.dependencies] aiosignal = ">=1.1.2" -async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""} attrs = ">=17.3.0" frozenlist = ">=1.1.1" multidict = ">=4.5,<7.0" @@ -96,6 +95,20 @@ yarl = ">=1.0,<2.0" [package.extras] speedups = ["Brotli", "aiodns", "brotlicffi"] +[[package]] +name = "aiohttp-retry" +version = "2.8.3" +description = "Simple retry client for aiohttp" +optional = false +python-versions = ">=3.7" +files = [ + {file = "aiohttp_retry-2.8.3-py3-none-any.whl", hash = "sha256:3aeeead8f6afe48272db93ced9440cf4eda8b6fd7ee2abb25357b7eb28525b45"}, + {file = "aiohttp_retry-2.8.3.tar.gz", hash = "sha256:9a8e637e31682ad36e1ff9f8bcba912fcfc7d7041722bc901a4b948da4d71ea9"}, +] + +[package.dependencies] +aiohttp = "*" + [[package]] name = "aiosignal" version = "1.3.1" @@ -111,41 +124,54 @@ files = [ frozenlist = ">=1.1.0" [[package]] -name = "anthropic" -version = "0.2.10" -description = "Library for accessing the anthropic API" +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" files = [ - {file = "anthropic-0.2.10-py3-none-any.whl", hash = "sha256:a007496207fd186b0bcb9592b00ca130069d2a427f3d6f602a61dbbd1ac6316e"}, - {file = "anthropic-0.2.10.tar.gz", hash = "sha256:e4da061a86d8ffb86072c0b0feaf219a3a4f7dfddd4224df9ba769e469498c19"}, + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, +] + +[[package]] +name = "anthropic" +version = "0.28.0" +description = "The official Python library for the anthropic API" +optional = false +python-versions = ">=3.7" +files = [ + {file = "anthropic-0.28.0-py3-none-any.whl", hash = "sha256:2b620b21aee3d20c5d8005483c34df239d53ae895687113b26b8a36892a7e20f"}, ] [package.dependencies] -aiohttp = "*" -httpx = "*" -requests = "*" -tokenizers = "*" +anyio = ">=3.5.0,<5" +distro = ">=1.7.0,<2" +httpx = ">=0.23.0,<1" +jiter = ">=0.4.0,<1" +pydantic = ">=1.9.0,<3" +sniffio = "*" +tokenizers = ">=0.13.0" +typing-extensions = ">=4.7,<5" [package.extras] -dev = ["black (>=22.3.0)", "pytest"] +bedrock = ["boto3 (>=1.28.57)", "botocore (>=1.31.57)"] +vertex = ["google-auth (>=2,<3)"] [[package]] name = "anyio" -version = "4.2.0" +version = "4.4.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.8" files = [ - {file = "anyio-4.2.0-py3-none-any.whl", hash = "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee"}, - {file = "anyio-4.2.0.tar.gz", hash = "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f"}, + {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, + {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, ] [package.dependencies] -exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" sniffio = ">=1.1" -typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} [package.extras] doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] @@ -202,28 +228,39 @@ tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "p [[package]] name = "azure-cognitiveservices-speech" -version = "1.34.1" +version = "1.37.0" description = "Microsoft Cognitive Services Speech SDK for Python" optional = false python-versions = ">=3.7" files = [ - {file = "azure_cognitiveservices_speech-1.34.1-py3-none-macosx_10_14_x86_64.whl", hash = "sha256:f0bbdb78b6c48b34b870bb05e7085ae277ef230425b86e25ac62f808480bbbbf"}, - {file = "azure_cognitiveservices_speech-1.34.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:501be52021acea776c23e1fae3fc08b65801008dc6d919959758723ee8114fbf"}, - {file = "azure_cognitiveservices_speech-1.34.1-py3-none-manylinux1_x86_64.whl", hash = "sha256:d28ec35b4e88d5205dda2afb401588d185dabeede9a16432d53f8751bcf853ba"}, - {file = "azure_cognitiveservices_speech-1.34.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:12a243371a133d0299fcebb067ed93e989fdeaa163b5dcf63f6f2d6a2ebcb8e7"}, - {file = "azure_cognitiveservices_speech-1.34.1-py3-none-win32.whl", hash = "sha256:cd0d4b84b6fd1657ad1f2b088fa83bb851c6f1568b514d92f265d9e958e7f83f"}, - {file = "azure_cognitiveservices_speech-1.34.1-py3-none-win_amd64.whl", hash = "sha256:21a1fc84eca697332862af0a1fafe0766e9742c91848e0c3a6cf4f883081721d"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-macosx_10_14_x86_64.whl", hash = "sha256:906d6bf65176e93464e2d763dd074ca00c48cfe1a896371fcdcb155a500910f7"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:54ec8dd55d4dbd9058c61909e08485d3761d6d30954da189e1b17d84daf5e2e0"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:685424689725d2d4115485998c0888c8b5b502259037ff533e5a834575f80b66"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:384f66786c2335165035270897b34d0b91736a1fdf38f7696e9a227075cb2489"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-win32.whl", hash = "sha256:343d5f449ccd6c9b53cd37dd46a70ece0905243517df7a0c047779e55072254c"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-win_amd64.whl", hash = "sha256:a18fb45490cdcd681407ccaad9560fb14dda1c8276de297e219ea1a880467e28"}, +] + +[[package]] +name = "cachetools" +version = "5.3.3" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cachetools-5.3.3-py3-none-any.whl", hash = "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945"}, + {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, ] [[package]] name = "certifi" -version = "2023.11.17" +version = "2024.2.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, - {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, ] [[package]] @@ -414,15 +451,69 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "cryptography" +version = "42.0.7" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +optional = false +python-versions = ">=3.7" +files = [ + {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"}, + {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"}, + {file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"}, + {file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"}, + {file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"}, + {file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"}, + {file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"}, + {file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"}, +] + +[package.dependencies] +cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} + +[package.extras] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] +docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"] +nox = ["nox"] +pep8test = ["check-sdist", "click", "mypy", "ruff"] +sdist = ["build"] +ssh = ["bcrypt (>=3.1.5)"] +test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test-randomorder = ["pytest-randomly"] + [[package]] name = "dataclasses-json" -version = "0.5.14" +version = "0.6.6" description = "Easily serialize dataclasses to and from JSON." optional = false -python-versions = ">=3.7,<3.13" +python-versions = "<4.0,>=3.7" files = [ - {file = "dataclasses_json-0.5.14-py3-none-any.whl", hash = "sha256:5ec6fed642adb1dbdb4182badb01e0861badfd8fda82e3b67f44b2d1e9d10d21"}, - {file = "dataclasses_json-0.5.14.tar.gz", hash = "sha256:d82896a94c992ffaf689cd1fafc180164e2abdd415b8f94a7f78586af5886236"}, + {file = "dataclasses_json-0.6.6-py3-none-any.whl", hash = "sha256:e54c5c87497741ad454070ba0ed411523d46beb5da102e221efb873801b0ba85"}, + {file = "dataclasses_json-0.6.6.tar.gz", hash = "sha256:0c09827d26fffda27f1be2fed7a7a01a29c5ddcd2eb6393ad5ebf9d77e9deae8"}, ] [package.dependencies] @@ -457,32 +548,80 @@ wrapt = ">=1.10,<2" [package.extras] dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] +[[package]] +name = "distro" +version = "1.9.0" +description = "Distro - an OS platform information API" +optional = false +python-versions = ">=3.6" +files = [ + {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, + {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, +] + +[[package]] +name = "dnspython" +version = "2.6.1" +description = "DNS toolkit" +optional = false +python-versions = ">=3.8" +files = [ + {file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"}, + {file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"}, +] + +[package.extras] +dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "sphinx (>=7.2.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"] +dnssec = ["cryptography (>=41)"] +doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"] +doq = ["aioquic (>=0.9.25)"] +idna = ["idna (>=3.6)"] +trio = ["trio (>=0.23)"] +wmi = ["wmi (>=1.5.1)"] + [[package]] name = "elevenlabs" -version = "0.2.24" -description = "The official elevenlabs python package." +version = "1.2.2" +description = "" optional = false -python-versions = "*" +python-versions = "<4.0,>=3.8" files = [ - {file = "elevenlabs-0.2.24-py3-none-any.whl", hash = "sha256:f1dc780e50ace7a499717cc67485b87bf5cd806a2711fca7a4fbf1b8b9f3a41c"}, - {file = "elevenlabs-0.2.24.tar.gz", hash = "sha256:7719816f8d74666c0da5567e737b6c0200f2807bed9d9c21ed750f14e8a3669d"}, + {file = "elevenlabs-1.2.2-py3-none-any.whl", hash = "sha256:60b92b0e2aabdfba93a43569f207f8a2ad397492519b8e11a2eebb32807ddefa"}, + {file = "elevenlabs-1.2.2.tar.gz", hash = "sha256:ebd02869b95602b8956874dd727981bb49ad16b9a3c2f5901193d838213694aa"}, ] [package.dependencies] +httpx = ">=0.21.2" ipython = ">=7.0" -pydantic = ">=1.10,<2.0" +pydantic = ">=1.9.2" requests = ">=2.20" +typing_extensions = ">=4.0.0" websockets = ">=11.0" +[[package]] +name = "email-validator" +version = "2.1.1" +description = "A robust email address syntax and deliverability validation library." +optional = false +python-versions = ">=3.8" +files = [ + {file = "email_validator-2.1.1-py3-none-any.whl", hash = "sha256:97d882d174e2a65732fb43bfce81a3a834cbc1bde8bf419e30ef5ea976370a05"}, + {file = "email_validator-2.1.1.tar.gz", hash = "sha256:200a70680ba08904be6d1eef729205cc0d687634399a5924d842533efb824b84"}, +] + +[package.dependencies] +dnspython = ">=2.0.0" +idna = ">=2.0.0" + [[package]] name = "exceptiongroup" -version = "1.2.0" +version = "1.2.1" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, - {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, + {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, + {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, ] [package.extras] @@ -504,37 +643,62 @@ tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipyth [[package]] name = "fastapi" -version = "0.100.1" +version = "0.111.0" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "fastapi-0.100.1-py3-none-any.whl", hash = "sha256:ec6dd52bfc4eff3063cfcd0713b43c87640fefb2687bbbe3d8a08d94049cdf32"}, - {file = "fastapi-0.100.1.tar.gz", hash = "sha256:522700d7a469e4a973d92321ab93312448fbe20fca9c8da97effc7e7bc56df23"}, + {file = "fastapi-0.111.0-py3-none-any.whl", hash = "sha256:97ecbf994be0bcbdadedf88c3150252bed7b2087075ac99735403b1b76cc8fc0"}, + {file = "fastapi-0.111.0.tar.gz", hash = "sha256:b9db9dd147c91cb8b769f7183535773d8741dd46f9dc6676cd82eab510228cd7"}, ] [package.dependencies] -pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<3.0.0" -starlette = ">=0.27.0,<0.28.0" -typing-extensions = ">=4.5.0" +email_validator = ">=2.0.0" +fastapi-cli = ">=0.0.2" +httpx = ">=0.23.0" +jinja2 = ">=2.11.2" +orjson = ">=3.2.1" +pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" +python-multipart = ">=0.0.7" +starlette = ">=0.37.2,<0.38.0" +typing-extensions = ">=4.8.0" +ujson = ">=4.0.1,<4.0.2 || >4.0.2,<4.1.0 || >4.1.0,<4.2.0 || >4.2.0,<4.3.0 || >4.3.0,<5.0.0 || >5.0.0,<5.1.0 || >5.1.0" +uvicorn = {version = ">=0.12.0", extras = ["standard"]} [package.extras] -all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +all = ["email_validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] + +[[package]] +name = "fastapi-cli" +version = "0.0.4" +description = "Run and manage FastAPI apps from the command line with FastAPI CLI. 🚀" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fastapi_cli-0.0.4-py3-none-any.whl", hash = "sha256:a2552f3a7ae64058cdbb530be6fa6dbfc975dc165e4fa66d224c3d396e25e809"}, + {file = "fastapi_cli-0.0.4.tar.gz", hash = "sha256:e2e9ffaffc1f7767f488d6da34b6f5a377751c996f397902eb6abb99a67bde32"}, +] + +[package.dependencies] +typer = ">=0.12.3" + +[package.extras] +standard = ["fastapi", "uvicorn[standard] (>=0.15.0)"] [[package]] name = "filelock" -version = "3.13.1" +version = "3.14.0" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"}, - {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"}, + {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"}, + {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"}, ] [package.extras] -docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] typing = ["typing-extensions (>=4.8)"] [[package]] @@ -625,13 +789,13 @@ files = [ [[package]] name = "fsspec" -version = "2023.12.2" +version = "2024.5.0" description = "File-system specification" optional = false python-versions = ">=3.8" files = [ - {file = "fsspec-2023.12.2-py3-none-any.whl", hash = "sha256:d800d87f72189a745fa3d6b033b9dc4a34ad069f60ca60b943a63599f5501960"}, - {file = "fsspec-2023.12.2.tar.gz", hash = "sha256:8548d39e8810b59c38014934f6b31e57f40c1b20f911f4cc2b85389c7e9bf0cb"}, + {file = "fsspec-2024.5.0-py3-none-any.whl", hash = "sha256:e0fdbc446d67e182f49a70b82cf7889028a63588fde6b222521f10937b2b670c"}, + {file = "fsspec-2024.5.0.tar.gz", hash = "sha256:1d021b0b0f933e3b3029ed808eb400c08ba101ca2de4b3483fbc9ca23fcee94a"}, ] [package.extras] @@ -639,7 +803,7 @@ abfs = ["adlfs"] adl = ["adlfs"] arrow = ["pyarrow (>=1)"] dask = ["dask", "distributed"] -devel = ["pytest", "pytest-cov"] +dev = ["pre-commit", "ruff"] dropbox = ["dropbox", "dropboxdrivefs", "requests"] full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] fuse = ["fusepy"] @@ -649,15 +813,117 @@ github = ["requests"] gs = ["gcsfs"] gui = ["panel"] hdfs = ["pyarrow (>=1)"] -http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)", "requests"] +http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)"] libarchive = ["libarchive-c"] oci = ["ocifs"] s3 = ["s3fs"] sftp = ["paramiko"] smb = ["smbprotocol"] ssh = ["paramiko"] +test = ["aiohttp (!=4.0.0a0,!=4.0.0a1)", "numpy", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "requests"] +test-downstream = ["aiobotocore (>=2.5.4,<3.0.0)", "dask-expr", "dask[dataframe,test]", "moto[server] (>4,<5)", "pytest-timeout", "xarray"] +test-full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "cloudpickle", "dask", "distributed", "dropbox", "dropboxdrivefs", "fastparquet", "fusepy", "gcsfs", "jinja2", "kerchunk", "libarchive-c", "lz4", "notebook", "numpy", "ocifs", "pandas", "panel", "paramiko", "pyarrow", "pyarrow (>=1)", "pyftpdlib", "pygit2", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "python-snappy", "requests", "smbprotocol", "tqdm", "urllib3", "zarr", "zstandard"] tqdm = ["tqdm"] +[[package]] +name = "google-api-core" +version = "2.19.0" +description = "Google API client core library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-api-core-2.19.0.tar.gz", hash = "sha256:cf1b7c2694047886d2af1128a03ae99e391108a08804f87cfd35970e49c9cd10"}, + {file = "google_api_core-2.19.0-py3-none-any.whl", hash = "sha256:8661eec4078c35428fd3f69a2c7ee29e342896b70f01d1a1cbcb334372dd6251"}, +] + +[package.dependencies] +google-auth = ">=2.14.1,<3.0.dev0" +googleapis-common-protos = ">=1.56.2,<2.0.dev0" +grpcio = {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""} +grpcio-status = {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""} +proto-plus = ">=1.22.3,<2.0.0dev" +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" +requests = ">=2.18.0,<3.0.0.dev0" + +[package.extras] +grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "grpcio-status (>=1.33.2,<2.0.dev0)", "grpcio-status (>=1.49.1,<2.0.dev0)"] +grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] +grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] + +[[package]] +name = "google-auth" +version = "2.29.0" +description = "Google Authentication Library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-auth-2.29.0.tar.gz", hash = "sha256:672dff332d073227550ffc7457868ac4218d6c500b155fe6cc17d2b13602c360"}, + {file = "google_auth-2.29.0-py2.py3-none-any.whl", hash = "sha256:d452ad095688cd52bae0ad6fafe027f6a6d6f560e810fec20914e17a09526415"}, +] + +[package.dependencies] +cachetools = ">=2.0.0,<6.0" +pyasn1-modules = ">=0.2.1" +rsa = ">=3.1.4,<5" + +[package.extras] +aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"] +enterprise-cert = ["cryptography (==36.0.2)", "pyopenssl (==22.0.0)"] +pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] +reauth = ["pyu2f (>=0.1.5)"] +requests = ["requests (>=2.20.0,<3.0.0.dev0)"] + +[[package]] +name = "google-cloud-speech" +version = "2.26.0" +description = "Google Cloud Speech API client library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-cloud-speech-2.26.0.tar.gz", hash = "sha256:d3156a78496aeacff403429408a1b13efe996da6f0544a25567904ad801671d5"}, + {file = "google_cloud_speech-2.26.0-py2.py3-none-any.whl", hash = "sha256:8b61aebcbcc9bd5450933c94c431584a07667e022d12834f9037bb2c0e673c87"}, +] + +[package.dependencies] +google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} +google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev" +proto-plus = ">=1.22.3,<2.0.0dev" +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" + +[[package]] +name = "google-cloud-texttospeech" +version = "2.16.3" +description = "Google Cloud Texttospeech API client library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-cloud-texttospeech-2.16.3.tar.gz", hash = "sha256:fabc315032d137da0710bb4c268734d336212d8fa8316b23b277dd3a84ce721c"}, + {file = "google_cloud_texttospeech-2.16.3-py2.py3-none-any.whl", hash = "sha256:5d1e23f9270908a5d7ecf2af04105fbd3a7ddde60fe48506e397bd18c1ece499"}, +] + +[package.dependencies] +google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} +google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev" +proto-plus = ">=1.22.3,<2.0.0dev" +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" + +[[package]] +name = "googleapis-common-protos" +version = "1.63.0" +description = "Common protobufs used in Google APIs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "googleapis-common-protos-1.63.0.tar.gz", hash = "sha256:17ad01b11d5f1d0171c06d3ba5c04c54474e883b66b949722b4938ee2694ef4e"}, + {file = "googleapis_common_protos-1.63.0-py2.py3-none-any.whl", hash = "sha256:ae45f75702f7c08b541f750854a678bd8f534a1a6bace6afe975f1d0a82d6632"}, +] + +[package.dependencies] +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" + +[package.extras] +grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] + [[package]] name = "greenlet" version = "3.0.3" @@ -729,6 +995,80 @@ files = [ docs = ["Sphinx", "furo"] test = ["objgraph", "psutil"] +[[package]] +name = "grpcio" +version = "1.64.0" +description = "HTTP/2-based RPC framework" +optional = false +python-versions = ">=3.8" +files = [ + {file = "grpcio-1.64.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:3b09c3d9de95461214a11d82cc0e6a46a6f4e1f91834b50782f932895215e5db"}, + {file = "grpcio-1.64.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:7e013428ab472892830287dd082b7d129f4d8afef49227a28223a77337555eaa"}, + {file = "grpcio-1.64.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:02cc9cc3f816d30f7993d0d408043b4a7d6a02346d251694d8ab1f78cc723e7e"}, + {file = "grpcio-1.64.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f5de082d936e0208ce8db9095821361dfa97af8767a6607ae71425ac8ace15c"}, + {file = "grpcio-1.64.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7b7bf346391dffa182fba42506adf3a84f4a718a05e445b37824136047686a1"}, + {file = "grpcio-1.64.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b2cbdfba18408389a1371f8c2af1659119e1831e5ed24c240cae9e27b4abc38d"}, + {file = "grpcio-1.64.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:aca4f15427d2df592e0c8f3d38847e25135e4092d7f70f02452c0e90d6a02d6d"}, + {file = "grpcio-1.64.0-cp310-cp310-win32.whl", hash = "sha256:7c1f5b2298244472bcda49b599be04579f26425af0fd80d3f2eb5fd8bc84d106"}, + {file = "grpcio-1.64.0-cp310-cp310-win_amd64.whl", hash = "sha256:73f84f9e5985a532e47880b3924867de16fa1aa513fff9b26106220c253c70c5"}, + {file = "grpcio-1.64.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:2a18090371d138a57714ee9bffd6c9c9cb2e02ce42c681aac093ae1e7189ed21"}, + {file = "grpcio-1.64.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:59c68df3a934a586c3473d15956d23a618b8f05b5e7a3a904d40300e9c69cbf0"}, + {file = "grpcio-1.64.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:b52e1ec7185512103dd47d41cf34ea78e7a7361ba460187ddd2416b480e0938c"}, + {file = "grpcio-1.64.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d598b5d5e2c9115d7fb7e2cb5508d14286af506a75950762aa1372d60e41851"}, + {file = "grpcio-1.64.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01615bbcae6875eee8091e6b9414072f4e4b00d8b7e141f89635bdae7cf784e5"}, + {file = "grpcio-1.64.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0b2dfe6dcace264807d9123d483d4c43274e3f8c39f90ff51de538245d7a4145"}, + {file = "grpcio-1.64.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7f17572dc9acd5e6dfd3014d10c0b533e9f79cd9517fc10b0225746f4c24b58e"}, + {file = "grpcio-1.64.0-cp311-cp311-win32.whl", hash = "sha256:6ec5ed15b4ffe56e2c6bc76af45e6b591c9be0224b3fb090adfb205c9012367d"}, + {file = "grpcio-1.64.0-cp311-cp311-win_amd64.whl", hash = "sha256:597191370951b477b7a1441e1aaa5cacebeb46a3b0bd240ec3bb2f28298c7553"}, + {file = "grpcio-1.64.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:1ce4cd5a61d4532651079e7aae0fedf9a80e613eed895d5b9743e66b52d15812"}, + {file = "grpcio-1.64.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:650a8150a9b288f40d5b7c1d5400cc11724eae50bd1f501a66e1ea949173649b"}, + {file = "grpcio-1.64.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:8de0399b983f8676a7ccfdd45e5b2caec74a7e3cc576c6b1eecf3b3680deda5e"}, + {file = "grpcio-1.64.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:46b8b43ba6a2a8f3103f103f97996cad507bcfd72359af6516363c48793d5a7b"}, + {file = "grpcio-1.64.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a54362f03d4dcfae63be455d0a7d4c1403673498b92c6bfe22157d935b57c7a9"}, + {file = "grpcio-1.64.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1f8ea18b928e539046bb5f9c124d717fbf00cc4b2d960ae0b8468562846f5aa1"}, + {file = "grpcio-1.64.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c56c91bd2923ddb6e7ed28ebb66d15633b03e0df22206f22dfcdde08047e0a48"}, + {file = "grpcio-1.64.0-cp312-cp312-win32.whl", hash = "sha256:874c741c8a66f0834f653a69e7e64b4e67fcd4a8d40296919b93bab2ccc780ba"}, + {file = "grpcio-1.64.0-cp312-cp312-win_amd64.whl", hash = "sha256:0da1d921f8e4bcee307aeef6c7095eb26e617c471f8cb1c454fd389c5c296d1e"}, + {file = "grpcio-1.64.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:c46fb6bfca17bfc49f011eb53416e61472fa96caa0979b4329176bdd38cbbf2a"}, + {file = "grpcio-1.64.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3d2004e85cf5213995d09408501f82c8534700d2babeb81dfdba2a3bff0bb396"}, + {file = "grpcio-1.64.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:6d5541eb460d73a07418524fb64dcfe0adfbcd32e2dac0f8f90ce5b9dd6c046c"}, + {file = "grpcio-1.64.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f279ad72dd7d64412e10f2443f9f34872a938c67387863c4cd2fb837f53e7d2"}, + {file = "grpcio-1.64.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85fda90b81da25993aa47fae66cae747b921f8f6777550895fb62375b776a231"}, + {file = "grpcio-1.64.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a053584079b793a54bece4a7d1d1b5c0645bdbee729215cd433703dc2532f72b"}, + {file = "grpcio-1.64.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:579dd9fb11bc73f0de061cab5f8b2def21480fd99eb3743ed041ad6a1913ee2f"}, + {file = "grpcio-1.64.0-cp38-cp38-win32.whl", hash = "sha256:23b6887bb21d77649d022fa1859e05853fdc2e60682fd86c3db652a555a282e0"}, + {file = "grpcio-1.64.0-cp38-cp38-win_amd64.whl", hash = "sha256:753cb58683ba0c545306f4e17dabf468d29cb6f6b11832e1e432160bb3f8403c"}, + {file = "grpcio-1.64.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:2186d76a7e383e1466e0ea2b0febc343ffeae13928c63c6ec6826533c2d69590"}, + {file = "grpcio-1.64.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0f30596cdcbed3c98024fb4f1d91745146385b3f9fd10c9f2270cbfe2ed7ed91"}, + {file = "grpcio-1.64.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:d9171f025a196f5bcfec7e8e7ffb7c3535f7d60aecd3503f9e250296c7cfc150"}, + {file = "grpcio-1.64.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf4c8daed18ae2be2f1fc7d613a76ee2a2e28fdf2412d5c128be23144d28283d"}, + {file = "grpcio-1.64.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3550493ac1d23198d46dc9c9b24b411cef613798dc31160c7138568ec26bc9b4"}, + {file = "grpcio-1.64.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3161a8f8bb38077a6470508c1a7301cd54301c53b8a34bb83e3c9764874ecabd"}, + {file = "grpcio-1.64.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e8fabe2cc57a369638ab1ad8e6043721014fdf9a13baa7c0e35995d3a4a7618"}, + {file = "grpcio-1.64.0-cp39-cp39-win32.whl", hash = "sha256:31890b24d47b62cc27da49a462efe3d02f3c120edb0e6c46dcc0025506acf004"}, + {file = "grpcio-1.64.0-cp39-cp39-win_amd64.whl", hash = "sha256:5a56797dea8c02e7d3a85dfea879f286175cf4d14fbd9ab3ef2477277b927baa"}, + {file = "grpcio-1.64.0.tar.gz", hash = "sha256:257baf07f53a571c215eebe9679c3058a313fd1d1f7c4eede5a8660108c52d9c"}, +] + +[package.extras] +protobuf = ["grpcio-tools (>=1.64.0)"] + +[[package]] +name = "grpcio-status" +version = "1.62.2" +description = "Status proto mapping for gRPC" +optional = false +python-versions = ">=3.6" +files = [ + {file = "grpcio-status-1.62.2.tar.gz", hash = "sha256:62e1bfcb02025a1cd73732a2d33672d3e9d0df4d21c12c51e0bbcaf09bab742a"}, + {file = "grpcio_status-1.62.2-py3-none-any.whl", hash = "sha256:206ddf0eb36bc99b033f03b2c8e95d319f0044defae9b41ae21408e7e0cda48f"}, +] + +[package.dependencies] +googleapis-common-protos = ">=1.5.5" +grpcio = ">=1.62.2" +protobuf = ">=4.21.6" + [[package]] name = "h11" version = "0.14.0" @@ -742,13 +1082,13 @@ files = [ [[package]] name = "httpcore" -version = "1.0.2" +version = "1.0.5" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpcore-1.0.2-py3-none-any.whl", hash = "sha256:096cc05bca73b8e459a1fc3dcf585148f63e534eae4339559c9b8a8d6399acc7"}, - {file = "httpcore-1.0.2.tar.gz", hash = "sha256:9fc092e4799b26174648e54b74ed5f683132a464e95643b226e00c2ed2fa6535"}, + {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, + {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, ] [package.dependencies] @@ -759,17 +1099,65 @@ h11 = ">=0.13,<0.15" asyncio = ["anyio (>=4.0,<5.0)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<0.23.0)"] +trio = ["trio (>=0.22.0,<0.26.0)"] + +[[package]] +name = "httptools" +version = "0.6.1" +description = "A collection of framework independent HTTP protocol utils." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d2f6c3c4cb1948d912538217838f6e9960bc4a521d7f9b323b3da579cd14532f"}, + {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:00d5d4b68a717765b1fabfd9ca755bd12bf44105eeb806c03d1962acd9b8e563"}, + {file = "httptools-0.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:639dc4f381a870c9ec860ce5c45921db50205a37cc3334e756269736ff0aac58"}, + {file = "httptools-0.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e57997ac7fb7ee43140cc03664de5f268813a481dff6245e0075925adc6aa185"}, + {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0ac5a0ae3d9f4fe004318d64b8a854edd85ab76cffbf7ef5e32920faef62f142"}, + {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3f30d3ce413088a98b9db71c60a6ada2001a08945cb42dd65a9a9fe228627658"}, + {file = "httptools-0.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:1ed99a373e327f0107cb513b61820102ee4f3675656a37a50083eda05dc9541b"}, + {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7a7ea483c1a4485c71cb5f38be9db078f8b0e8b4c4dc0210f531cdd2ddac1ef1"}, + {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:85ed077c995e942b6f1b07583e4eb0a8d324d418954fc6af913d36db7c05a5a0"}, + {file = "httptools-0.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b0bb634338334385351a1600a73e558ce619af390c2b38386206ac6a27fecfc"}, + {file = "httptools-0.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d9ceb2c957320def533671fc9c715a80c47025139c8d1f3797477decbc6edd2"}, + {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4f0f8271c0a4db459f9dc807acd0eadd4839934a4b9b892f6f160e94da309837"}, + {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6a4f5ccead6d18ec072ac0b84420e95d27c1cdf5c9f1bc8fbd8daf86bd94f43d"}, + {file = "httptools-0.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:5cceac09f164bcba55c0500a18fe3c47df29b62353198e4f37bbcc5d591172c3"}, + {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:75c8022dca7935cba14741a42744eee13ba05db00b27a4b940f0d646bd4d56d0"}, + {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:48ed8129cd9a0d62cf4d1575fcf90fb37e3ff7d5654d3a5814eb3d55f36478c2"}, + {file = "httptools-0.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f58e335a1402fb5a650e271e8c2d03cfa7cea46ae124649346d17bd30d59c90"}, + {file = "httptools-0.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93ad80d7176aa5788902f207a4e79885f0576134695dfb0fefc15b7a4648d503"}, + {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9bb68d3a085c2174c2477eb3ffe84ae9fb4fde8792edb7bcd09a1d8467e30a84"}, + {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b512aa728bc02354e5ac086ce76c3ce635b62f5fbc32ab7082b5e582d27867bb"}, + {file = "httptools-0.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:97662ce7fb196c785344d00d638fc9ad69e18ee4bfb4000b35a52efe5adcc949"}, + {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8e216a038d2d52ea13fdd9b9c9c7459fb80d78302b257828285eca1c773b99b3"}, + {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3e802e0b2378ade99cd666b5bffb8b2a7cc8f3d28988685dc300469ea8dd86cb"}, + {file = "httptools-0.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bd3e488b447046e386a30f07af05f9b38d3d368d1f7b4d8f7e10af85393db97"}, + {file = "httptools-0.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe467eb086d80217b7584e61313ebadc8d187a4d95bb62031b7bab4b205c3ba3"}, + {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3c3b214ce057c54675b00108ac42bacf2ab8f85c58e3f324a4e963bbc46424f4"}, + {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8ae5b97f690badd2ca27cbf668494ee1b6d34cf1c464271ef7bfa9ca6b83ffaf"}, + {file = "httptools-0.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:405784577ba6540fa7d6ff49e37daf104e04f4b4ff2d1ac0469eaa6a20fde084"}, + {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:95fb92dd3649f9cb139e9c56604cc2d7c7bf0fc2e7c8d7fbd58f96e35eddd2a3"}, + {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dcbab042cc3ef272adc11220517278519adf8f53fd3056d0e68f0a6f891ba94e"}, + {file = "httptools-0.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf2372e98406efb42e93bfe10f2948e467edfd792b015f1b4ecd897903d3e8d"}, + {file = "httptools-0.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:678fcbae74477a17d103b7cae78b74800d795d702083867ce160fc202104d0da"}, + {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e0b281cf5a125c35f7f6722b65d8542d2e57331be573e9e88bc8b0115c4a7a81"}, + {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:95658c342529bba4e1d3d2b1a874db16c7cca435e8827422154c9da76ac4e13a"}, + {file = "httptools-0.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ebaec1bf683e4bf5e9fbb49b8cc36da482033596a415b3e4ebab5a4c0d7ec5e"}, + {file = "httptools-0.6.1.tar.gz", hash = "sha256:c6e26c30455600b95d94b1b836085138e82f177351454ee841c148f93a9bad5a"}, +] + +[package.extras] +test = ["Cython (>=0.29.24,<0.30.0)"] [[package]] name = "httpx" -version = "0.26.0" +version = "0.27.0" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpx-0.26.0-py3-none-any.whl", hash = "sha256:8915f5a3627c4d47b73e8202457cb28f1266982d1159bd5779d86a80c0eab1cd"}, - {file = "httpx-0.26.0.tar.gz", hash = "sha256:451b55c30d5185ea6b23c2c793abf9bb237d2a7dfb901ced6ff69ad37ec1dfaf"}, + {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, + {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, ] [package.dependencies] @@ -787,13 +1175,13 @@ socks = ["socksio (==1.*)"] [[package]] name = "huggingface-hub" -version = "0.20.3" +version = "0.23.2" description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" optional = false python-versions = ">=3.8.0" files = [ - {file = "huggingface_hub-0.20.3-py3-none-any.whl", hash = "sha256:d988ae4f00d3e307b0c80c6a05ca6dbb7edba8bba3079f74cda7d9c2e562a7b6"}, - {file = "huggingface_hub-0.20.3.tar.gz", hash = "sha256:94e7f8e074475fbc67d6a71957b678e1b4a74ff1b64a644fd6cbb83da962d05d"}, + {file = "huggingface_hub-0.23.2-py3-none-any.whl", hash = "sha256:48727a16e704d409c4bb5913613308499664f22a99743435dc3a13b23c485827"}, + {file = "huggingface_hub-0.23.2.tar.gz", hash = "sha256:f6829b62d5fdecb452a76fdbec620cba4c1573655a8d710c1df71735fd9edbd2"}, ] [package.dependencies] @@ -806,37 +1194,39 @@ tqdm = ">=4.42.1" typing-extensions = ">=3.7.4.3" [package.extras] -all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] cli = ["InquirerPy (==0.3.4)"] -dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"] -inference = ["aiohttp", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)"] -quality = ["mypy (==1.5.1)", "ruff (>=0.1.3)"] +hf-transfer = ["hf-transfer (>=0.1.4)"] +inference = ["aiohttp", "minijinja (>=1.0)"] +quality = ["mypy (==1.5.1)", "ruff (>=0.3.0)"] tensorflow = ["graphviz", "pydot", "tensorflow"] -testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] -torch = ["torch"] +tensorflow-testing = ["keras (<3.0)", "tensorflow"] +testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] +torch = ["safetensors", "torch"] typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"] [[package]] name = "idna" -version = "3.6" +version = "3.7" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ - {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, - {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, + {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, + {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, ] [[package]] name = "importlib-metadata" -version = "6.11.0" +version = "7.0.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-6.11.0-py3-none-any.whl", hash = "sha256:f0afba6205ad8f8947c7d338b5342d5db2afbfd82f9cbef7879a9539cc12eb9b"}, - {file = "importlib_metadata-6.11.0.tar.gz", hash = "sha256:1231cf92d825c9e03cfc4da076a16de6422c863558229ea0b22b675657463443"}, + {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"}, + {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"}, ] [package.dependencies] @@ -919,13 +1309,13 @@ testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] [[package]] name = "jinja2" -version = "3.1.3" +version = "3.1.4" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" files = [ - {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, - {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, ] [package.dependencies] @@ -934,173 +1324,421 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "jiter" +version = "0.4.0" +description = "Fast iterable JSON parser." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jiter-0.4.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:4aa6226d82a4a4505078c0bd5947bad65399635fc5cd4b226512e41753624edf"}, + {file = "jiter-0.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:947111ac906740a948e7b63799481acd3d5ef666ccb178d146e25718640b7408"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69572ffb4e84ae289a7422b9af4ea123cae2ce0772228859b37d4b26b4bc92ea"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ba6046cbb5d1baa5a781b846f7e5438596a332f249a857d63f86ef5d1d9563b0"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4f346e54602782e66d07df0d1c7389384fd93680052ed6170da2c6dc758409e"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:49110ce693f07e97d61089d894cea05a0b9894d5ccc6ac6fc583028726c8c8af"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e358df6fd129f3a4e087539f086355ad0107e5da16dbc8bc857d94222eaeed5"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7eb852ca39a48f3c049def56f0d1771b32e948e4f429a782d14ef4cc64cfd26e"}, + {file = "jiter-0.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:44dc045decb2545bffe2da04ea4c36d9438d3f3d49fc47ed423ea75c352b712e"}, + {file = "jiter-0.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:413adb15372ac63db04373240f40925788e4282c997eeafc2040530049a0a599"}, + {file = "jiter-0.4.0-cp310-none-win32.whl", hash = "sha256:0b48ea71673a97b897e4b94bbc871e62495a5a85f836c9f90712a4c70aa3ef7e"}, + {file = "jiter-0.4.0-cp310-none-win_amd64.whl", hash = "sha256:6a1c84b44afafaf0ba6223679cf17af664b889da14da31d8af3595fd977d96fa"}, + {file = "jiter-0.4.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b2cc498345fa37ca23fbc20271a553aa46e6eb00924600f49b7dc4b2aa8952ee"}, + {file = "jiter-0.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:69f7221ac09ab421abf04f89942026868297c568133998fb181bcf435760cbf3"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef7d01c52f3e5a56ae73af36bd13797dd1a56711eb522748e5e84d15425b3f10"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:39be97d5ce0c4d0dae28c23c03a0af0501a725589427e99763f99c42e18aa402"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eac2ed1ec1e577b92b7ea2d4e6de8aec0c1164defd8af8affdc8ec0f0ec2904a"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6258837d184c92c9cb91c983c310ad7269d41afb49d34f00ca9246e073943a03"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:123c2a77b066bf17a4d021e238e8351058cfa56b90ac04f2522d120dc64ea055"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2df939f792c7a40e55f36700417db551b9f6b84d348990fa0f2c608adeb1f11b"}, + {file = "jiter-0.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cb1b09b16d40cf9ba1d11ba11e5b96ad29286a6a1c4ad5e6a2aef5e352a89f5d"}, + {file = "jiter-0.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0efb4208889ebdbf933bf08dbcbc16e64ffd34c8e2b28044ee142789a9dc3a67"}, + {file = "jiter-0.4.0-cp311-none-win32.whl", hash = "sha256:20545ac1b68e7e5b066a1e8347840c9cebdd02ace65faae2e655fc02ec5c915c"}, + {file = "jiter-0.4.0-cp311-none-win_amd64.whl", hash = "sha256:6b300f9887c8e4431cd03a974ea3e4f9958885636003c3864220a9b2d2f8462b"}, + {file = "jiter-0.4.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:923432a0563bbae404ff25bb010e348514a69bfab979f2f8119b23b625dbf6d9"}, + {file = "jiter-0.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab8bb0ec8b97cec4422dc8b37b525442d969244488c805b834609ab0ccd788e2"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b857adb127b9c533907226791eafa79c5038c3eb5a477984994bf7c4715ba518"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2609cc0d1d8d470e921ff9a604afeb4c701bbe13e00bd9834d5aa6e7ea732a9b"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d39e99f8b7df46a119b6f84321f6ba01f16fa46abfa765d44c05c486d8e66829"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:56de8b518ebfe76a70f856741f6de248ce396c50a87acef827b6e8388e3a502d"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:488b7e777be47f67ce1a1f8f8eb907f9bbd81af5c03784a9bab09d025c250233"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7ea35e0ecbb5dadd457855eb980dcc548c14cf5341bcd22a43814cb56f2bcc79"}, + {file = "jiter-0.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e1a9e9ee69c80b63951c93226b68d0e955953f64fe758bad2afe7ef7f9016af9"}, + {file = "jiter-0.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:78e2f3cc2a32a21d43ccc5afcf66f5d17e827ccc4e6d21c0b353bdad2c7dcc9c"}, + {file = "jiter-0.4.0-cp312-none-win32.whl", hash = "sha256:eeaa7a2b47a99f4ebbb4142bb58b95617e09f24c87570f6a57d2770687c9ddbe"}, + {file = "jiter-0.4.0-cp312-none-win_amd64.whl", hash = "sha256:8d4a78b385b93ff59a67215d26000fcb4789a388fca3730d1b60fab17fc81e3c"}, + {file = "jiter-0.4.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:ebf20a3fac1089ce26963bf04140da0f803d55332ec69d59c5a87cf1a87d29c4"}, + {file = "jiter-0.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d62244ffc6a168187452277adeefb7b2c30170689c6bf543a51e98e8c17ddab7"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40b2cde77446a41cec595739fd168be87edff2428eaf7c3438231224dd0ab7a5"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e51fc0a22021ec8905b9b00a2f7d25756f2ff7a653e35a790a2067ae126b51f6"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a56e6f980b89d7cfe5c43811dcf52d6f37b319428a4540511235dafda9ea7808"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0fec16adab8d3d3d6d74e3711a1f380836ebeab2a20e3f88cfe2ec5094d8b84"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19e3de515801c954e8f1dc1f575282a4a86df9e782d4993ea1ed2be9a8dedaa0"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17e0ad8abf0bb04d81810eaeaab35d2c99b5da11fcd1058e0a389607ff6503b0"}, + {file = "jiter-0.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8dc0132b728f3b3e90ff0d1874504cd49c78f3553bf3745168a7fc0b4cf674e1"}, + {file = "jiter-0.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:81a883104aa96e494d3d28eaf7070780d03ecee8ccfdfaf7e4899710340c47f1"}, + {file = "jiter-0.4.0-cp38-none-win32.whl", hash = "sha256:a044c53ab1aaa4af624ac9574181b5bad8e260aea7e03104738156511433deba"}, + {file = "jiter-0.4.0-cp38-none-win_amd64.whl", hash = "sha256:d920035c869053e3d9a0b3ff94384d16a8ef5fde3dea55f97bd29916f6e27554"}, + {file = "jiter-0.4.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:091e978f4e586a2f1c69bf940d45f4e6a23455877172a0ab7d6de04a3b119299"}, + {file = "jiter-0.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:79134b2d601309bcbe3304a262d7d228ad61d53c80883231c637773000a6d683"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c471473e0b05058b5d729ff04271b6d45a575ac8bd9948563268c734b380ac7e"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb84b8930da8b32b0b1fdff9817e2c4b47e8981b5647ad11c4975403416e4112"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f2805e28941751ebfe0948596a64cde4cfb9b84bea5282affd020063e659c96"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:42ef59f9e513bf081a8b5c5578933ea9c3a63e559e6e3501a3e72edcd456ff5e"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ae12e3906f9e565120ab569de261b738e3a1ec50c40e30c67499e4f893e9a8c"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:264dc1324f45a793bc89af4f653225229eb17bca9ec7107dce6c8fb4fe68d20f"}, + {file = "jiter-0.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9a1c172ec47d846e25881dfbd52438ddb690da4ea04d185e477abd3db6c32f8a"}, + {file = "jiter-0.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ccde31d0bc114aedad0dbd71b7f63ba0f0eecd7ec9ae1926a0ca01c1eb2854e7"}, + {file = "jiter-0.4.0-cp39-none-win32.whl", hash = "sha256:13139b05792fbc13a0f9a5b4c89823ea0874141decae1b8f693f12bb1d28e061"}, + {file = "jiter-0.4.0-cp39-none-win_amd64.whl", hash = "sha256:3a729b2631c6d5551a41069697415fee9659c3eadc9ab87369376ba51930cd00"}, + {file = "jiter-0.4.0.tar.gz", hash = "sha256:68203e02e0419bc3eca717c580c2d8f615aeee1150e2a1fb68d6600a7e52a37c"}, +] + [[package]] name = "joblib" -version = "1.3.2" +version = "1.4.2" description = "Lightweight pipelining with Python functions" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "joblib-1.4.2-py3-none-any.whl", hash = "sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6"}, + {file = "joblib-1.4.2.tar.gz", hash = "sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e"}, +] + +[[package]] +name = "jsonpatch" +version = "1.33" +description = "Apply JSON-Patches (RFC 6902)" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +files = [ + {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, + {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"}, +] + +[package.dependencies] +jsonpointer = ">=1.9" + +[[package]] +name = "jsonpointer" +version = "2.4" +description = "Identify specific nodes in a JSON document (RFC 6901)" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +files = [ + {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, + {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, +] + +[[package]] +name = "jsonschema" +version = "4.22.0" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema-4.22.0-py3-none-any.whl", hash = "sha256:ff4cfd6b1367a40e7bc6411caec72effadd3db0bbe5017de188f2d6108335802"}, + {file = "jsonschema-4.22.0.tar.gz", hash = "sha256:5b22d434a45935119af990552c862e5d6d564e8f6601206b305a61fdf661a2b7"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] + +[[package]] +name = "jsonschema-specifications" +version = "2023.12.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +optional = false +python-versions = ">=3.8" files = [ - {file = "joblib-1.3.2-py3-none-any.whl", hash = "sha256:ef4331c65f239985f3f2220ecc87db222f08fd22097a3dd5698f693875f8cbb9"}, - {file = "joblib-1.3.2.tar.gz", hash = "sha256:92f865e621e17784e7955080b6d042489e3b8e294949cc44c6eac304f59772b1"}, + {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, + {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, ] +[package.dependencies] +referencing = ">=0.31.0" + [[package]] name = "langchain" -version = "0.0.198" +version = "0.2.1" description = "Building applications with LLMs through composability" optional = false -python-versions = ">=3.8.1,<4.0" +python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain-0.0.198-py3-none-any.whl", hash = "sha256:9d8e57ec25901989339ffac2ea7e759333d084100c90526e8ad57fb61b2003c9"}, - {file = "langchain-0.0.198.tar.gz", hash = "sha256:656385c23aeec1f8f4efbce598f729c817c60eb3f7c9fd77c03a8d28e7d0fa81"}, + {file = "langchain-0.2.1-py3-none-any.whl", hash = "sha256:3e13bf97c5717bce2c281f5117e8778823e8ccf62d949e73d3869448962b1c97"}, + {file = "langchain-0.2.1.tar.gz", hash = "sha256:5758a315e1ac92eb26dafec5ad0fafa03cafa686aba197d5bb0b1dd28cc03ebe"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" -async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""} -dataclasses-json = ">=0.5.7,<0.6.0" -langchainplus-sdk = ">=0.0.7" -numexpr = ">=2.8.4,<3.0.0" +langchain-core = ">=0.2.0,<0.3.0" +langchain-text-splitters = ">=0.2.0,<0.3.0" +langsmith = ">=0.1.17,<0.2.0" numpy = ">=1,<2" -openapi-schema-pydantic = ">=1.2,<2.0" -pydantic = ">=1,<2" -PyYAML = ">=5.4.1" +pydantic = ">=1,<3" +PyYAML = ">=5.3" requests = ">=2,<3" SQLAlchemy = ">=1.4,<3" tenacity = ">=8.1.0,<9.0.0" [package.extras] -all = ["O365 (>=2.0.26,<3.0.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.2.6,<0.3.0)", "arxiv (>=1.4,<2.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "awadb (>=0.3.2,<0.4.0)", "azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-vision (>=0.11.1b1,<0.12.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "beautifulsoup4 (>=4,<5)", "clickhouse-connect (>=0.5.14,<0.6.0)", "cohere (>=3,<4)", "deeplake (>=3.3.0,<4.0.0)", "docarray[hnswlib] (>=0.32.0,<0.33.0)", "duckduckgo-search (>=2.8.6,<3.0.0)", "elasticsearch (>=8,<9)", "faiss-cpu (>=1,<2)", "google-api-python-client (==2.70.0)", "google-auth (>=2.18.1,<3.0.0)", "google-search-results (>=2,<3)", "gptcache (>=0.1.7)", "html2text (>=2020.1.16,<2021.0.0)", "huggingface_hub (>=0,<1)", "jina (>=3.14,<4.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "lancedb (>=0.1,<0.2)", "langkit (>=0.0.1.dev3,<0.1.0)", "lark (>=1.1.5,<2.0.0)", "lxml (>=4.9.2,<5.0.0)", "manifest-ml (>=0.0.1,<0.0.2)", "momento (>=1.5.0,<2.0.0)", "nebula3-python (>=3.4.0,<4.0.0)", "neo4j (>=5.8.1,<6.0.0)", "networkx (>=2.6.3,<3.0.0)", "nlpcloud (>=1,<2)", "nltk (>=3,<4)", "nomic (>=1.0.43,<2.0.0)", "openai (>=0,<1)", "openlm (>=0.0.5,<0.0.6)", "opensearch-py (>=2.0.0,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pexpect (>=4.8.0,<5.0.0)", "pgvector (>=0.1.6,<0.2.0)", "pinecone-client (>=2,<3)", "pinecone-text (>=0.4.2,<0.5.0)", "psycopg2-binary (>=2.9.5,<3.0.0)", "pymongo (>=4.3.3,<5.0.0)", "pyowm (>=3.3.0,<4.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pytesseract (>=0.3.10,<0.4.0)", "pyvespa (>=0.33.0,<0.34.0)", "qdrant-client (>=1.1.2,<2.0.0)", "redis (>=4,<5)", "requests-toolbelt (>=1.0.0,<2.0.0)", "sentence-transformers (>=2,<3)", "singlestoredb (>=0.6.1,<0.7.0)", "spacy (>=3,<4)", "steamship (>=2.16.9,<3.0.0)", "tensorflow-text (>=2.11.0,<3.0.0)", "tigrisdb (>=1.0.0b6,<2.0.0)", "tiktoken (>=0.3.2,<0.4.0)", "torch (>=1,<3)", "transformers (>=4,<5)", "weaviate-client (>=3,<4)", "wikipedia (>=1,<2)", "wolframalpha (==5.0.0)"] -azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-vision (>=0.11.1b1,<0.12.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0a20230509004)", "openai (>=0,<1)"] -cohere = ["cohere (>=3,<4)"] +azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-textanalytics (>=5.3.0,<6.0.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b8)", "openai (<2)"] +clarifai = ["clarifai (>=9.1.0)"] +cli = ["typer (>=0.9.0,<0.10.0)"] +cohere = ["cohere (>=4,<6)"] docarray = ["docarray[hnswlib] (>=0.32.0,<0.33.0)"] embeddings = ["sentence-transformers (>=2,<3)"] -extended-testing = ["atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "chardet (>=5.1.0,<6.0.0)", "gql (>=3.4.1,<4.0.0)", "html2text (>=2020.1.16,<2021.0.0)", "jq (>=1.4.1,<2.0.0)", "lxml (>=4.9.2,<5.0.0)", "openai (>=0,<1)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "psychicapi (>=0.5,<0.6)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "telethon (>=1.28.5,<2.0.0)", "tqdm (>=4.48.0)", "zep-python (>=0.31)"] -llms = ["anthropic (>=0.2.6,<0.3.0)", "cohere (>=3,<4)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (>=0,<1)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] -openai = ["openai (>=0,<1)", "tiktoken (>=0.3.2,<0.4.0)"] -qdrant = ["qdrant-client (>=1.1.2,<2.0.0)"] +extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<6)", "couchbase (>=4.1.9,<5.0.0)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "langchain-openai (>=0.1,<0.2)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] +javascript = ["esprima (>=4.0.1,<5.0.0)"] +llms = ["clarifai (>=9.1.0)", "cohere (>=4,<6)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (<2)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] +openai = ["openai (<2)", "tiktoken (>=0.7,<1.0)"] +qdrant = ["qdrant-client (>=1.3.1,<2.0.0)"] text-helpers = ["chardet (>=5.1.0,<6.0.0)"] [[package]] -name = "langchainplus-sdk" -version = "0.0.20" -description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." +name = "langchain-community" +version = "0.2.1" +description = "Community contributed LangChain integrations." optional = false -python-versions = ">=3.8.1,<4.0" +python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchainplus_sdk-0.0.20-py3-none-any.whl", hash = "sha256:07a869d476755803aa04c4986ce78d00c2fe4ff584c0eaa57d7570c9664188db"}, - {file = "langchainplus_sdk-0.0.20.tar.gz", hash = "sha256:3d300e2e3290f68cc9d842c059f9458deba60e776c9e790309688cad1bfbb219"}, + {file = "langchain_community-0.2.1-py3-none-any.whl", hash = "sha256:b834e2c5ded6903b839fcaf566eee90a0ffae53405a0f7748202725e701d39cd"}, + {file = "langchain_community-0.2.1.tar.gz", hash = "sha256:079942e8f15da975769ccaae19042b7bba5481c42020bbbd7d8cad73a9393261"}, ] [package.dependencies] -pydantic = ">=1,<2" +aiohttp = ">=3.8.3,<4.0.0" +dataclasses-json = ">=0.5.7,<0.7" +langchain = ">=0.2.0,<0.3.0" +langchain-core = ">=0.2.0,<0.3.0" +langsmith = ">=0.1.0,<0.2.0" +numpy = ">=1,<2" +PyYAML = ">=5.3" requests = ">=2,<3" +SQLAlchemy = ">=1.4,<3" +tenacity = ">=8.1.0,<9.0.0" + +[package.extras] +cli = ["typer (>=0.9.0,<0.10.0)"] +extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "azure-identity (>=1.15.0,<2.0.0)", "azure-search-documents (==11.4.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.6,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cloudpathlib (>=0.18,<0.19)", "cloudpickle (>=2.0.0)", "cohere (>=4,<5)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "friendli-client (>=1.2.4,<2.0.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "httpx (>=0.24.1,<0.25.0)", "httpx-sse (>=0.4.0,<0.5.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "nvidia-riva-client (>=2.14.0,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "oracledb (>=2.2.0,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "premai (>=0.3.25,<0.4.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pyjwt (>=2.8.0,<3.0.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "tidb-vector (>=0.0.3,<1.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "tree-sitter (>=0.20.2,<0.21.0)", "tree-sitter-languages (>=1.8.0,<2.0.0)", "upstash-redis (>=0.15.0,<0.16.0)", "vdms (>=0.0.20,<0.0.21)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] + +[[package]] +name = "langchain-core" +version = "0.2.3" +description = "Building applications with LLMs through composability" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_core-0.2.3-py3-none-any.whl", hash = "sha256:22189b5a3a30bfd65eb995f95e627f7c2c3acb322feb89f5f5f2fb7df21833a7"}, + {file = "langchain_core-0.2.3.tar.gz", hash = "sha256:fbc75a64b9c0b7655d96ca57a707df1e6c09efc1539c36adbd73260612549810"}, +] + +[package.dependencies] +jsonpatch = ">=1.33,<2.0" +langsmith = ">=0.1.65,<0.2.0" +packaging = ">=23.2,<24.0" +pydantic = ">=1,<3" +PyYAML = ">=5.3" tenacity = ">=8.1.0,<9.0.0" +[package.extras] +extended-testing = ["jinja2 (>=3,<4)"] + +[[package]] +name = "langchain-text-splitters" +version = "0.2.0" +description = "LangChain text splitting utilities" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_text_splitters-0.2.0-py3-none-any.whl", hash = "sha256:7b4c6a45f8471630a882b321e138329b6897102a5bc62f4c12be1c0b05bb9199"}, + {file = "langchain_text_splitters-0.2.0.tar.gz", hash = "sha256:b32ab4f7397f7d42c1fa3283fefc2547ba356bd63a68ee9092865e5ad83c82f9"}, +] + +[package.dependencies] +langchain-core = ">=0.2.0,<0.3.0" + +[package.extras] +extended-testing = ["beautifulsoup4 (>=4.12.3,<5.0.0)", "lxml (>=4.9.3,<6.0)"] + +[[package]] +name = "langsmith" +version = "0.1.65" +description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langsmith-0.1.65-py3-none-any.whl", hash = "sha256:ab4487029240e69cca30da1065f1e9138e5a7ca2bbe8c697f0bd7d5839f71cf7"}, + {file = "langsmith-0.1.65.tar.gz", hash = "sha256:d3c2eb2391478bd79989f02652cf66e29a7959d677614b6993a47cef43f7f43b"}, +] + +[package.dependencies] +orjson = ">=3.9.14,<4.0.0" +pydantic = ">=1,<3" +requests = ">=2,<3" + +[[package]] +name = "loguru" +version = "0.7.2" +description = "Python logging made (stupidly) simple" +optional = false +python-versions = ">=3.5" +files = [ + {file = "loguru-0.7.2-py3-none-any.whl", hash = "sha256:003d71e3d3ed35f0f8984898359d65b79e5b21943f78af86aa5491210429b8eb"}, + {file = "loguru-0.7.2.tar.gz", hash = "sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"}, +] + +[package.dependencies] +colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} +win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} + +[package.extras] +dev = ["Sphinx (==7.2.5)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.2.2)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.4.1)", "mypy (==v1.5.1)", "pre-commit (==3.4.0)", "pytest (==6.1.2)", "pytest (==7.4.0)", "pytest-cov (==2.12.1)", "pytest-cov (==4.1.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.0.0)", "sphinx-autobuild (==2021.3.14)", "sphinx-rtd-theme (==1.3.0)", "tox (==3.27.1)", "tox (==4.11.0)"] + +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.8" +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + [[package]] name = "markupsafe" -version = "2.1.4" +version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.7" files = [ - {file = "MarkupSafe-2.1.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de8153a7aae3835484ac168a9a9bdaa0c5eee4e0bc595503c95d53b942879c84"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e888ff76ceb39601c59e219f281466c6d7e66bd375b4ec1ce83bcdc68306796b"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0b838c37ba596fcbfca71651a104a611543077156cb0a26fe0c475e1f152ee8"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac1ebf6983148b45b5fa48593950f90ed6d1d26300604f321c74a9ca1609f8e"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0fbad3d346df8f9d72622ac71b69565e621ada2ce6572f37c2eae8dacd60385d"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5291d98cd3ad9a562883468c690a2a238c4a6388ab3bd155b0c75dd55ece858"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a7cc49ef48a3c7a0005a949f3c04f8baa5409d3f663a1b36f0eba9bfe2a0396e"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b83041cda633871572f0d3c41dddd5582ad7d22f65a72eacd8d3d6d00291df26"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-win32.whl", hash = "sha256:0c26f67b3fe27302d3a412b85ef696792c4a2386293c53ba683a89562f9399b0"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-win_amd64.whl", hash = "sha256:a76055d5cb1c23485d7ddae533229039b850db711c554a12ea64a0fd8a0129e2"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9e9e3c4020aa2dc62d5dd6743a69e399ce3de58320522948af6140ac959ab863"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0042d6a9880b38e1dd9ff83146cc3c9c18a059b9360ceae207805567aacccc69"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55d03fea4c4e9fd0ad75dc2e7e2b6757b80c152c032ea1d1de487461d8140efc"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ab3a886a237f6e9c9f4f7d272067e712cdb4efa774bef494dccad08f39d8ae6"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abf5ebbec056817057bfafc0445916bb688a255a5146f900445d081db08cbabb"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e1a0d1924a5013d4f294087e00024ad25668234569289650929ab871231668e7"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e7902211afd0af05fbadcc9a312e4cf10f27b779cf1323e78d52377ae4b72bea"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c669391319973e49a7c6230c218a1e3044710bc1ce4c8e6eb71f7e6d43a2c131"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-win32.whl", hash = "sha256:31f57d64c336b8ccb1966d156932f3daa4fee74176b0fdc48ef580be774aae74"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-win_amd64.whl", hash = "sha256:54a7e1380dfece8847c71bf7e33da5d084e9b889c75eca19100ef98027bd9f56"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:a76cd37d229fc385738bd1ce4cba2a121cf26b53864c1772694ad0ad348e509e"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:987d13fe1d23e12a66ca2073b8d2e2a75cec2ecb8eab43ff5624ba0ad42764bc"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5244324676254697fe5c181fc762284e2c5fceeb1c4e3e7f6aca2b6f107e60dc"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78bc995e004681246e85e28e068111a4c3f35f34e6c62da1471e844ee1446250"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4d176cfdfde84f732c4a53109b293d05883e952bbba68b857ae446fa3119b4f"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f9917691f410a2e0897d1ef99619fd3f7dd503647c8ff2475bf90c3cf222ad74"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f06e5a9e99b7df44640767842f414ed5d7bedaaa78cd817ce04bbd6fd86e2dd6"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:396549cea79e8ca4ba65525470d534e8a41070e6b3500ce2414921099cb73e8d"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-win32.whl", hash = "sha256:f6be2d708a9d0e9b0054856f07ac7070fbe1754be40ca8525d5adccdbda8f475"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-win_amd64.whl", hash = "sha256:5045e892cfdaecc5b4c01822f353cf2c8feb88a6ec1c0adef2a2e705eef0f656"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7a07f40ef8f0fbc5ef1000d0c78771f4d5ca03b4953fc162749772916b298fc4"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d18b66fe626ac412d96c2ab536306c736c66cf2a31c243a45025156cc190dc8a"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:698e84142f3f884114ea8cf83e7a67ca8f4ace8454e78fe960646c6c91c63bfa"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49a3b78a5af63ec10d8604180380c13dcd870aba7928c1fe04e881d5c792dc4e"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:15866d7f2dc60cfdde12ebb4e75e41be862348b4728300c36cdf405e258415ec"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6aa5e2e7fc9bc042ae82d8b79d795b9a62bd8f15ba1e7594e3db243f158b5565"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:54635102ba3cf5da26eb6f96c4b8c53af8a9c0d97b64bdcb592596a6255d8518"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-win32.whl", hash = "sha256:3583a3a3ab7958e354dc1d25be74aee6228938312ee875a22330c4dc2e41beb0"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-win_amd64.whl", hash = "sha256:d6e427c7378c7f1b2bef6a344c925b8b63623d3321c09a237b7cc0e77dd98ceb"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:bf1196dcc239e608605b716e7b166eb5faf4bc192f8a44b81e85251e62584bd2"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4df98d4a9cd6a88d6a585852f56f2155c9cdb6aec78361a19f938810aa020954"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b835aba863195269ea358cecc21b400276747cc977492319fd7682b8cd2c253d"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23984d1bdae01bee794267424af55eef4dfc038dc5d1272860669b2aa025c9e3"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c98c33ffe20e9a489145d97070a435ea0679fddaabcafe19982fe9c971987d5"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9896fca4a8eb246defc8b2a7ac77ef7553b638e04fbf170bff78a40fa8a91474"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b0fe73bac2fed83839dbdbe6da84ae2a31c11cfc1c777a40dbd8ac8a6ed1560f"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c7556bafeaa0a50e2fe7dc86e0382dea349ebcad8f010d5a7dc6ba568eaaa789"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-win32.whl", hash = "sha256:fc1a75aa8f11b87910ffd98de62b29d6520b6d6e8a3de69a70ca34dea85d2a8a"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-win_amd64.whl", hash = "sha256:3a66c36a3864df95e4f62f9167c734b3b1192cb0851b43d7cc08040c074c6279"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:765f036a3d00395a326df2835d8f86b637dbaf9832f90f5d196c3b8a7a5080cb"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:21e7af8091007bf4bebf4521184f4880a6acab8df0df52ef9e513d8e5db23411"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5c31fe855c77cad679b302aabc42d724ed87c043b1432d457f4976add1c2c3e"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7653fa39578957bc42e5ebc15cf4361d9e0ee4b702d7d5ec96cdac860953c5b4"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47bb5f0142b8b64ed1399b6b60f700a580335c8e1c57f2f15587bd072012decc"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fe8512ed897d5daf089e5bd010c3dc03bb1bdae00b35588c49b98268d4a01e00"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:36d7626a8cca4d34216875aee5a1d3d654bb3dac201c1c003d182283e3205949"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b6f14a9cd50c3cb100eb94b3273131c80d102e19bb20253ac7bd7336118a673a"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-win32.whl", hash = "sha256:c8f253a84dbd2c63c19590fa86a032ef3d8cc18923b8049d91bcdeeb2581fbf6"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-win_amd64.whl", hash = "sha256:8b570a1537367b52396e53325769608f2a687ec9a4363647af1cded8928af959"}, - {file = "MarkupSafe-2.1.4.tar.gz", hash = "sha256:3aae9af4cac263007fd6309c64c6ab4506dd2b79382d9d19a1994f9240b8db4f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, ] [[package]] name = "marshmallow" -version = "3.20.2" +version = "3.21.2" description = "A lightweight library for converting complex datatypes to and from native Python datatypes." optional = false python-versions = ">=3.8" files = [ - {file = "marshmallow-3.20.2-py3-none-any.whl", hash = "sha256:c21d4b98fee747c130e6bc8f45c4b3199ea66bc00c12ee1f639f0aeca034d5e9"}, - {file = "marshmallow-3.20.2.tar.gz", hash = "sha256:4c1daff273513dc5eb24b219a8035559dc573c8f322558ef85f5438ddd1236dd"}, + {file = "marshmallow-3.21.2-py3-none-any.whl", hash = "sha256:70b54a6282f4704d12c0a41599682c5c5450e843b9ec406308653b47c59648a1"}, + {file = "marshmallow-3.21.2.tar.gz", hash = "sha256:82408deadd8b33d56338d2182d455db632c6313aa2af61916672146bb32edc56"}, ] [package.dependencies] packaging = ">=17.0" [package.extras] -dev = ["pre-commit (>=2.4,<4.0)", "pytest", "pytz", "simplejson", "tox"] -docs = ["alabaster (==0.7.15)", "autodocsumm (==0.2.12)", "sphinx (==7.2.6)", "sphinx-issues (==3.0.1)", "sphinx-version-warning (==1.1.2)"] -lint = ["pre-commit (>=2.4,<4.0)"] +dev = ["marshmallow[tests]", "pre-commit (>=3.5,<4.0)", "tox"] +docs = ["alabaster (==0.7.16)", "autodocsumm (==0.2.12)", "sphinx (==7.3.7)", "sphinx-issues (==4.1.0)", "sphinx-version-warning (==1.1.2)"] tests = ["pytest", "pytz", "simplejson"] [[package]] name = "matplotlib-inline" -version = "0.1.6" +version = "0.1.7" description = "Inline Matplotlib backend for Jupyter" optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" files = [ - {file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"}, - {file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"}, + {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"}, + {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"}, ] [package.dependencies] traitlets = "*" +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + [[package]] name = "miniaudio" version = "1.59" @@ -1167,85 +1805,101 @@ cffi = ">=1.12.0" [[package]] name = "multidict" -version = "6.0.4" +version = "6.0.5" description = "multidict implementation" optional = false python-versions = ">=3.7" files = [ - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, - {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, - {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, - {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, - {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, - {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, - {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, - {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, - {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, - {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, - {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, - {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, - {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, + {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, + {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, + {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, + {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, + {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, + {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, + {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, + {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, + {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, + {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, + {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, + {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, + {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, + {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, + {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, ] [[package]] @@ -1284,168 +1938,169 @@ plot = ["matplotlib"] tgrep = ["pyparsing"] twitter = ["twython"] -[[package]] -name = "numexpr" -version = "2.8.8" -description = "Fast numerical expression evaluator for NumPy" -optional = false -python-versions = ">=3.9" -files = [ - {file = "numexpr-2.8.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:85c9f79e346c26aa0d425ecfc9e5de7184567d5e48d0bdb02d468bb927e92525"}, - {file = "numexpr-2.8.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dbac846f713b4c82333e6af0814ebea0b4e74dfb2649e76c58953fd4862322dd"}, - {file = "numexpr-2.8.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d7bfc8b77d8a7b04cd64ae42b62b3bf824a8c751ca235692bfd5231c6e90127"}, - {file = "numexpr-2.8.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:307b49fd15ef2ca292f381e67759e5b477410341f2f499a377234f1b42f529a6"}, - {file = "numexpr-2.8.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:aab17d65751c039d13ed9d49c9a7517b130ef488c1885c4666af9b5c6ad59520"}, - {file = "numexpr-2.8.8-cp310-cp310-win32.whl", hash = "sha256:6459dc6ed6abcdeab3cd3667c79f29e4a0f0a02c29ad71ee5cff065e880ee9ef"}, - {file = "numexpr-2.8.8-cp310-cp310-win_amd64.whl", hash = "sha256:22ccd67c0fbeae091f2c577f5b9c8046de6631d46b1cbe22aad46a08d2b42c2d"}, - {file = "numexpr-2.8.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:47c05007cd1c553515492c1a78b5477eaaba9cadc5d7b795d49f7aae53ccdf68"}, - {file = "numexpr-2.8.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b4649c1dcf9b0c2ae0a7b767dbbbde4e05ee68480c1ba7f06fc7963f1f73acf4"}, - {file = "numexpr-2.8.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a82d710145b0fbaec919dde9c90ed9df1e6785625cc36d1c71f3a53112b66fc5"}, - {file = "numexpr-2.8.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a92f230dd9d6c42803f855970e93677b44290b6dad15cb6796fd85edee171ce"}, - {file = "numexpr-2.8.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ccef9b09432d59229c2a737882e55de7906006452003323e107576f264cec373"}, - {file = "numexpr-2.8.8-cp311-cp311-win32.whl", hash = "sha256:bf8c517bbbb82c07c23c17f9d52b4c9f86601f57d48e87c0cbda24af5907f4dd"}, - {file = "numexpr-2.8.8-cp311-cp311-win_amd64.whl", hash = "sha256:4f01d71db6fdb97a68def5407e2dbd748eaea9d98929db08816de40aa4ae3084"}, - {file = "numexpr-2.8.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:76f0f010f9c6318bae213b21c5c0e381c2fc9c9ecb8b35f99f5030e7ac96c9ce"}, - {file = "numexpr-2.8.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3f168b4b42d4cb120fe1993676dcf74b77a3e8e45b58855566da037cfd938ca3"}, - {file = "numexpr-2.8.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f031ac4e70f9ad867543bfbde8452e9d1a14f0525346b4b8bd4e5c0f1380a11c"}, - {file = "numexpr-2.8.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:121b049b6909787111daf92919c052c4fd87b5691172e8f19f702b96f20aaafa"}, - {file = "numexpr-2.8.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2ae264c35fa67cd510191ab8144f131fddd0f1d13413af710913ea6fc0c6aa61"}, - {file = "numexpr-2.8.8-cp312-cp312-win32.whl", hash = "sha256:399cb914b41c4027ba88a18f6b8ccfc3af5c32bc3b1758403a7c44c72530618a"}, - {file = "numexpr-2.8.8-cp312-cp312-win_amd64.whl", hash = "sha256:925927cd1f610593e7783d8f2e12e3d800d5928601e077e4910e2b50bde624b6"}, - {file = "numexpr-2.8.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cd07793b074cc38e478637cbe738dff7d8eb92b5cf8ffaacff0c4f0bca5270a0"}, - {file = "numexpr-2.8.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:290f91c7ba7772abaf7107f3cc0601d93d6a3f21c13ee3da93f1b8a9ca3e8d39"}, - {file = "numexpr-2.8.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:296dc1f79d386166dec3bdb45f51caba29ffd8dc91db15447108c04d3001d921"}, - {file = "numexpr-2.8.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7badc50efbb2f1c8b78cd68089031e0fd29cbafa6a9e6d730533f22d88168406"}, - {file = "numexpr-2.8.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4d83a542d9deefb050e389aacaddea0f09d68ec617dd37e45b9a7cfbcba6d729"}, - {file = "numexpr-2.8.8-cp39-cp39-win32.whl", hash = "sha256:17104051f0bd83fd350212e268d8b48017d5eff522b09b573fdbcc560c5e7ab3"}, - {file = "numexpr-2.8.8-cp39-cp39-win_amd64.whl", hash = "sha256:12146521b1730073859a20454e75004e38cd0cb61333e763c58ef5171e101eb2"}, - {file = "numexpr-2.8.8.tar.gz", hash = "sha256:e76ce4d25372f46170cf7eb1ff14ed5d9c69a0b162a405063cbe481bafe3af34"}, -] - -[package.dependencies] -numpy = ">=1.13.3" - [[package]] name = "numpy" -version = "1.26.3" +version = "1.26.4" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.9" files = [ - {file = "numpy-1.26.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:806dd64230dbbfaca8a27faa64e2f414bf1c6622ab78cc4264f7f5f028fee3bf"}, - {file = "numpy-1.26.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02f98011ba4ab17f46f80f7f8f1c291ee7d855fcef0a5a98db80767a468c85cd"}, - {file = "numpy-1.26.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d45b3ec2faed4baca41c76617fcdcfa4f684ff7a151ce6fc78ad3b6e85af0a6"}, - {file = "numpy-1.26.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdd2b45bf079d9ad90377048e2747a0c82351989a2165821f0c96831b4a2a54b"}, - {file = "numpy-1.26.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:211ddd1e94817ed2d175b60b6374120244a4dd2287f4ece45d49228b4d529178"}, - {file = "numpy-1.26.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b1240f767f69d7c4c8a29adde2310b871153df9b26b5cb2b54a561ac85146485"}, - {file = "numpy-1.26.3-cp310-cp310-win32.whl", hash = "sha256:21a9484e75ad018974a2fdaa216524d64ed4212e418e0a551a2d83403b0531d3"}, - {file = "numpy-1.26.3-cp310-cp310-win_amd64.whl", hash = "sha256:9e1591f6ae98bcfac2a4bbf9221c0b92ab49762228f38287f6eeb5f3f55905ce"}, - {file = "numpy-1.26.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b831295e5472954104ecb46cd98c08b98b49c69fdb7040483aff799a755a7374"}, - {file = "numpy-1.26.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9e87562b91f68dd8b1c39149d0323b42e0082db7ddb8e934ab4c292094d575d6"}, - {file = "numpy-1.26.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c66d6fec467e8c0f975818c1796d25c53521124b7cfb760114be0abad53a0a2"}, - {file = "numpy-1.26.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f25e2811a9c932e43943a2615e65fc487a0b6b49218899e62e426e7f0a57eeda"}, - {file = "numpy-1.26.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:af36e0aa45e25c9f57bf684b1175e59ea05d9a7d3e8e87b7ae1a1da246f2767e"}, - {file = "numpy-1.26.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:51c7f1b344f302067b02e0f5b5d2daa9ed4a721cf49f070280ac202738ea7f00"}, - {file = "numpy-1.26.3-cp311-cp311-win32.whl", hash = "sha256:7ca4f24341df071877849eb2034948459ce3a07915c2734f1abb4018d9c49d7b"}, - {file = "numpy-1.26.3-cp311-cp311-win_amd64.whl", hash = "sha256:39763aee6dfdd4878032361b30b2b12593fb445ddb66bbac802e2113eb8a6ac4"}, - {file = "numpy-1.26.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a7081fd19a6d573e1a05e600c82a1c421011db7935ed0d5c483e9dd96b99cf13"}, - {file = "numpy-1.26.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12c70ac274b32bc00c7f61b515126c9205323703abb99cd41836e8125ea0043e"}, - {file = "numpy-1.26.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f784e13e598e9594750b2ef6729bcd5a47f6cfe4a12cca13def35e06d8163e3"}, - {file = "numpy-1.26.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f24750ef94d56ce6e33e4019a8a4d68cfdb1ef661a52cdaee628a56d2437419"}, - {file = "numpy-1.26.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:77810ef29e0fb1d289d225cabb9ee6cf4d11978a00bb99f7f8ec2132a84e0166"}, - {file = "numpy-1.26.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8ed07a90f5450d99dad60d3799f9c03c6566709bd53b497eb9ccad9a55867f36"}, - {file = "numpy-1.26.3-cp312-cp312-win32.whl", hash = "sha256:f73497e8c38295aaa4741bdfa4fda1a5aedda5473074369eca10626835445511"}, - {file = "numpy-1.26.3-cp312-cp312-win_amd64.whl", hash = "sha256:da4b0c6c699a0ad73c810736303f7fbae483bcb012e38d7eb06a5e3b432c981b"}, - {file = "numpy-1.26.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1666f634cb3c80ccbd77ec97bc17337718f56d6658acf5d3b906ca03e90ce87f"}, - {file = "numpy-1.26.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18c3319a7d39b2c6a9e3bb75aab2304ab79a811ac0168a671a62e6346c29b03f"}, - {file = "numpy-1.26.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b7e807d6888da0db6e7e75838444d62495e2b588b99e90dd80c3459594e857b"}, - {file = "numpy-1.26.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4d362e17bcb0011738c2d83e0a65ea8ce627057b2fdda37678f4374a382a137"}, - {file = "numpy-1.26.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b8c275f0ae90069496068c714387b4a0eba5d531aace269559ff2b43655edd58"}, - {file = "numpy-1.26.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cc0743f0302b94f397a4a65a660d4cd24267439eb16493fb3caad2e4389bccbb"}, - {file = "numpy-1.26.3-cp39-cp39-win32.whl", hash = "sha256:9bc6d1a7f8cedd519c4b7b1156d98e051b726bf160715b769106661d567b3f03"}, - {file = "numpy-1.26.3-cp39-cp39-win_amd64.whl", hash = "sha256:867e3644e208c8922a3be26fc6bbf112a035f50f0a86497f98f228c50c607bb2"}, - {file = "numpy-1.26.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3c67423b3703f8fbd90f5adaa37f85b5794d3366948efe9a5190a5f3a83fc34e"}, - {file = "numpy-1.26.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46f47ee566d98849323f01b349d58f2557f02167ee301e5e28809a8c0e27a2d0"}, - {file = "numpy-1.26.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a8474703bffc65ca15853d5fd4d06b18138ae90c17c8d12169968e998e448bb5"}, - {file = "numpy-1.26.3.tar.gz", hash = "sha256:697df43e2b6310ecc9d95f05d5ef20eacc09c7c4ecc9da3f235d39e71b7da1e4"}, + {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, + {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, + {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, + {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, + {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, + {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, + {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, + {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, + {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, + {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, + {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, ] [[package]] name = "openai" -version = "0.27.10" -description = "Python client library for the OpenAI API" +version = "1.30.5" +description = "The official Python library for the openai API" optional = false python-versions = ">=3.7.1" files = [ - {file = "openai-0.27.10-py3-none-any.whl", hash = "sha256:beabd1757e3286fa166dde3b70ebb5ad8081af046876b47c14c41e203ed22a14"}, - {file = "openai-0.27.10.tar.gz", hash = "sha256:60e09edf7100080283688748c6803b7b3b52d5a55d21890f3815292a0552d83b"}, + {file = "openai-1.30.5-py3-none-any.whl", hash = "sha256:2ad95e926de0d2e09cde632a9204b0a6dca4a03c2cdcc84329b01f355784355a"}, + {file = "openai-1.30.5.tar.gz", hash = "sha256:5366562eb2c5917e6116ae0391b7ae6e3acd62b0ae3f565ada32b35d8fcfa106"}, ] [package.dependencies] -aiohttp = "*" -requests = ">=2.20" -tqdm = "*" +anyio = ">=3.5.0,<5" +distro = ">=1.7.0,<2" +httpx = ">=0.23.0,<1" +pydantic = ">=1.9.0,<3" +sniffio = "*" +tqdm = ">4" +typing-extensions = ">=4.7,<5" [package.extras] -datalib = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] -dev = ["black (>=21.6b0,<22.0)", "pytest (==6.*)", "pytest-asyncio", "pytest-mock"] -embeddings = ["matplotlib", "numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "plotly", "scikit-learn (>=1.0.2)", "scipy", "tenacity (>=8.0.1)"] -wandb = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "wandb"] - -[[package]] -name = "openapi-schema-pydantic" -version = "1.2.4" -description = "OpenAPI (v3) specification schema as pydantic class" -optional = false -python-versions = ">=3.6.1" -files = [ - {file = "openapi-schema-pydantic-1.2.4.tar.gz", hash = "sha256:3e22cf58b74a69f752cc7e5f1537f6e44164282db2700cbbcd3bb99ddd065196"}, - {file = "openapi_schema_pydantic-1.2.4-py3-none-any.whl", hash = "sha256:a932ecc5dcbb308950282088956e94dea069c9823c84e507d64f6b622222098c"}, -] - -[package.dependencies] -pydantic = ">=1.8.2" +datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] [[package]] name = "opentelemetry-api" -version = "1.22.0" +version = "1.24.0" description = "OpenTelemetry Python API" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "opentelemetry_api-1.22.0-py3-none-any.whl", hash = "sha256:43621514301a7e9f5d06dd8013a1b450f30c2e9372b8e30aaeb4562abf2ce034"}, - {file = "opentelemetry_api-1.22.0.tar.gz", hash = "sha256:15ae4ca925ecf9cfdfb7a709250846fbb08072260fca08ade78056c502b86bed"}, + {file = "opentelemetry_api-1.24.0-py3-none-any.whl", hash = "sha256:0f2c363d98d10d1ce93330015ca7fd3a65f60be64e05e30f557c61de52c80ca2"}, + {file = "opentelemetry_api-1.24.0.tar.gz", hash = "sha256:42719f10ce7b5a9a73b10a4baf620574fb8ad495a9cbe5c18d76b75d8689c67e"}, ] [package.dependencies] deprecated = ">=1.2.6" -importlib-metadata = ">=6.0,<7.0" +importlib-metadata = ">=6.0,<=7.0" [[package]] name = "opentelemetry-sdk" -version = "1.22.0" +version = "1.24.0" description = "OpenTelemetry Python SDK" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "opentelemetry_sdk-1.22.0-py3-none-any.whl", hash = "sha256:a730555713d7c8931657612a88a141e3a4fe6eb5523d9e2d5a8b1e673d76efa6"}, - {file = "opentelemetry_sdk-1.22.0.tar.gz", hash = "sha256:45267ac1f38a431fc2eb5d6e0c0d83afc0b78de57ac345488aa58c28c17991d0"}, + {file = "opentelemetry_sdk-1.24.0-py3-none-any.whl", hash = "sha256:fa731e24efe832e98bcd90902085b359dcfef7d9c9c00eb5b9a18587dae3eb59"}, + {file = "opentelemetry_sdk-1.24.0.tar.gz", hash = "sha256:75bc0563affffa827700e0f4f4a68e1e257db0df13372344aebc6f8a64cde2e5"}, ] [package.dependencies] -opentelemetry-api = "1.22.0" -opentelemetry-semantic-conventions = "0.43b0" +opentelemetry-api = "1.24.0" +opentelemetry-semantic-conventions = "0.45b0" typing-extensions = ">=3.7.4" [[package]] name = "opentelemetry-semantic-conventions" -version = "0.43b0" +version = "0.45b0" description = "OpenTelemetry Semantic Conventions" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_semantic_conventions-0.45b0-py3-none-any.whl", hash = "sha256:a4a6fb9a7bacd9167c082aa4681009e9acdbfa28ffb2387af50c2fef3d30c864"}, + {file = "opentelemetry_semantic_conventions-0.45b0.tar.gz", hash = "sha256:7c84215a44ac846bc4b8e32d5e78935c5c43482e491812a0bb8aaf87e4d92118"}, +] + +[[package]] +name = "orjson" +version = "3.10.3" +description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" +optional = false +python-versions = ">=3.8" files = [ - {file = "opentelemetry_semantic_conventions-0.43b0-py3-none-any.whl", hash = "sha256:291284d7c1bf15fdaddf309b3bd6d3b7ce12a253cec6d27144439819a15d8445"}, - {file = "opentelemetry_semantic_conventions-0.43b0.tar.gz", hash = "sha256:b9576fb890df479626fa624e88dde42d3d60b8b6c8ae1152ad157a8b97358635"}, + {file = "orjson-3.10.3-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9fb6c3f9f5490a3eb4ddd46fc1b6eadb0d6fc16fb3f07320149c3286a1409dd8"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:252124b198662eee80428f1af8c63f7ff077c88723fe206a25df8dc57a57b1fa"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f3e87733823089a338ef9bbf363ef4de45e5c599a9bf50a7a9b82e86d0228da"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8334c0d87103bb9fbbe59b78129f1f40d1d1e8355bbed2ca71853af15fa4ed3"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1952c03439e4dce23482ac846e7961f9d4ec62086eb98ae76d97bd41d72644d7"}, + {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c0403ed9c706dcd2809f1600ed18f4aae50be263bd7112e54b50e2c2bc3ebd6d"}, + {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:382e52aa4270a037d41f325e7d1dfa395b7de0c367800b6f337d8157367bf3a7"}, + {file = "orjson-3.10.3-cp310-none-win32.whl", hash = "sha256:be2aab54313752c04f2cbaab4515291ef5af8c2256ce22abc007f89f42f49109"}, + {file = "orjson-3.10.3-cp310-none-win_amd64.whl", hash = "sha256:416b195f78ae461601893f482287cee1e3059ec49b4f99479aedf22a20b1098b"}, + {file = "orjson-3.10.3-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:73100d9abbbe730331f2242c1fc0bcb46a3ea3b4ae3348847e5a141265479700"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a12eee96e3ab828dbfcb4d5a0023aa971b27143a1d35dc214c176fdfb29b3"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520de5e2ef0b4ae546bea25129d6c7c74edb43fc6cf5213f511a927f2b28148b"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccaa0a401fc02e8828a5bedfd80f8cd389d24f65e5ca3954d72c6582495b4bcf"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7bc9e8bc11bac40f905640acd41cbeaa87209e7e1f57ade386da658092dc16"}, + {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3582b34b70543a1ed6944aca75e219e1192661a63da4d039d088a09c67543b08"}, + {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c23dfa91481de880890d17aa7b91d586a4746a4c2aa9a145bebdbaf233768d5"}, + {file = "orjson-3.10.3-cp311-none-win32.whl", hash = "sha256:1770e2a0eae728b050705206d84eda8b074b65ee835e7f85c919f5705b006c9b"}, + {file = "orjson-3.10.3-cp311-none-win_amd64.whl", hash = "sha256:93433b3c1f852660eb5abdc1f4dd0ced2be031ba30900433223b28ee0140cde5"}, + {file = "orjson-3.10.3-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a39aa73e53bec8d410875683bfa3a8edf61e5a1c7bb4014f65f81d36467ea098"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0943a96b3fa09bee1afdfccc2cb236c9c64715afa375b2af296c73d91c23eab2"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e852baafceff8da3c9defae29414cc8513a1586ad93e45f27b89a639c68e8176"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18566beb5acd76f3769c1d1a7ec06cdb81edc4d55d2765fb677e3eaa10fa99e0"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd2218d5a3aa43060efe649ec564ebedec8ce6ae0a43654b81376216d5ebd42"}, + {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cf20465e74c6e17a104ecf01bf8cd3b7b252565b4ccee4548f18b012ff2f8069"}, + {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba7f67aa7f983c4345eeda16054a4677289011a478ca947cd69c0a86ea45e534"}, + {file = "orjson-3.10.3-cp312-none-win32.whl", hash = "sha256:17e0713fc159abc261eea0f4feda611d32eabc35708b74bef6ad44f6c78d5ea0"}, + {file = "orjson-3.10.3-cp312-none-win_amd64.whl", hash = "sha256:4c895383b1ec42b017dd2c75ae8a5b862fc489006afde06f14afbdd0309b2af0"}, + {file = "orjson-3.10.3-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:be2719e5041e9fb76c8c2c06b9600fe8e8584e6980061ff88dcbc2691a16d20d"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0175a5798bdc878956099f5c54b9837cb62cfbf5d0b86ba6d77e43861bcec2"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:978be58a68ade24f1af7758626806e13cff7748a677faf95fbb298359aa1e20d"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16bda83b5c61586f6f788333d3cf3ed19015e3b9019188c56983b5a299210eb5"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ad1f26bea425041e0a1adad34630c4825a9e3adec49079b1fb6ac8d36f8b754"}, + {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9e253498bee561fe85d6325ba55ff2ff08fb5e7184cd6a4d7754133bd19c9195"}, + {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0a62f9968bab8a676a164263e485f30a0b748255ee2f4ae49a0224be95f4532b"}, + {file = "orjson-3.10.3-cp38-none-win32.whl", hash = "sha256:8d0b84403d287d4bfa9bf7d1dc298d5c1c5d9f444f3737929a66f2fe4fb8f134"}, + {file = "orjson-3.10.3-cp38-none-win_amd64.whl", hash = "sha256:8bc7a4df90da5d535e18157220d7915780d07198b54f4de0110eca6b6c11e290"}, + {file = "orjson-3.10.3-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9059d15c30e675a58fdcd6f95465c1522b8426e092de9fff20edebfdc15e1cb0"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d40c7f7938c9c2b934b297412c067936d0b54e4b8ab916fd1a9eb8f54c02294"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4a654ec1de8fdaae1d80d55cee65893cb06494e124681ab335218be6a0691e7"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:831c6ef73f9aa53c5f40ae8f949ff7681b38eaddb6904aab89dca4d85099cb78"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99b880d7e34542db89f48d14ddecbd26f06838b12427d5a25d71baceb5ba119d"}, + {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e5e176c994ce4bd434d7aafb9ecc893c15f347d3d2bbd8e7ce0b63071c52e25"}, + {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b69a58a37dab856491bf2d3bbf259775fdce262b727f96aafbda359cb1d114d8"}, + {file = "orjson-3.10.3-cp39-none-win32.whl", hash = "sha256:b8d4d1a6868cde356f1402c8faeb50d62cee765a1f7ffcfd6de732ab0581e063"}, + {file = "orjson-3.10.3-cp39-none-win_amd64.whl", hash = "sha256:5102f50c5fc46d94f2033fe00d392588564378260d64377aec702f21a7a22912"}, + {file = "orjson-3.10.3.tar.gz", hash = "sha256:2b166507acae7ba2f7c315dcf185a9111ad5e992ac81f2d507aac39193c2c818"}, ] [[package]] @@ -1461,18 +2116,18 @@ files = [ [[package]] name = "parso" -version = "0.8.3" +version = "0.8.4" description = "A Python Parser" optional = false python-versions = ">=3.6" files = [ - {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, - {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, + {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, + {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"}, ] [package.extras] -qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] -testing = ["docopt", "pytest (<6.0.0)"] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["docopt", "pytest"] [[package]] name = "pexpect" @@ -1488,20 +2143,68 @@ files = [ [package.dependencies] ptyprocess = ">=0.5" +[[package]] +name = "phonenumbers" +version = "8.13.37" +description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers." +optional = false +python-versions = "*" +files = [ + {file = "phonenumbers-8.13.37-py2.py3-none-any.whl", hash = "sha256:4ea00ef5012422c08c7955c21131e7ae5baa9a3ef52cf2d561e963f023006b80"}, + {file = "phonenumbers-8.13.37.tar.gz", hash = "sha256:bd315fed159aea0516f7c367231810fe8344d5bec26156b88fa18374c11d1cf2"}, +] + [[package]] name = "prompt-toolkit" -version = "3.0.43" +version = "3.0.45" description = "Library for building powerful interactive command lines in Python" optional = false python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.43-py3-none-any.whl", hash = "sha256:a11a29cb3bf0a28a387fe5122cdb649816a957cd9261dcedf8c9f1fef33eacf6"}, - {file = "prompt_toolkit-3.0.43.tar.gz", hash = "sha256:3527b7af26106cbc65a040bcc84839a3566ec1b051bb0bfe953631e704b0ff7d"}, + {file = "prompt_toolkit-3.0.45-py3-none-any.whl", hash = "sha256:a29b89160e494e3ea8622b09fa5897610b437884dcdcd054fdc1308883326c2a"}, + {file = "prompt_toolkit-3.0.45.tar.gz", hash = "sha256:07c60ee4ab7b7e90824b61afa840c8f5aad2d46b3e2e10acc33d8ecc94a49089"}, ] [package.dependencies] wcwidth = "*" +[[package]] +name = "proto-plus" +version = "1.23.0" +description = "Beautiful, Pythonic protocol buffers." +optional = false +python-versions = ">=3.6" +files = [ + {file = "proto-plus-1.23.0.tar.gz", hash = "sha256:89075171ef11988b3fa157f5dbd8b9cf09d65fffee97e29ce403cd8defba19d2"}, + {file = "proto_plus-1.23.0-py3-none-any.whl", hash = "sha256:a829c79e619e1cf632de091013a4173deed13a55f326ef84f05af6f50ff4c82c"}, +] + +[package.dependencies] +protobuf = ">=3.19.0,<5.0.0dev" + +[package.extras] +testing = ["google-api-core[grpc] (>=1.31.5)"] + +[[package]] +name = "protobuf" +version = "4.25.3" +description = "" +optional = false +python-versions = ">=3.8" +files = [ + {file = "protobuf-4.25.3-cp310-abi3-win32.whl", hash = "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa"}, + {file = "protobuf-4.25.3-cp310-abi3-win_amd64.whl", hash = "sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8"}, + {file = "protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c"}, + {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019"}, + {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d"}, + {file = "protobuf-4.25.3-cp38-cp38-win32.whl", hash = "sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2"}, + {file = "protobuf-4.25.3-cp38-cp38-win_amd64.whl", hash = "sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4"}, + {file = "protobuf-4.25.3-cp39-cp39-win32.whl", hash = "sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4"}, + {file = "protobuf-4.25.3-cp39-cp39-win_amd64.whl", hash = "sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c"}, + {file = "protobuf-4.25.3-py3-none-any.whl", hash = "sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9"}, + {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, +] + [[package]] name = "ptyprocess" version = "0.7.0" @@ -1527,68 +2230,162 @@ files = [ [package.extras] tests = ["pytest"] +[[package]] +name = "pvkoala" +version = "2.0.1" +description = "Koala Noise Suppression Engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pvkoala-2.0.1-py3-none-any.whl", hash = "sha256:8b153e076b4d14adccdcb4d800aa84e8d2f91e0640b959677582d3128cbcb249"}, + {file = "pvkoala-2.0.1.tar.gz", hash = "sha256:5e017c671fc1338d42dc20f9dee003d0144bbba1757b6f1fcd6272c5308da242"}, +] + +[[package]] +name = "pyasn1" +version = "0.6.0" +description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyasn1-0.6.0-py2.py3-none-any.whl", hash = "sha256:cca4bb0f2df5504f02f6f8a775b6e416ff9b0b3b16f7ee80b5a3153d9b804473"}, + {file = "pyasn1-0.6.0.tar.gz", hash = "sha256:3a35ab2c4b5ef98e17dfdec8ab074046fbda76e281c5a706ccd82328cfc8f64c"}, +] + +[[package]] +name = "pyasn1-modules" +version = "0.4.0" +description = "A collection of ASN.1-based protocols modules" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyasn1_modules-0.4.0-py3-none-any.whl", hash = "sha256:be04f15b66c206eed667e0bb5ab27e2b1855ea54a842e5037738099e8ca4ae0b"}, + {file = "pyasn1_modules-0.4.0.tar.gz", hash = "sha256:831dbcea1b177b28c9baddf4c6d1013c24c3accd14a1873fffaa6a2e905f17b6"}, +] + +[package.dependencies] +pyasn1 = ">=0.4.6,<0.7.0" + [[package]] name = "pycparser" -version = "2.21" +version = "2.22" description = "C parser in Python" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.8" files = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, ] [[package]] name = "pydantic" -version = "1.10.14" -description = "Data validation and settings management using python type hints" +version = "2.7.2" +description = "Data validation using Python type hints" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pydantic-1.10.14-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7f4fcec873f90537c382840f330b90f4715eebc2bc9925f04cb92de593eae054"}, - {file = "pydantic-1.10.14-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e3a76f571970fcd3c43ad982daf936ae39b3e90b8a2e96c04113a369869dc87"}, - {file = "pydantic-1.10.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d886bd3c3fbeaa963692ef6b643159ccb4b4cefaf7ff1617720cbead04fd1d"}, - {file = "pydantic-1.10.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:798a3d05ee3b71967844a1164fd5bdb8c22c6d674f26274e78b9f29d81770c4e"}, - {file = "pydantic-1.10.14-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:23d47a4b57a38e8652bcab15a658fdb13c785b9ce217cc3a729504ab4e1d6bc9"}, - {file = "pydantic-1.10.14-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f9f674b5c3bebc2eba401de64f29948ae1e646ba2735f884d1594c5f675d6f2a"}, - {file = "pydantic-1.10.14-cp310-cp310-win_amd64.whl", hash = "sha256:24a7679fab2e0eeedb5a8924fc4a694b3bcaac7d305aeeac72dd7d4e05ecbebf"}, - {file = "pydantic-1.10.14-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9d578ac4bf7fdf10ce14caba6f734c178379bd35c486c6deb6f49006e1ba78a7"}, - {file = "pydantic-1.10.14-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa7790e94c60f809c95602a26d906eba01a0abee9cc24150e4ce2189352deb1b"}, - {file = "pydantic-1.10.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aad4e10efa5474ed1a611b6d7f0d130f4aafadceb73c11d9e72823e8f508e663"}, - {file = "pydantic-1.10.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1245f4f61f467cb3dfeced2b119afef3db386aec3d24a22a1de08c65038b255f"}, - {file = "pydantic-1.10.14-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:21efacc678a11114c765eb52ec0db62edffa89e9a562a94cbf8fa10b5db5c046"}, - {file = "pydantic-1.10.14-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:412ab4a3f6dbd2bf18aefa9f79c7cca23744846b31f1d6555c2ee2b05a2e14ca"}, - {file = "pydantic-1.10.14-cp311-cp311-win_amd64.whl", hash = "sha256:e897c9f35281f7889873a3e6d6b69aa1447ceb024e8495a5f0d02ecd17742a7f"}, - {file = "pydantic-1.10.14-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d604be0f0b44d473e54fdcb12302495fe0467c56509a2f80483476f3ba92b33c"}, - {file = "pydantic-1.10.14-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a42c7d17706911199798d4c464b352e640cab4351efe69c2267823d619a937e5"}, - {file = "pydantic-1.10.14-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:596f12a1085e38dbda5cbb874d0973303e34227b400b6414782bf205cc14940c"}, - {file = "pydantic-1.10.14-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bfb113860e9288d0886e3b9e49d9cf4a9d48b441f52ded7d96db7819028514cc"}, - {file = "pydantic-1.10.14-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bc3ed06ab13660b565eed80887fcfbc0070f0aa0691fbb351657041d3e874efe"}, - {file = "pydantic-1.10.14-cp37-cp37m-win_amd64.whl", hash = "sha256:ad8c2bc677ae5f6dbd3cf92f2c7dc613507eafe8f71719727cbc0a7dec9a8c01"}, - {file = "pydantic-1.10.14-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c37c28449752bb1f47975d22ef2882d70513c546f8f37201e0fec3a97b816eee"}, - {file = "pydantic-1.10.14-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:49a46a0994dd551ec051986806122767cf144b9702e31d47f6d493c336462597"}, - {file = "pydantic-1.10.14-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53e3819bd20a42470d6dd0fe7fc1c121c92247bca104ce608e609b59bc7a77ee"}, - {file = "pydantic-1.10.14-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0fbb503bbbbab0c588ed3cd21975a1d0d4163b87e360fec17a792f7d8c4ff29f"}, - {file = "pydantic-1.10.14-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:336709883c15c050b9c55a63d6c7ff09be883dbc17805d2b063395dd9d9d0022"}, - {file = "pydantic-1.10.14-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4ae57b4d8e3312d486e2498d42aed3ece7b51848336964e43abbf9671584e67f"}, - {file = "pydantic-1.10.14-cp38-cp38-win_amd64.whl", hash = "sha256:dba49d52500c35cfec0b28aa8b3ea5c37c9df183ffc7210b10ff2a415c125c4a"}, - {file = "pydantic-1.10.14-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c66609e138c31cba607d8e2a7b6a5dc38979a06c900815495b2d90ce6ded35b4"}, - {file = "pydantic-1.10.14-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d986e115e0b39604b9eee3507987368ff8148222da213cd38c359f6f57b3b347"}, - {file = "pydantic-1.10.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:646b2b12df4295b4c3148850c85bff29ef6d0d9621a8d091e98094871a62e5c7"}, - {file = "pydantic-1.10.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282613a5969c47c83a8710cc8bfd1e70c9223feb76566f74683af889faadc0ea"}, - {file = "pydantic-1.10.14-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:466669501d08ad8eb3c4fecd991c5e793c4e0bbd62299d05111d4f827cded64f"}, - {file = "pydantic-1.10.14-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:13e86a19dca96373dcf3190fcb8797d40a6f12f154a244a8d1e8e03b8f280593"}, - {file = "pydantic-1.10.14-cp39-cp39-win_amd64.whl", hash = "sha256:08b6ec0917c30861e3fe71a93be1648a2aa4f62f866142ba21670b24444d7fd8"}, - {file = "pydantic-1.10.14-py3-none-any.whl", hash = "sha256:8ee853cd12ac2ddbf0ecbac1c289f95882b2d4482258048079d13be700aa114c"}, - {file = "pydantic-1.10.14.tar.gz", hash = "sha256:46f17b832fe27de7850896f3afee50ea682220dd218f7e9c88d436788419dca6"}, -] - -[package.dependencies] -typing-extensions = ">=4.2.0" - -[package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] + {file = "pydantic-2.7.2-py3-none-any.whl", hash = "sha256:834ab954175f94e6e68258537dc49402c4a5e9d0409b9f1b86b7e934a8372de7"}, + {file = "pydantic-2.7.2.tar.gz", hash = "sha256:71b2945998f9c9b7919a45bde9a50397b289937d215ae141c1d0903ba7149fd7"}, +] + +[package.dependencies] +annotated-types = ">=0.4.0" +pydantic-core = "2.18.3" +typing-extensions = ">=4.6.1" + +[package.extras] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.18.3" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_core-2.18.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:744697428fcdec6be5670460b578161d1ffe34743a5c15656be7ea82b008197c"}, + {file = "pydantic_core-2.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b40c05ced1ba4218b14986fe6f283d22e1ae2ff4c8e28881a70fb81fbfcda7"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a9a75622357076efb6b311983ff190fbfb3c12fc3a853122b34d3d358126c"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e2e253af04ceaebde8eb201eb3f3e3e7e390f2d275a88300d6a1959d710539e2"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:855ec66589c68aa367d989da5c4755bb74ee92ccad4fdb6af942c3612c067e34"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d3e42bb54e7e9d72c13ce112e02eb1b3b55681ee948d748842171201a03a98a"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6ac9ffccc9d2e69d9fba841441d4259cb668ac180e51b30d3632cd7abca2b9b"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c56eca1686539fa0c9bda992e7bd6a37583f20083c37590413381acfc5f192d6"}, + {file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:17954d784bf8abfc0ec2a633108207ebc4fa2df1a0e4c0c3ccbaa9bb01d2c426"}, + {file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:98ed737567d8f2ecd54f7c8d4f8572ca7c7921ede93a2e52939416170d357812"}, + {file = "pydantic_core-2.18.3-cp310-none-win32.whl", hash = "sha256:9f9e04afebd3ed8c15d67a564ed0a34b54e52136c6d40d14c5547b238390e779"}, + {file = "pydantic_core-2.18.3-cp310-none-win_amd64.whl", hash = "sha256:45e4ffbae34f7ae30d0047697e724e534a7ec0a82ef9994b7913a412c21462a0"}, + {file = "pydantic_core-2.18.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b9ebe8231726c49518b16b237b9fe0d7d361dd221302af511a83d4ada01183ab"}, + {file = "pydantic_core-2.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b8e20e15d18bf7dbb453be78a2d858f946f5cdf06c5072453dace00ab652e2b2"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0d9ff283cd3459fa0bf9b0256a2b6f01ac1ff9ffb034e24457b9035f75587cb"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f7ef5f0ebb77ba24c9970da18b771711edc5feaf00c10b18461e0f5f5949231"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73038d66614d2e5cde30435b5afdced2b473b4c77d4ca3a8624dd3e41a9c19be"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6afd5c867a74c4d314c557b5ea9520183fadfbd1df4c2d6e09fd0d990ce412cd"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd7df92f28d351bb9f12470f4c533cf03d1b52ec5a6e5c58c65b183055a60106"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:80aea0ffeb1049336043d07799eace1c9602519fb3192916ff525b0287b2b1e4"}, + {file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaee40f25bba38132e655ffa3d1998a6d576ba7cf81deff8bfa189fb43fd2bbe"}, + {file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9128089da8f4fe73f7a91973895ebf2502539d627891a14034e45fb9e707e26d"}, + {file = "pydantic_core-2.18.3-cp311-none-win32.whl", hash = "sha256:fec02527e1e03257aa25b1a4dcbe697b40a22f1229f5d026503e8b7ff6d2eda7"}, + {file = "pydantic_core-2.18.3-cp311-none-win_amd64.whl", hash = "sha256:58ff8631dbab6c7c982e6425da8347108449321f61fe427c52ddfadd66642af7"}, + {file = "pydantic_core-2.18.3-cp311-none-win_arm64.whl", hash = "sha256:3fc1c7f67f34c6c2ef9c213e0f2a351797cda98249d9ca56a70ce4ebcaba45f4"}, + {file = "pydantic_core-2.18.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f0928cde2ae416a2d1ebe6dee324709c6f73e93494d8c7aea92df99aab1fc40f"}, + {file = "pydantic_core-2.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0bee9bb305a562f8b9271855afb6ce00223f545de3d68560b3c1649c7c5295e9"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e862823be114387257dacbfa7d78547165a85d7add33b446ca4f4fae92c7ff5c"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a36f78674cbddc165abab0df961b5f96b14461d05feec5e1f78da58808b97e7"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba905d184f62e7ddbb7a5a751d8a5c805463511c7b08d1aca4a3e8c11f2e5048"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fdd362f6a586e681ff86550b2379e532fee63c52def1c666887956748eaa326"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24b214b7ee3bd3b865e963dbed0f8bc5375f49449d70e8d407b567af3222aae4"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:691018785779766127f531674fa82bb368df5b36b461622b12e176c18e119022"}, + {file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:60e4c625e6f7155d7d0dcac151edf5858102bc61bf959d04469ca6ee4e8381bd"}, + {file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4e651e47d981c1b701dcc74ab8fec5a60a5b004650416b4abbef13db23bc7be"}, + {file = "pydantic_core-2.18.3-cp312-none-win32.whl", hash = "sha256:ffecbb5edb7f5ffae13599aec33b735e9e4c7676ca1633c60f2c606beb17efc5"}, + {file = "pydantic_core-2.18.3-cp312-none-win_amd64.whl", hash = "sha256:2c8333f6e934733483c7eddffdb094c143b9463d2af7e6bd85ebcb2d4a1b82c6"}, + {file = "pydantic_core-2.18.3-cp312-none-win_arm64.whl", hash = "sha256:7a20dded653e516a4655f4c98e97ccafb13753987434fe7cf044aa25f5b7d417"}, + {file = "pydantic_core-2.18.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:eecf63195be644b0396f972c82598cd15693550f0ff236dcf7ab92e2eb6d3522"}, + {file = "pydantic_core-2.18.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c44efdd3b6125419c28821590d7ec891c9cb0dff33a7a78d9d5c8b6f66b9702"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e59fca51ffbdd1638b3856779342ed69bcecb8484c1d4b8bdb237d0eb5a45e2"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70cf099197d6b98953468461d753563b28e73cf1eade2ffe069675d2657ed1d5"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63081a49dddc6124754b32a3774331467bfc3d2bd5ff8f10df36a95602560361"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:370059b7883485c9edb9655355ff46d912f4b03b009d929220d9294c7fd9fd60"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a64faeedfd8254f05f5cf6fc755023a7e1606af3959cfc1a9285744cc711044"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19d2e725de0f90d8671f89e420d36c3dd97639b98145e42fcc0e1f6d492a46dc"}, + {file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:67bc078025d70ec5aefe6200ef094576c9d86bd36982df1301c758a9fff7d7f4"}, + {file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:adf952c3f4100e203cbaf8e0c907c835d3e28f9041474e52b651761dc248a3c0"}, + {file = "pydantic_core-2.18.3-cp38-none-win32.whl", hash = "sha256:9a46795b1f3beb167eaee91736d5d17ac3a994bf2215a996aed825a45f897558"}, + {file = "pydantic_core-2.18.3-cp38-none-win_amd64.whl", hash = "sha256:200ad4e3133cb99ed82342a101a5abf3d924722e71cd581cc113fe828f727fbc"}, + {file = "pydantic_core-2.18.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:304378b7bf92206036c8ddd83a2ba7b7d1a5b425acafff637172a3aa72ad7083"}, + {file = "pydantic_core-2.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c826870b277143e701c9ccf34ebc33ddb4d072612683a044e7cce2d52f6c3fef"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e201935d282707394f3668380e41ccf25b5794d1b131cdd96b07f615a33ca4b1"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5560dda746c44b48bf82b3d191d74fe8efc5686a9ef18e69bdabccbbb9ad9442"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b32c2a1f8032570842257e4c19288eba9a2bba4712af542327de9a1204faff8"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:929c24e9dea3990bc8bcd27c5f2d3916c0c86f5511d2caa69e0d5290115344a9"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a8376fef60790152564b0eab376b3e23dd6e54f29d84aad46f7b264ecca943"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dccf3ef1400390ddd1fb55bf0632209d39140552d068ee5ac45553b556780e06"}, + {file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:41dbdcb0c7252b58fa931fec47937edb422c9cb22528f41cb8963665c372caf6"}, + {file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:666e45cf071669fde468886654742fa10b0e74cd0fa0430a46ba6056b24fb0af"}, + {file = "pydantic_core-2.18.3-cp39-none-win32.whl", hash = "sha256:f9c08cabff68704a1b4667d33f534d544b8a07b8e5d039c37067fceb18789e78"}, + {file = "pydantic_core-2.18.3-cp39-none-win_amd64.whl", hash = "sha256:4afa5f5973e8572b5c0dcb4e2d4fda7890e7cd63329bd5cc3263a25c92ef0026"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:77319771a026f7c7d29c6ebc623de889e9563b7087911b46fd06c044a12aa5e9"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:df11fa992e9f576473038510d66dd305bcd51d7dd508c163a8c8fe148454e059"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d531076bdfb65af593326ffd567e6ab3da145020dafb9187a1d131064a55f97c"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d33ce258e4e6e6038f2b9e8b8a631d17d017567db43483314993b3ca345dcbbb"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1f9cd7f5635b719939019be9bda47ecb56e165e51dd26c9a217a433e3d0d59a9"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cd4a032bb65cc132cae1fe3e52877daecc2097965cd3914e44fbd12b00dae7c5"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f2718430098bcdf60402136c845e4126a189959d103900ebabb6774a5d9fdb"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c0037a92cf0c580ed14e10953cdd26528e8796307bb8bb312dc65f71547df04d"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b95a0972fac2b1ff3c94629fc9081b16371dad870959f1408cc33b2f78ad347a"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a62e437d687cc148381bdd5f51e3e81f5b20a735c55f690c5be94e05da2b0d5c"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b367a73a414bbb08507da102dc2cde0fa7afe57d09b3240ce82a16d608a7679c"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ecce4b2360aa3f008da3327d652e74a0e743908eac306198b47e1c58b03dd2b"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd4435b8d83f0c9561a2a9585b1de78f1abb17cb0cef5f39bf6a4b47d19bafe3"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:616221a6d473c5b9aa83fa8982745441f6a4a62a66436be9445c65f241b86c94"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7e6382ce89a92bc1d0c0c5edd51e931432202b9080dc921d8d003e616402efd1"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ff58f379345603d940e461eae474b6bbb6dab66ed9a851ecd3cb3709bf4dcf6a"}, + {file = "pydantic_core-2.18.3.tar.gz", hash = "sha256:432e999088d85c8f36b9a3f769a8e2b57aabd817bbb729a90d1fe7f18f6f1f39"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pydub" @@ -1603,19 +2400,55 @@ files = [ [[package]] name = "pygments" -version = "2.17.2" +version = "2.18.0" description = "Pygments is a syntax highlighting package written in Python." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, - {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, ] [package.extras] -plugins = ["importlib-metadata"] windows-terminal = ["colorama (>=0.4.6)"] +[[package]] +name = "pyht" +version = "0.0.28" +description = "" +optional = false +python-versions = "<4.0,>=3.8" +files = [ + {file = "pyht-0.0.28-py3-none-any.whl", hash = "sha256:ad8801acaa906eff5d6b39ce5ca76a08c154f705a2d0b2b6e841b219ef7875be"}, + {file = "pyht-0.0.28.tar.gz", hash = "sha256:00792e8c068fc905557525de9db0dbd7dcb651e15f05c6cc49490340b95a444a"}, +] + +[package.dependencies] +filelock = ">=3.12.4,<4.0.0" +grpcio = ">=1.58.0,<2.0.0" +protobuf = ">=4.24.3,<5.0.0" +requests = ">=2.31.0,<3.0.0" + +[[package]] +name = "pyjwt" +version = "2.8.0" +description = "JSON Web Token implementation in Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, + {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, +] + +[package.dependencies] +cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"crypto\""} + +[package.extras] +crypto = ["cryptography (>=3.4.0)"] +dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] +docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] +tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] + [[package]] name = "python-dotenv" version = "1.0.1" @@ -1632,17 +2465,28 @@ cli = ["click (>=5.0)"] [[package]] name = "python-multipart" -version = "0.0.6" +version = "0.0.9" description = "A streaming multipart parser for Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "python_multipart-0.0.6-py3-none-any.whl", hash = "sha256:ee698bab5ef148b0a760751c261902cd096e57e10558e11aca17646b74ee1c18"}, - {file = "python_multipart-0.0.6.tar.gz", hash = "sha256:e9925a80bb668529f1b67c7fdb0a5dacdd7cbfc6fb0bff3ea443fe22bdd62132"}, + {file = "python_multipart-0.0.9-py3-none-any.whl", hash = "sha256:97ca7b8ea7b05f977dc3849c3ba99d51689822fab725c3703af7c866a0c2b215"}, + {file = "python_multipart-0.0.9.tar.gz", hash = "sha256:03f54688c663f1b7977105f021043b0793151e4cb1c1a9d4a11fc13d622c4026"}, ] [package.extras] -dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==1.7.3)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"] +dev = ["atomicwrites (==1.4.1)", "attrs (==23.2.0)", "coverage (==7.4.1)", "hatch", "invoke (==2.2.0)", "more-itertools (==10.2.0)", "pbr (==6.0.0)", "pluggy (==1.4.0)", "py (==1.11.0)", "pytest (==8.0.0)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.2.0)", "pyyaml (==6.0.1)", "ruff (==0.2.1)"] + +[[package]] +name = "pytz" +version = "2024.1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, +] [[package]] name = "pyyaml" @@ -1656,6 +2500,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -1663,8 +2508,16 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -1681,6 +2534,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -1688,122 +2542,142 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] +[[package]] +name = "redis" +version = "5.0.4" +description = "Python client for Redis database and key-value store" +optional = false +python-versions = ">=3.7" +files = [ + {file = "redis-5.0.4-py3-none-any.whl", hash = "sha256:7adc2835c7a9b5033b7ad8f8918d09b7344188228809c98df07af226d39dec91"}, + {file = "redis-5.0.4.tar.gz", hash = "sha256:ec31f2ed9675cc54c21ba854cfe0462e6faf1d83c8ce5944709db8a4700b9c61"}, +] + +[package.dependencies] +async-timeout = {version = ">=4.0.3", markers = "python_full_version < \"3.11.3\""} + +[package.extras] +hiredis = ["hiredis (>=1.0.0)"] +ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"] + +[[package]] +name = "referencing" +version = "0.35.1" +description = "JSON Referencing + Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"}, + {file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + [[package]] name = "regex" -version = "2023.12.25" +version = "2024.5.15" description = "Alternative regular expression module, to replace re." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"}, - {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"}, - {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"}, - {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"}, - {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"}, - {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"}, - {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"}, - {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"}, - {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"}, - {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"}, - {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"}, - {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"}, - {file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"}, - {file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"}, - {file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"}, - {file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"}, - {file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53"}, + {file = "regex-2024.5.15-cp310-cp310-win32.whl", hash = "sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3"}, + {file = "regex-2024.5.15-cp310-cp310-win_amd64.whl", hash = "sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68"}, + {file = "regex-2024.5.15-cp311-cp311-win32.whl", hash = "sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa"}, + {file = "regex-2024.5.15-cp311-cp311-win_amd64.whl", hash = "sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80"}, + {file = "regex-2024.5.15-cp312-cp312-win32.whl", hash = "sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe"}, + {file = "regex-2024.5.15-cp312-cp312-win_amd64.whl", hash = "sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741"}, + {file = "regex-2024.5.15-cp38-cp38-win32.whl", hash = "sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9"}, + {file = "regex-2024.5.15-cp38-cp38-win_amd64.whl", hash = "sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456"}, + {file = "regex-2024.5.15-cp39-cp39-win32.whl", hash = "sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694"}, + {file = "regex-2024.5.15-cp39-cp39-win_amd64.whl", hash = "sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388"}, + {file = "regex-2024.5.15.tar.gz", hash = "sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c"}, ] [[package]] name = "requests" -version = "2.31.0" +version = "2.32.3" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -1817,46 +2691,206 @@ socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] -name = "scipy" -version = "1.12.0" -description = "Fundamental algorithms for scientific computing in Python" +name = "rich" +version = "13.7.1" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false -python-versions = ">=3.9" +python-versions = ">=3.7.0" +files = [ + {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"}, + {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + +[[package]] +name = "rpds-py" +version = "0.18.1" +description = "Python bindings to Rust's persistent data structures (rpds)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "rpds_py-0.18.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:d31dea506d718693b6b2cffc0648a8929bdc51c70a311b2770f09611caa10d53"}, + {file = "rpds_py-0.18.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:732672fbc449bab754e0b15356c077cc31566df874964d4801ab14f71951ea80"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a98a1f0552b5f227a3d6422dbd61bc6f30db170939bd87ed14f3c339aa6c7c9"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f1944ce16401aad1e3f7d312247b3d5de7981f634dc9dfe90da72b87d37887d"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38e14fb4e370885c4ecd734f093a2225ee52dc384b86fa55fe3f74638b2cfb09"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08d74b184f9ab6289b87b19fe6a6d1a97fbfea84b8a3e745e87a5de3029bf944"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d70129cef4a8d979caa37e7fe957202e7eee8ea02c5e16455bc9808a59c6b2f0"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ce0bb20e3a11bd04461324a6a798af34d503f8d6f1aa3d2aa8901ceaf039176d"}, + {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81c5196a790032e0fc2464c0b4ab95f8610f96f1f2fa3d4deacce6a79852da60"}, + {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f3027be483868c99b4985fda802a57a67fdf30c5d9a50338d9db646d590198da"}, + {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d44607f98caa2961bab4fa3c4309724b185b464cdc3ba6f3d7340bac3ec97cc1"}, + {file = "rpds_py-0.18.1-cp310-none-win32.whl", hash = "sha256:c273e795e7a0f1fddd46e1e3cb8be15634c29ae8ff31c196debb620e1edb9333"}, + {file = "rpds_py-0.18.1-cp310-none-win_amd64.whl", hash = "sha256:8352f48d511de5f973e4f2f9412736d7dea76c69faa6d36bcf885b50c758ab9a"}, + {file = "rpds_py-0.18.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6b5ff7e1d63a8281654b5e2896d7f08799378e594f09cf3674e832ecaf396ce8"}, + {file = "rpds_py-0.18.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8927638a4d4137a289e41d0fd631551e89fa346d6dbcfc31ad627557d03ceb6d"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:154bf5c93d79558b44e5b50cc354aa0459e518e83677791e6adb0b039b7aa6a7"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07f2139741e5deb2c5154a7b9629bc5aa48c766b643c1a6750d16f865a82c5fc"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c7672e9fba7425f79019db9945b16e308ed8bc89348c23d955c8c0540da0a07"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:489bdfe1abd0406eba6b3bb4fdc87c7fa40f1031de073d0cfb744634cc8fa261"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c20f05e8e3d4fc76875fc9cb8cf24b90a63f5a1b4c5b9273f0e8225e169b100"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:967342e045564cef76dfcf1edb700b1e20838d83b1aa02ab313e6a497cf923b8"}, + {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2cc7c1a47f3a63282ab0f422d90ddac4aa3034e39fc66a559ab93041e6505da7"}, + {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f7afbfee1157e0f9376c00bb232e80a60e59ed716e3211a80cb8506550671e6e"}, + {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9e6934d70dc50f9f8ea47081ceafdec09245fd9f6032669c3b45705dea096b88"}, + {file = "rpds_py-0.18.1-cp311-none-win32.whl", hash = "sha256:c69882964516dc143083d3795cb508e806b09fc3800fd0d4cddc1df6c36e76bb"}, + {file = "rpds_py-0.18.1-cp311-none-win_amd64.whl", hash = "sha256:70a838f7754483bcdc830444952fd89645569e7452e3226de4a613a4c1793fb2"}, + {file = "rpds_py-0.18.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3dd3cd86e1db5aadd334e011eba4e29d37a104b403e8ca24dcd6703c68ca55b3"}, + {file = "rpds_py-0.18.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:05f3d615099bd9b13ecf2fc9cf2d839ad3f20239c678f461c753e93755d629ee"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35b2b771b13eee8729a5049c976197ff58a27a3829c018a04341bcf1ae409b2b"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ee17cd26b97d537af8f33635ef38be873073d516fd425e80559f4585a7b90c43"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b646bf655b135ccf4522ed43d6902af37d3f5dbcf0da66c769a2b3938b9d8184"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19ba472b9606c36716062c023afa2484d1e4220548751bda14f725a7de17b4f6"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e30ac5e329098903262dc5bdd7e2086e0256aa762cc8b744f9e7bf2a427d3f8"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d58ad6317d188c43750cb76e9deacf6051d0f884d87dc6518e0280438648a9ac"}, + {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e1735502458621921cee039c47318cb90b51d532c2766593be6207eec53e5c4c"}, + {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f5bab211605d91db0e2995a17b5c6ee5edec1270e46223e513eaa20da20076ac"}, + {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2fc24a329a717f9e2448f8cd1f960f9dac4e45b6224d60734edeb67499bab03a"}, + {file = "rpds_py-0.18.1-cp312-none-win32.whl", hash = "sha256:1805d5901779662d599d0e2e4159d8a82c0b05faa86ef9222bf974572286b2b6"}, + {file = "rpds_py-0.18.1-cp312-none-win_amd64.whl", hash = "sha256:720edcb916df872d80f80a1cc5ea9058300b97721efda8651efcd938a9c70a72"}, + {file = "rpds_py-0.18.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:c827576e2fa017a081346dce87d532a5310241648eb3700af9a571a6e9fc7e74"}, + {file = "rpds_py-0.18.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aa3679e751408d75a0b4d8d26d6647b6d9326f5e35c00a7ccd82b78ef64f65f8"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0abeee75434e2ee2d142d650d1e54ac1f8b01e6e6abdde8ffd6eeac6e9c38e20"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed402d6153c5d519a0faf1bb69898e97fb31613b49da27a84a13935ea9164dfc"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:338dee44b0cef8b70fd2ef54b4e09bb1b97fc6c3a58fea5db6cc083fd9fc2724"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7750569d9526199c5b97e5a9f8d96a13300950d910cf04a861d96f4273d5b104"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:607345bd5912aacc0c5a63d45a1f73fef29e697884f7e861094e443187c02be5"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:207c82978115baa1fd8d706d720b4a4d2b0913df1c78c85ba73fe6c5804505f0"}, + {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6d1e42d2735d437e7e80bab4d78eb2e459af48c0a46e686ea35f690b93db792d"}, + {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5463c47c08630007dc0fe99fb480ea4f34a89712410592380425a9b4e1611d8e"}, + {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:06d218939e1bf2ca50e6b0ec700ffe755e5216a8230ab3e87c059ebb4ea06afc"}, + {file = "rpds_py-0.18.1-cp38-none-win32.whl", hash = "sha256:312fe69b4fe1ffbe76520a7676b1e5ac06ddf7826d764cc10265c3b53f96dbe9"}, + {file = "rpds_py-0.18.1-cp38-none-win_amd64.whl", hash = "sha256:9437ca26784120a279f3137ee080b0e717012c42921eb07861b412340f85bae2"}, + {file = "rpds_py-0.18.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:19e515b78c3fc1039dd7da0a33c28c3154458f947f4dc198d3c72db2b6b5dc93"}, + {file = "rpds_py-0.18.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7b28c5b066bca9a4eb4e2f2663012debe680f097979d880657f00e1c30875a0"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:673fdbbf668dd958eff750e500495ef3f611e2ecc209464f661bc82e9838991e"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d960de62227635d2e61068f42a6cb6aae91a7fe00fca0e3aeed17667c8a34611"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:352a88dc7892f1da66b6027af06a2e7e5d53fe05924cc2cfc56495b586a10b72"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e0ee01ad8260184db21468a6e1c37afa0529acc12c3a697ee498d3c2c4dcaf3"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4c39ad2f512b4041343ea3c7894339e4ca7839ac38ca83d68a832fc8b3748ab"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aaa71ee43a703c321906813bb252f69524f02aa05bf4eec85f0c41d5d62d0f4c"}, + {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6cd8098517c64a85e790657e7b1e509b9fe07487fd358e19431cb120f7d96338"}, + {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:4adec039b8e2928983f885c53b7cc4cda8965b62b6596501a0308d2703f8af1b"}, + {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:32b7daaa3e9389db3695964ce8e566e3413b0c43e3394c05e4b243a4cd7bef26"}, + {file = "rpds_py-0.18.1-cp39-none-win32.whl", hash = "sha256:2625f03b105328729f9450c8badda34d5243231eef6535f80064d57035738360"}, + {file = "rpds_py-0.18.1-cp39-none-win_amd64.whl", hash = "sha256:bf18932d0003c8c4d51a39f244231986ab23ee057d235a12b2684ea26a353590"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cbfbea39ba64f5e53ae2915de36f130588bba71245b418060ec3330ebf85678e"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:a3d456ff2a6a4d2adcdf3c1c960a36f4fd2fec6e3b4902a42a384d17cf4e7a65"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7700936ef9d006b7ef605dc53aa364da2de5a3aa65516a1f3ce73bf82ecfc7ae"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:51584acc5916212e1bf45edd17f3a6b05fe0cbb40482d25e619f824dccb679de"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:942695a206a58d2575033ff1e42b12b2aece98d6003c6bc739fbf33d1773b12f"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b906b5f58892813e5ba5c6056d6a5ad08f358ba49f046d910ad992196ea61397"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6f8e3fecca256fefc91bb6765a693d96692459d7d4c644660a9fff32e517843"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7732770412bab81c5a9f6d20aeb60ae943a9b36dcd990d876a773526468e7163"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:bd1105b50ede37461c1d51b9698c4f4be6e13e69a908ab7751e3807985fc0346"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:618916f5535784960f3ecf8111581f4ad31d347c3de66d02e728de460a46303c"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:17c6d2155e2423f7e79e3bb18151c686d40db42d8645e7977442170c360194d4"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c4c4c3f878df21faf5fac86eda32671c27889e13570645a9eea0a1abdd50922"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:fab6ce90574645a0d6c58890e9bcaac8d94dff54fb51c69e5522a7358b80ab64"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:531796fb842b53f2695e94dc338929e9f9dbf473b64710c28af5a160b2a8927d"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:740884bc62a5e2bbb31e584f5d23b32320fd75d79f916f15a788d527a5e83644"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:998125738de0158f088aef3cb264a34251908dd2e5d9966774fdab7402edfab7"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e2be6e9dd4111d5b31ba3b74d17da54a8319d8168890fbaea4b9e5c3de630ae5"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0cee71bc618cd93716f3c1bf56653740d2d13ddbd47673efa8bf41435a60daa"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2c3caec4ec5cd1d18e5dd6ae5194d24ed12785212a90b37f5f7f06b8bedd7139"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:27bba383e8c5231cd559affe169ca0b96ec78d39909ffd817f28b166d7ddd4d8"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:a888e8bdb45916234b99da2d859566f1e8a1d2275a801bb8e4a9644e3c7e7909"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6031b25fb1b06327b43d841f33842b383beba399884f8228a6bb3df3088485ff"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48c2faaa8adfacefcbfdb5f2e2e7bdad081e5ace8d182e5f4ade971f128e6bb3"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:d85164315bd68c0806768dc6bb0429c6f95c354f87485ee3593c4f6b14def2bd"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6afd80f6c79893cfc0574956f78a0add8c76e3696f2d6a15bca2c66c415cf2d4"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa242ac1ff583e4ec7771141606aafc92b361cd90a05c30d93e343a0c2d82a89"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21be4770ff4e08698e1e8e0bce06edb6ea0626e7c8f560bc08222880aca6a6f"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c45a639e93a0c5d4b788b2613bd637468edd62f8f95ebc6fcc303d58ab3f0a8"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910e71711d1055b2768181efa0a17537b2622afeb0424116619817007f8a2b10"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b9bb1f182a97880f6078283b3505a707057c42bf55d8fca604f70dedfdc0772a"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d54f74f40b1f7aaa595a02ff42ef38ca654b1469bef7d52867da474243cc633"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:8d2e182c9ee01135e11e9676e9a62dfad791a7a467738f06726872374a83db49"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:636a15acc588f70fda1661234761f9ed9ad79ebed3f2125d44be0862708b666e"}, + {file = "rpds_py-0.18.1.tar.gz", hash = "sha256:dc48b479d540770c811fbd1eb9ba2bb66951863e448efec2e2c102625328e92f"}, +] + +[[package]] +name = "rsa" +version = "4.9" +description = "Pure-Python RSA implementation" +optional = false +python-versions = ">=3.6,<4" +files = [ + {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, + {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, +] + +[package.dependencies] +pyasn1 = ">=0.1.3" + +[[package]] +name = "sentry-sdk" +version = "2.3.1" +description = "Python client for Sentry (https://sentry.io)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "sentry_sdk-2.3.1-py2.py3-none-any.whl", hash = "sha256:c5aeb095ba226391d337dd42a6f9470d86c9fc236ecc71cfc7cd1942b45010c6"}, + {file = "sentry_sdk-2.3.1.tar.gz", hash = "sha256:139a71a19f5e9eb5d3623942491ce03cf8ebc14ea2e39ba3e6fe79560d8a5b1f"}, +] + +[package.dependencies] +certifi = "*" +fastapi = {version = ">=0.79.0", optional = true, markers = "extra == \"fastapi\""} +urllib3 = ">=1.26.11" + +[package.extras] +aiohttp = ["aiohttp (>=3.5)"] +anthropic = ["anthropic (>=0.16)"] +arq = ["arq (>=0.23)"] +asyncpg = ["asyncpg (>=0.23)"] +beam = ["apache-beam (>=2.12)"] +bottle = ["bottle (>=0.12.13)"] +celery = ["celery (>=3)"] +celery-redbeat = ["celery-redbeat (>=2)"] +chalice = ["chalice (>=1.16.0)"] +clickhouse-driver = ["clickhouse-driver (>=0.2.0)"] +django = ["django (>=1.8)"] +falcon = ["falcon (>=1.4)"] +fastapi = ["fastapi (>=0.79.0)"] +flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"] +grpcio = ["grpcio (>=1.21.1)", "protobuf (>=3.8.0)"] +httpx = ["httpx (>=0.16.0)"] +huey = ["huey (>=2)"] +huggingface-hub = ["huggingface-hub (>=0.22)"] +langchain = ["langchain (>=0.0.210)"] +loguru = ["loguru (>=0.5)"] +openai = ["openai (>=1.0.0)", "tiktoken (>=0.3.0)"] +opentelemetry = ["opentelemetry-distro (>=0.35b0)"] +opentelemetry-experimental = ["opentelemetry-distro (>=0.40b0,<1.0)", "opentelemetry-instrumentation-aiohttp-client (>=0.40b0,<1.0)", "opentelemetry-instrumentation-django (>=0.40b0,<1.0)", "opentelemetry-instrumentation-fastapi (>=0.40b0,<1.0)", "opentelemetry-instrumentation-flask (>=0.40b0,<1.0)", "opentelemetry-instrumentation-requests (>=0.40b0,<1.0)", "opentelemetry-instrumentation-sqlite3 (>=0.40b0,<1.0)", "opentelemetry-instrumentation-urllib (>=0.40b0,<1.0)"] +pure-eval = ["asttokens", "executing", "pure-eval"] +pymongo = ["pymongo (>=3.1)"] +pyspark = ["pyspark (>=2.4.4)"] +quart = ["blinker (>=1.1)", "quart (>=0.16.1)"] +rq = ["rq (>=0.6)"] +sanic = ["sanic (>=0.8)"] +sqlalchemy = ["sqlalchemy (>=1.2)"] +starlette = ["starlette (>=0.19.1)"] +starlite = ["starlite (>=1.48)"] +tornado = ["tornado (>=5)"] + +[[package]] +name = "shellingham" +version = "1.5.4" +description = "Tool to Detect Surrounding Shell" +optional = false +python-versions = ">=3.7" files = [ - {file = "scipy-1.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:78e4402e140879387187f7f25d91cc592b3501a2e51dfb320f48dfb73565f10b"}, - {file = "scipy-1.12.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:f5f00ebaf8de24d14b8449981a2842d404152774c1a1d880c901bf454cb8e2a1"}, - {file = "scipy-1.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e53958531a7c695ff66c2e7bb7b79560ffdc562e2051644c5576c39ff8efb563"}, - {file = "scipy-1.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e32847e08da8d895ce09d108a494d9eb78974cf6de23063f93306a3e419960c"}, - {file = "scipy-1.12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4c1020cad92772bf44b8e4cdabc1df5d87376cb219742549ef69fc9fd86282dd"}, - {file = "scipy-1.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:75ea2a144096b5e39402e2ff53a36fecfd3b960d786b7efd3c180e29c39e53f2"}, - {file = "scipy-1.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:408c68423f9de16cb9e602528be4ce0d6312b05001f3de61fe9ec8b1263cad08"}, - {file = "scipy-1.12.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:5adfad5dbf0163397beb4aca679187d24aec085343755fcdbdeb32b3679f254c"}, - {file = "scipy-1.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3003652496f6e7c387b1cf63f4bb720951cfa18907e998ea551e6de51a04467"}, - {file = "scipy-1.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b8066bce124ee5531d12a74b617d9ac0ea59245246410e19bca549656d9a40a"}, - {file = "scipy-1.12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8bee4993817e204d761dba10dbab0774ba5a8612e57e81319ea04d84945375ba"}, - {file = "scipy-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:a24024d45ce9a675c1fb8494e8e5244efea1c7a09c60beb1eeb80373d0fecc70"}, - {file = "scipy-1.12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e7e76cc48638228212c747ada851ef355c2bb5e7f939e10952bc504c11f4e372"}, - {file = "scipy-1.12.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:f7ce148dffcd64ade37b2df9315541f9adad6efcaa86866ee7dd5db0c8f041c3"}, - {file = "scipy-1.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c39f92041f490422924dfdb782527a4abddf4707616e07b021de33467f917bc"}, - {file = "scipy-1.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7ebda398f86e56178c2fa94cad15bf457a218a54a35c2a7b4490b9f9cb2676c"}, - {file = "scipy-1.12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:95e5c750d55cf518c398a8240571b0e0782c2d5a703250872f36eaf737751338"}, - {file = "scipy-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:e646d8571804a304e1da01040d21577685ce8e2db08ac58e543eaca063453e1c"}, - {file = "scipy-1.12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:913d6e7956c3a671de3b05ccb66b11bc293f56bfdef040583a7221d9e22a2e35"}, - {file = "scipy-1.12.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba1b0c7256ad75401c73e4b3cf09d1f176e9bd4248f0d3112170fb2ec4db067"}, - {file = "scipy-1.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:730badef9b827b368f351eacae2e82da414e13cf8bd5051b4bdfd720271a5371"}, - {file = "scipy-1.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6546dc2c11a9df6926afcbdd8a3edec28566e4e785b915e849348c6dd9f3f490"}, - {file = "scipy-1.12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:196ebad3a4882081f62a5bf4aeb7326aa34b110e533aab23e4374fcccb0890dc"}, - {file = "scipy-1.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:b360f1b6b2f742781299514e99ff560d1fe9bd1bff2712894b52abe528d1fd1e"}, - {file = "scipy-1.12.0.tar.gz", hash = "sha256:4bf5abab8a36d20193c698b0f1fc282c1d083c94723902c447e5d2f1780936a3"}, -] - -[package.dependencies] -numpy = ">=1.22.4,<1.29.0" - -[package.extras] -dev = ["click", "cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pydevtool", "rich-click", "ruff", "types-psutil", "typing_extensions"] -doc = ["jupytext", "matplotlib (>2)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] -test = ["asv", "gmpy2", "hypothesis", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] + {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, + {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, +] [[package]] name = "six" @@ -1871,27 +2905,27 @@ files = [ [[package]] name = "sniffio" -version = "1.3.0" +version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" files = [ - {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, - {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] [[package]] name = "sounddevice" -version = "0.4.6" +version = "0.4.7" description = "Play and Record Sound with Python" optional = false python-versions = ">=3.7" files = [ - {file = "sounddevice-0.4.6-py3-none-any.whl", hash = "sha256:5de768ba6fe56ad2b5aaa2eea794b76b73e427961c95acad2ee2ed7f866a4b20"}, - {file = "sounddevice-0.4.6-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl", hash = "sha256:8b0b806c205dd3e3cd5a97262b2482624fd21db7d47083b887090148a08051c8"}, - {file = "sounddevice-0.4.6-py3-none-win32.whl", hash = "sha256:e3ba6e674ffa8f79a591d744a1d4ab922fe5bdfd4faf8b25069a08e051010b7b"}, - {file = "sounddevice-0.4.6-py3-none-win_amd64.whl", hash = "sha256:7830d4f8f8570f2e5552942f81d96999c5fcd9a0b682d6fc5d5c5529df23be2c"}, - {file = "sounddevice-0.4.6.tar.gz", hash = "sha256:3236b78f15f0415bdf006a620cef073d0c0522851d66f4a961ed6d8eb1482fe9"}, + {file = "sounddevice-0.4.7-py3-none-any.whl", hash = "sha256:1c3f18bfa4d9a257f5715f2ab83f2c0eb412a09f3e6a9fa73720886ca88f6bc7"}, + {file = "sounddevice-0.4.7-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl", hash = "sha256:d6ddfd341ad7412b14ca001f2c4dbf5fa2503bdc9eb15ad2c3105f6c260b698a"}, + {file = "sounddevice-0.4.7-py3-none-win32.whl", hash = "sha256:1ec1df094c468a210113aa22c4f390d5b4d9c7a73e41a6cb6ecfec83db59b380"}, + {file = "sounddevice-0.4.7-py3-none-win_amd64.whl", hash = "sha256:0c8b3543da1496f282b66a7bc54b755577ba638b1af06c146d4ac7f39d86b548"}, + {file = "sounddevice-0.4.7.tar.gz", hash = "sha256:69b386818d50a2d518607d4b973442e8d524760c7cd6c8b8be03d8c98fc4bce7"}, ] [package.dependencies] @@ -1900,80 +2934,62 @@ CFFI = ">=1.0" [package.extras] numpy = ["NumPy"] -[[package]] -name = "speechrecognition" -version = "3.10.1" -description = "Library for performing speech recognition, with support for several engines and APIs, online and offline." -optional = false -python-versions = ">=3.8" -files = [ - {file = "SpeechRecognition-3.10.1-py2.py3-none-any.whl", hash = "sha256:69898b2b0bbd5bc65647c5ef833fe318ad74f02e8a6af5c9fd671933083660bc"}, - {file = "SpeechRecognition-3.10.1.tar.gz", hash = "sha256:718731886b7836e20a06b9a2c6cace12a9e130971bb6af1b1dd130b22bad9f82"}, -] - -[package.dependencies] -requests = ">=2.26.0" -typing-extensions = "*" - -[package.extras] -whisper-api = ["openai"] - [[package]] name = "sqlalchemy" -version = "2.0.25" +version = "2.0.30" description = "Database Abstraction Library" optional = false python-versions = ">=3.7" files = [ - {file = "SQLAlchemy-2.0.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4344d059265cc8b1b1be351bfb88749294b87a8b2bbe21dfbe066c4199541ebd"}, - {file = "SQLAlchemy-2.0.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6f9e2e59cbcc6ba1488404aad43de005d05ca56e069477b33ff74e91b6319735"}, - {file = "SQLAlchemy-2.0.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84daa0a2055df9ca0f148a64fdde12ac635e30edbca80e87df9b3aaf419e144a"}, - {file = "SQLAlchemy-2.0.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc8b7dabe8e67c4832891a5d322cec6d44ef02f432b4588390017f5cec186a84"}, - {file = "SQLAlchemy-2.0.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f5693145220517b5f42393e07a6898acdfe820e136c98663b971906120549da5"}, - {file = "SQLAlchemy-2.0.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:db854730a25db7c956423bb9fb4bdd1216c839a689bf9cc15fada0a7fb2f4570"}, - {file = "SQLAlchemy-2.0.25-cp310-cp310-win32.whl", hash = "sha256:14a6f68e8fc96e5e8f5647ef6cda6250c780612a573d99e4d881581432ef1669"}, - {file = "SQLAlchemy-2.0.25-cp310-cp310-win_amd64.whl", hash = "sha256:87f6e732bccd7dcf1741c00f1ecf33797383128bd1c90144ac8adc02cbb98643"}, - {file = "SQLAlchemy-2.0.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:342d365988ba88ada8af320d43df4e0b13a694dbd75951f537b2d5e4cb5cd002"}, - {file = "SQLAlchemy-2.0.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f37c0caf14b9e9b9e8f6dbc81bc56db06acb4363eba5a633167781a48ef036ed"}, - {file = "SQLAlchemy-2.0.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa9373708763ef46782d10e950b49d0235bfe58facebd76917d3f5cbf5971aed"}, - {file = "SQLAlchemy-2.0.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d24f571990c05f6b36a396218f251f3e0dda916e0c687ef6fdca5072743208f5"}, - {file = "SQLAlchemy-2.0.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75432b5b14dc2fff43c50435e248b45c7cdadef73388e5610852b95280ffd0e9"}, - {file = "SQLAlchemy-2.0.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:884272dcd3ad97f47702965a0e902b540541890f468d24bd1d98bcfe41c3f018"}, - {file = "SQLAlchemy-2.0.25-cp311-cp311-win32.whl", hash = "sha256:e607cdd99cbf9bb80391f54446b86e16eea6ad309361942bf88318bcd452363c"}, - {file = "SQLAlchemy-2.0.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d505815ac340568fd03f719446a589162d55c52f08abd77ba8964fbb7eb5b5f"}, - {file = "SQLAlchemy-2.0.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0dacf67aee53b16f365c589ce72e766efaabd2b145f9de7c917777b575e3659d"}, - {file = "SQLAlchemy-2.0.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b801154027107461ee992ff4b5c09aa7cc6ec91ddfe50d02bca344918c3265c6"}, - {file = "SQLAlchemy-2.0.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59a21853f5daeb50412d459cfb13cb82c089ad4c04ec208cd14dddd99fc23b39"}, - {file = "SQLAlchemy-2.0.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29049e2c299b5ace92cbed0c1610a7a236f3baf4c6b66eb9547c01179f638ec5"}, - {file = "SQLAlchemy-2.0.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b64b183d610b424a160b0d4d880995e935208fc043d0302dd29fee32d1ee3f95"}, - {file = "SQLAlchemy-2.0.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4f7a7d7fcc675d3d85fbf3b3828ecd5990b8d61bd6de3f1b260080b3beccf215"}, - {file = "SQLAlchemy-2.0.25-cp312-cp312-win32.whl", hash = "sha256:cf18ff7fc9941b8fc23437cc3e68ed4ebeff3599eec6ef5eebf305f3d2e9a7c2"}, - {file = "SQLAlchemy-2.0.25-cp312-cp312-win_amd64.whl", hash = "sha256:91f7d9d1c4dd1f4f6e092874c128c11165eafcf7c963128f79e28f8445de82d5"}, - {file = "SQLAlchemy-2.0.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bb209a73b8307f8fe4fe46f6ad5979649be01607f11af1eb94aa9e8a3aaf77f0"}, - {file = "SQLAlchemy-2.0.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:798f717ae7c806d67145f6ae94dc7c342d3222d3b9a311a784f371a4333212c7"}, - {file = "SQLAlchemy-2.0.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fdd402169aa00df3142149940b3bf9ce7dde075928c1886d9a1df63d4b8de62"}, - {file = "SQLAlchemy-2.0.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0d3cab3076af2e4aa5693f89622bef7fa770c6fec967143e4da7508b3dceb9b9"}, - {file = "SQLAlchemy-2.0.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:74b080c897563f81062b74e44f5a72fa44c2b373741a9ade701d5f789a10ba23"}, - {file = "SQLAlchemy-2.0.25-cp37-cp37m-win32.whl", hash = "sha256:87d91043ea0dc65ee583026cb18e1b458d8ec5fc0a93637126b5fc0bc3ea68c4"}, - {file = "SQLAlchemy-2.0.25-cp37-cp37m-win_amd64.whl", hash = "sha256:75f99202324383d613ddd1f7455ac908dca9c2dd729ec8584c9541dd41822a2c"}, - {file = "SQLAlchemy-2.0.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:420362338681eec03f53467804541a854617faed7272fe71a1bfdb07336a381e"}, - {file = "SQLAlchemy-2.0.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c88f0c7dcc5f99bdb34b4fd9b69b93c89f893f454f40219fe923a3a2fd11625"}, - {file = "SQLAlchemy-2.0.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3be4987e3ee9d9a380b66393b77a4cd6d742480c951a1c56a23c335caca4ce3"}, - {file = "SQLAlchemy-2.0.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a159111a0f58fb034c93eeba211b4141137ec4b0a6e75789ab7a3ef3c7e7e3"}, - {file = "SQLAlchemy-2.0.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8b8cb63d3ea63b29074dcd29da4dc6a97ad1349151f2d2949495418fd6e48db9"}, - {file = "SQLAlchemy-2.0.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:736ea78cd06de6c21ecba7416499e7236a22374561493b456a1f7ffbe3f6cdb4"}, - {file = "SQLAlchemy-2.0.25-cp38-cp38-win32.whl", hash = "sha256:10331f129982a19df4284ceac6fe87353ca3ca6b4ca77ff7d697209ae0a5915e"}, - {file = "SQLAlchemy-2.0.25-cp38-cp38-win_amd64.whl", hash = "sha256:c55731c116806836a5d678a70c84cb13f2cedba920212ba7dcad53260997666d"}, - {file = "SQLAlchemy-2.0.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:605b6b059f4b57b277f75ace81cc5bc6335efcbcc4ccb9066695e515dbdb3900"}, - {file = "SQLAlchemy-2.0.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:665f0a3954635b5b777a55111ababf44b4fc12b1f3ba0a435b602b6387ffd7cf"}, - {file = "SQLAlchemy-2.0.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecf6d4cda1f9f6cb0b45803a01ea7f034e2f1aed9475e883410812d9f9e3cfcf"}, - {file = "SQLAlchemy-2.0.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c51db269513917394faec5e5c00d6f83829742ba62e2ac4fa5c98d58be91662f"}, - {file = "SQLAlchemy-2.0.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:790f533fa5c8901a62b6fef5811d48980adeb2f51f1290ade8b5e7ba990ba3de"}, - {file = "SQLAlchemy-2.0.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1b1180cda6df7af84fe72e4530f192231b1f29a7496951db4ff38dac1687202d"}, - {file = "SQLAlchemy-2.0.25-cp39-cp39-win32.whl", hash = "sha256:555651adbb503ac7f4cb35834c5e4ae0819aab2cd24857a123370764dc7d7e24"}, - {file = "SQLAlchemy-2.0.25-cp39-cp39-win_amd64.whl", hash = "sha256:dc55990143cbd853a5d038c05e79284baedf3e299661389654551bd02a6a68d7"}, - {file = "SQLAlchemy-2.0.25-py3-none-any.whl", hash = "sha256:a86b4240e67d4753dc3092d9511886795b3c2852abe599cffe108952f7af7ac3"}, - {file = "SQLAlchemy-2.0.25.tar.gz", hash = "sha256:a2c69a7664fb2d54b8682dd774c3b54f67f84fa123cf84dda2a5f40dcaa04e08"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3b48154678e76445c7ded1896715ce05319f74b1e73cf82d4f8b59b46e9c0ddc"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2753743c2afd061bb95a61a51bbb6a1a11ac1c44292fad898f10c9839a7f75b2"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7bfc726d167f425d4c16269a9a10fe8630ff6d14b683d588044dcef2d0f6be7"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4f61ada6979223013d9ab83a3ed003ded6959eae37d0d685db2c147e9143797"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a365eda439b7a00732638f11072907c1bc8e351c7665e7e5da91b169af794af"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bba002a9447b291548e8d66fd8c96a6a7ed4f2def0bb155f4f0a1309fd2735d5"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-win32.whl", hash = "sha256:0138c5c16be3600923fa2169532205d18891b28afa817cb49b50e08f62198bb8"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-win_amd64.whl", hash = "sha256:99650e9f4cf3ad0d409fed3eec4f071fadd032e9a5edc7270cd646a26446feeb"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:955991a09f0992c68a499791a753523f50f71a6885531568404fa0f231832aa0"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f69e4c756ee2686767eb80f94c0125c8b0a0b87ede03eacc5c8ae3b54b99dc46"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69c9db1ce00e59e8dd09d7bae852a9add716efdc070a3e2068377e6ff0d6fdaa"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1429a4b0f709f19ff3b0cf13675b2b9bfa8a7e79990003207a011c0db880a13"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:efedba7e13aa9a6c8407c48facfdfa108a5a4128e35f4c68f20c3407e4376aa9"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:16863e2b132b761891d6c49f0a0f70030e0bcac4fd208117f6b7e053e68668d0"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-win32.whl", hash = "sha256:2ecabd9ccaa6e914e3dbb2aa46b76dede7eadc8cbf1b8083c94d936bcd5ffb49"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-win_amd64.whl", hash = "sha256:0b3f4c438e37d22b83e640f825ef0f37b95db9aa2d68203f2c9549375d0b2260"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5a79d65395ac5e6b0c2890935bad892eabb911c4aa8e8015067ddb37eea3d56c"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9a5baf9267b752390252889f0c802ea13b52dfee5e369527da229189b8bd592e"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cb5a646930c5123f8461f6468901573f334c2c63c795b9af350063a736d0134"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:296230899df0b77dec4eb799bcea6fbe39a43707ce7bb166519c97b583cfcab3"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c62d401223f468eb4da32627bffc0c78ed516b03bb8a34a58be54d618b74d472"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3b69e934f0f2b677ec111b4d83f92dc1a3210a779f69bf905273192cf4ed433e"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-win32.whl", hash = "sha256:77d2edb1f54aff37e3318f611637171e8ec71472f1fdc7348b41dcb226f93d90"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-win_amd64.whl", hash = "sha256:b6c7ec2b1f4969fc19b65b7059ed00497e25f54069407a8701091beb69e591a5"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5a8e3b0a7e09e94be7510d1661339d6b52daf202ed2f5b1f9f48ea34ee6f2d57"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b60203c63e8f984df92035610c5fb76d941254cf5d19751faab7d33b21e5ddc0"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1dc3eabd8c0232ee8387fbe03e0a62220a6f089e278b1f0aaf5e2d6210741ad"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:40ad017c672c00b9b663fcfcd5f0864a0a97828e2ee7ab0c140dc84058d194cf"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e42203d8d20dc704604862977b1470a122e4892791fe3ed165f041e4bf447a1b"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-win32.whl", hash = "sha256:2a4f4da89c74435f2bc61878cd08f3646b699e7d2eba97144030d1be44e27584"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-win_amd64.whl", hash = "sha256:b6bf767d14b77f6a18b6982cbbf29d71bede087edae495d11ab358280f304d8e"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc0c53579650a891f9b83fa3cecd4e00218e071d0ba00c4890f5be0c34887ed3"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:311710f9a2ee235f1403537b10c7687214bb1f2b9ebb52702c5aa4a77f0b3af7"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:408f8b0e2c04677e9c93f40eef3ab22f550fecb3011b187f66a096395ff3d9fd"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37a4b4fb0dd4d2669070fb05b8b8824afd0af57587393015baee1cf9890242d9"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a943d297126c9230719c27fcbbeab57ecd5d15b0bd6bfd26e91bfcfe64220621"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0a089e218654e740a41388893e090d2e2c22c29028c9d1353feb38638820bbeb"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-win32.whl", hash = "sha256:fa561138a64f949f3e889eb9ab8c58e1504ab351d6cf55259dc4c248eaa19da6"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-win_amd64.whl", hash = "sha256:7d74336c65705b986d12a7e337ba27ab2b9d819993851b140efdf029248e818e"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae8c62fe2480dd61c532ccafdbce9b29dacc126fe8be0d9a927ca3e699b9491a"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2383146973a15435e4717f94c7509982770e3e54974c71f76500a0136f22810b"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8409de825f2c3b62ab15788635ccaec0c881c3f12a8af2b12ae4910a0a9aeef6"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0094c5dc698a5f78d3d1539853e8ecec02516b62b8223c970c86d44e7a80f6c7"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:edc16a50f5e1b7a06a2dcc1f2205b0b961074c123ed17ebda726f376a5ab0953"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f7703c2010355dd28f53deb644a05fc30f796bd8598b43f0ba678878780b6e4c"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-win32.whl", hash = "sha256:1f9a727312ff6ad5248a4367358e2cf7e625e98b1028b1d7ab7b806b7d757513"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-win_amd64.whl", hash = "sha256:a0ef36b28534f2a5771191be6edb44cc2673c7b2edf6deac6562400288664221"}, + {file = "SQLAlchemy-2.0.30-py3-none-any.whl", hash = "sha256:7108d569d3990c71e26a42f60474b4c02c8586c4681af5fd67e51a044fdea86a"}, + {file = "SQLAlchemy-2.0.30.tar.gz", hash = "sha256:2b1708916730f4830bc69d6f49d37f7698b5bd7530aca7f04f785f8849e95255"}, ] [package.dependencies] @@ -2026,172 +3042,214 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] [[package]] name = "starlette" -version = "0.27.0" +version = "0.37.2" description = "The little ASGI library that shines." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"}, - {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"}, + {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"}, + {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"}, ] [package.dependencies] anyio = ">=3.4.0,<5" -typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [package.extras] -full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] +full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"] [[package]] name = "tenacity" -version = "8.2.3" +version = "8.3.0" description = "Retry code until it succeeds" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "tenacity-8.3.0-py3-none-any.whl", hash = "sha256:3649f6443dbc0d9b01b9d8020a9c4ec7a1ff5f6f3c6c8a036ef371f573fe9185"}, + {file = "tenacity-8.3.0.tar.gz", hash = "sha256:953d4e6ad24357bceffbc9707bc74349aca9d245f68eb65419cf0c249a1949a2"}, +] + +[package.extras] +doc = ["reno", "sphinx"] +test = ["pytest", "tornado (>=4.5)", "typeguard"] + +[[package]] +name = "tiktoken" +version = "0.7.0" +description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" +optional = false +python-versions = ">=3.8" files = [ - {file = "tenacity-8.2.3-py3-none-any.whl", hash = "sha256:ce510e327a630c9e1beaf17d42e6ffacc88185044ad85cf74c0a8887c6a0f88c"}, - {file = "tenacity-8.2.3.tar.gz", hash = "sha256:5398ef0d78e63f40007c1fb4c0bff96e1911394d2fa8d194f77619c05ff6cc8a"}, + {file = "tiktoken-0.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485f3cc6aba7c6b6ce388ba634fbba656d9ee27f766216f45146beb4ac18b25f"}, + {file = "tiktoken-0.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e54be9a2cd2f6d6ffa3517b064983fb695c9a9d8aa7d574d1ef3c3f931a99225"}, + {file = "tiktoken-0.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79383a6e2c654c6040e5f8506f3750db9ddd71b550c724e673203b4f6b4b4590"}, + {file = "tiktoken-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d4511c52caacf3c4981d1ae2df85908bd31853f33d30b345c8b6830763f769c"}, + {file = "tiktoken-0.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13c94efacdd3de9aff824a788353aa5749c0faee1fbe3816df365ea450b82311"}, + {file = "tiktoken-0.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8e58c7eb29d2ab35a7a8929cbeea60216a4ccdf42efa8974d8e176d50c9a3df5"}, + {file = "tiktoken-0.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:21a20c3bd1dd3e55b91c1331bf25f4af522c525e771691adbc9a69336fa7f702"}, + {file = "tiktoken-0.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:10c7674f81e6e350fcbed7c09a65bca9356eaab27fb2dac65a1e440f2bcfe30f"}, + {file = "tiktoken-0.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:084cec29713bc9d4189a937f8a35dbdfa785bd1235a34c1124fe2323821ee93f"}, + {file = "tiktoken-0.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:811229fde1652fedcca7c6dfe76724d0908775b353556d8a71ed74d866f73f7b"}, + {file = "tiktoken-0.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86b6e7dc2e7ad1b3757e8a24597415bafcfb454cebf9a33a01f2e6ba2e663992"}, + {file = "tiktoken-0.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1063c5748be36344c7e18c7913c53e2cca116764c2080177e57d62c7ad4576d1"}, + {file = "tiktoken-0.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:20295d21419bfcca092644f7e2f2138ff947a6eb8cfc732c09cc7d76988d4a89"}, + {file = "tiktoken-0.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:959d993749b083acc57a317cbc643fb85c014d055b2119b739487288f4e5d1cb"}, + {file = "tiktoken-0.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:71c55d066388c55a9c00f61d2c456a6086673ab7dec22dd739c23f77195b1908"}, + {file = "tiktoken-0.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:09ed925bccaa8043e34c519fbb2f99110bd07c6fd67714793c21ac298e449410"}, + {file = "tiktoken-0.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03c6c40ff1db0f48a7b4d2dafeae73a5607aacb472fa11f125e7baf9dce73704"}, + {file = "tiktoken-0.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d20b5c6af30e621b4aca094ee61777a44118f52d886dbe4f02b70dfe05c15350"}, + {file = "tiktoken-0.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d427614c3e074004efa2f2411e16c826f9df427d3c70a54725cae860f09e4bf4"}, + {file = "tiktoken-0.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8c46d7af7b8c6987fac9b9f61041b452afe92eb087d29c9ce54951280f899a97"}, + {file = "tiktoken-0.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:0bc603c30b9e371e7c4c7935aba02af5994a909fc3c0fe66e7004070858d3f8f"}, + {file = "tiktoken-0.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2398fecd38c921bcd68418675a6d155fad5f5e14c2e92fcf5fe566fa5485a858"}, + {file = "tiktoken-0.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f5f6afb52fb8a7ea1c811e435e4188f2bef81b5e0f7a8635cc79b0eef0193d6"}, + {file = "tiktoken-0.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:861f9ee616766d736be4147abac500732b505bf7013cfaf019b85892637f235e"}, + {file = "tiktoken-0.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54031f95c6939f6b78122c0aa03a93273a96365103793a22e1793ee86da31685"}, + {file = "tiktoken-0.7.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fffdcb319b614cf14f04d02a52e26b1d1ae14a570f90e9b55461a72672f7b13d"}, + {file = "tiktoken-0.7.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c72baaeaefa03ff9ba9688624143c858d1f6b755bb85d456d59e529e17234769"}, + {file = "tiktoken-0.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:131b8aeb043a8f112aad9f46011dced25d62629091e51d9dc1adbf4a1cc6aa98"}, + {file = "tiktoken-0.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cabc6dc77460df44ec5b879e68692c63551ae4fae7460dd4ff17181df75f1db7"}, + {file = "tiktoken-0.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8d57f29171255f74c0aeacd0651e29aa47dff6f070cb9f35ebc14c82278f3b25"}, + {file = "tiktoken-0.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ee92776fdbb3efa02a83f968c19d4997a55c8e9ce7be821ceee04a1d1ee149c"}, + {file = "tiktoken-0.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e215292e99cb41fbc96988ef62ea63bb0ce1e15f2c147a61acc319f8b4cbe5bf"}, + {file = "tiktoken-0.7.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8a81bac94769cab437dd3ab0b8a4bc4e0f9cf6835bcaa88de71f39af1791727a"}, + {file = "tiktoken-0.7.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d6d73ea93e91d5ca771256dfc9d1d29f5a554b83821a1dc0891987636e0ae226"}, + {file = "tiktoken-0.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:2bcb28ddf79ffa424f171dfeef9a4daff61a94c631ca6813f43967cb263b83b9"}, + {file = "tiktoken-0.7.0.tar.gz", hash = "sha256:1077266e949c24e0291f6c350433c6f0971365ece2b173a23bc3b9f9defef6b6"}, ] +[package.dependencies] +regex = ">=2022.1.18" +requests = ">=2.26.0" + [package.extras] -doc = ["reno", "sphinx", "tornado (>=4.5)"] +blobfile = ["blobfile (>=2)"] [[package]] name = "tokenizers" -version = "0.15.1" +version = "0.19.1" description = "" optional = false python-versions = ">=3.7" files = [ - {file = "tokenizers-0.15.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:32c9491dd1bcb33172c26b454dbd607276af959b9e78fa766e2694cafab3103c"}, - {file = "tokenizers-0.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29a1b784b870a097e7768f8c20c2dd851e2c75dad3efdae69a79d3e7f1d614d5"}, - {file = "tokenizers-0.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0049fbe648af04148b08cb211994ce8365ee628ce49724b56aaefd09a3007a78"}, - {file = "tokenizers-0.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e84b3c235219e75e24de6b71e6073cd2c8d740b14d88e4c6d131b90134e3a338"}, - {file = "tokenizers-0.15.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8cc575769ea11d074308c6d71cb10b036cdaec941562c07fc7431d956c502f0e"}, - {file = "tokenizers-0.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22bf28f299c4158e6d0b5eaebddfd500c4973d947ffeaca8bcbe2e8c137dff0b"}, - {file = "tokenizers-0.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:506555f98361db9c74e1323a862d77dcd7d64c2058829a368bf4159d986e339f"}, - {file = "tokenizers-0.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7061b0a28ade15906f5b2ec8c48d3bdd6e24eca6b427979af34954fbe31d5cef"}, - {file = "tokenizers-0.15.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7ed5e35507b7a0e2aac3285c4f5e37d4ec5cfc0e5825b862b68a0aaf2757af52"}, - {file = "tokenizers-0.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1c9df9247df0de6509dd751b1c086e5f124b220133b5c883bb691cb6fb3d786f"}, - {file = "tokenizers-0.15.1-cp310-none-win32.whl", hash = "sha256:dd999af1b4848bef1b11d289f04edaf189c269d5e6afa7a95fa1058644c3f021"}, - {file = "tokenizers-0.15.1-cp310-none-win_amd64.whl", hash = "sha256:39d06a57f7c06940d602fad98702cf7024c4eee7f6b9fe76b9f2197d5a4cc7e2"}, - {file = "tokenizers-0.15.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8ad034eb48bf728af06915e9294871f72fcc5254911eddec81d6df8dba1ce055"}, - {file = "tokenizers-0.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea9ede7c42f8fa90f31bfc40376fd91a7d83a4aa6ad38e6076de961d48585b26"}, - {file = "tokenizers-0.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b85d6fe1a20d903877aa0ef32ef6b96e81e0e48b71c206d6046ce16094de6970"}, - {file = "tokenizers-0.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a7d44f656320137c7d643b9c7dcc1814763385de737fb98fd2643880910f597"}, - {file = "tokenizers-0.15.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd244bd0793cdacf27ee65ec3db88c21f5815460e8872bbeb32b040469d6774e"}, - {file = "tokenizers-0.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3f4a36e371b3cb1123adac8aeeeeab207ad32f15ed686d9d71686a093bb140"}, - {file = "tokenizers-0.15.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2921a53966afb29444da98d56a6ccbef23feb3b0c0f294b4e502370a0a64f25"}, - {file = "tokenizers-0.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f49068cf51f49c231067f1a8c9fc075ff960573f6b2a956e8e1b0154fb638ea5"}, - {file = "tokenizers-0.15.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0ab1a22f20eaaab832ab3b00a0709ca44a0eb04721e580277579411b622c741c"}, - {file = "tokenizers-0.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:671268f24b607c4adc6fa2b5b580fd4211b9f84b16bd7f46d62f8e5be0aa7ba4"}, - {file = "tokenizers-0.15.1-cp311-none-win32.whl", hash = "sha256:a4f03e33d2bf7df39c8894032aba599bf90f6f6378e683a19d28871f09bb07fc"}, - {file = "tokenizers-0.15.1-cp311-none-win_amd64.whl", hash = "sha256:30f689537bcc7576d8bd4daeeaa2cb8f36446ba2f13f421b173e88f2d8289c4e"}, - {file = "tokenizers-0.15.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f3a379dd0898a82ea3125e8f9c481373f73bffce6430d4315f0b6cd5547e409"}, - {file = "tokenizers-0.15.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d870ae58bba347d38ac3fc8b1f662f51e9c95272d776dd89f30035c83ee0a4f"}, - {file = "tokenizers-0.15.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d6d28e0143ec2e253a8a39e94bf1d24776dbe73804fa748675dbffff4a5cd6d8"}, - {file = "tokenizers-0.15.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61ae9ac9f44e2da128ee35db69489883b522f7abe033733fa54eb2de30dac23d"}, - {file = "tokenizers-0.15.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d8e322a47e29128300b3f7749a03c0ec2bce0a3dc8539ebff738d3f59e233542"}, - {file = "tokenizers-0.15.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:760334f475443bc13907b1a8e1cb0aeaf88aae489062546f9704dce6c498bfe2"}, - {file = "tokenizers-0.15.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1b173753d4aca1e7d0d4cb52b5e3ffecfb0ca014e070e40391b6bb4c1d6af3f2"}, - {file = "tokenizers-0.15.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82c1f13d457c8f0ab17e32e787d03470067fe8a3b4d012e7cc57cb3264529f4a"}, - {file = "tokenizers-0.15.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:425b46ceff4505f20191df54b50ac818055d9d55023d58ae32a5d895b6f15bb0"}, - {file = "tokenizers-0.15.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:681ac6ba3b4fdaf868ead8971221a061f580961c386e9732ea54d46c7b72f286"}, - {file = "tokenizers-0.15.1-cp312-none-win32.whl", hash = "sha256:f2272656063ccfba2044df2115095223960d80525d208e7a32f6c01c351a6f4a"}, - {file = "tokenizers-0.15.1-cp312-none-win_amd64.whl", hash = "sha256:9abe103203b1c6a2435d248d5ff4cceebcf46771bfbc4957a98a74da6ed37674"}, - {file = "tokenizers-0.15.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:2ce9ed5c8ef26b026a66110e3c7b73d93ec2d26a0b1d0ea55ddce61c0e5f446f"}, - {file = "tokenizers-0.15.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:89b24d366137986c3647baac29ef902d2d5445003d11c30df52f1bd304689aeb"}, - {file = "tokenizers-0.15.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0faebedd01b413ab777ca0ee85914ed8b031ea5762ab0ea60b707ce8b9be6842"}, - {file = "tokenizers-0.15.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdbd9dfcdad4f3b95d801f768e143165165055c18e44ca79a8a26de889cd8e85"}, - {file = "tokenizers-0.15.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:97194324c12565b07e9993ca9aa813b939541185682e859fb45bb8d7d99b3193"}, - {file = "tokenizers-0.15.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:485e43e2cc159580e0d83fc919ec3a45ae279097f634b1ffe371869ffda5802c"}, - {file = "tokenizers-0.15.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:191d084d60e3589d6420caeb3f9966168269315f8ec7fbc3883122dc9d99759d"}, - {file = "tokenizers-0.15.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01c28cc8d7220634a75b14c53f4fc9d1b485f99a5a29306a999c115921de2897"}, - {file = "tokenizers-0.15.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:325212027745d3f8d5d5006bb9e5409d674eb80a184f19873f4f83494e1fdd26"}, - {file = "tokenizers-0.15.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:3c5573603c36ce12dbe318bcfb490a94cad2d250f34deb2f06cb6937957bbb71"}, - {file = "tokenizers-0.15.1-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:1441161adb6d71a15a630d5c1d8659d5ebe41b6b209586fbeea64738e58fcbb2"}, - {file = "tokenizers-0.15.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:382a8d0c31afcfb86571afbfefa37186df90865ce3f5b731842dab4460e53a38"}, - {file = "tokenizers-0.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e76959783e3f4ec73b3f3d24d4eec5aa9225f0bee565c48e77f806ed1e048f12"}, - {file = "tokenizers-0.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:401df223e5eb927c5961a0fc6b171818a2bba01fb36ef18c3e1b69b8cd80e591"}, - {file = "tokenizers-0.15.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c52606c233c759561a16e81b2290a7738c3affac7a0b1f0a16fe58dc22e04c7d"}, - {file = "tokenizers-0.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b72c658bbe5a05ed8bc2ac5ad782385bfd743ffa4bc87d9b5026341e709c6f44"}, - {file = "tokenizers-0.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:25f5643a2f005c42f0737a326c6c6bdfedfdc9a994b10a1923d9c3e792e4d6a6"}, - {file = "tokenizers-0.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c5b6f633999d6b42466bbfe21be2e26ad1760b6f106967a591a41d8cbca980e"}, - {file = "tokenizers-0.15.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ceb5c9ad11a015150b545c1a11210966a45b8c3d68a942e57cf8938c578a77ca"}, - {file = "tokenizers-0.15.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bedd4ce0c4872db193444c395b11c7697260ce86a635ab6d48102d76be07d324"}, - {file = "tokenizers-0.15.1-cp37-none-win32.whl", hash = "sha256:cd6caef6c14f5ed6d35f0ddb78eab8ca6306d0cd9870330bccff72ad014a6f42"}, - {file = "tokenizers-0.15.1-cp37-none-win_amd64.whl", hash = "sha256:d2bd7af78f58d75a55e5df61efae164ab9200c04b76025f9cc6eeb7aff3219c2"}, - {file = "tokenizers-0.15.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:59b3ca6c02e0bd5704caee274978bd055de2dff2e2f39dadf536c21032dfd432"}, - {file = "tokenizers-0.15.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:48fe21b67c22583bed71933a025fd66b1f5cfae1baefa423c3d40379b5a6e74e"}, - {file = "tokenizers-0.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3d190254c66a20fb1efbdf035e6333c5e1f1c73b1f7bfad88f9c31908ac2c2c4"}, - {file = "tokenizers-0.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fef90c8f5abf17d48d6635f5fd92ad258acd1d0c2d920935c8bf261782cfe7c8"}, - {file = "tokenizers-0.15.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fac011ef7da3357aa7eb19efeecf3d201ede9618f37ddedddc5eb809ea0963ca"}, - {file = "tokenizers-0.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:574ec5b3e71d1feda6b0ecac0e0445875729b4899806efbe2b329909ec75cb50"}, - {file = "tokenizers-0.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aca16c3c0637c051a59ea99c4253f16fbb43034fac849076a7e7913b2b9afd2d"}, - {file = "tokenizers-0.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a6f238fc2bbfd3e12e8529980ec1624c7e5b69d4e959edb3d902f36974f725a"}, - {file = "tokenizers-0.15.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:587e11a26835b73c31867a728f32ca8a93c9ded4a6cd746516e68b9d51418431"}, - {file = "tokenizers-0.15.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6456e7ad397352775e2efdf68a9ec5d6524bbc4543e926eef428d36de627aed4"}, - {file = "tokenizers-0.15.1-cp38-none-win32.whl", hash = "sha256:614f0da7dd73293214bd143e6221cafd3f7790d06b799f33a987e29d057ca658"}, - {file = "tokenizers-0.15.1-cp38-none-win_amd64.whl", hash = "sha256:a4fa0a20d9f69cc2bf1cfce41aa40588598e77ec1d6f56bf0eb99769969d1ede"}, - {file = "tokenizers-0.15.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:8d3f18a45e0cf03ce193d5900460dc2430eec4e14c786e5d79bddba7ea19034f"}, - {file = "tokenizers-0.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:38dbd6c38f88ad7d5dc5d70c764415d38fe3bcd99dc81638b572d093abc54170"}, - {file = "tokenizers-0.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:777286b1f7e52de92aa4af49fe31046cfd32885d1bbaae918fab3bba52794c33"}, - {file = "tokenizers-0.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58d4d550a3862a47dd249892d03a025e32286eb73cbd6bc887fb8fb64bc97165"}, - {file = "tokenizers-0.15.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4eda68ce0344f35042ae89220b40a0007f721776b727806b5c95497b35714bb7"}, - {file = "tokenizers-0.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cd33d15f7a3a784c3b665cfe807b8de3c6779e060349bd5005bb4ae5bdcb437"}, - {file = "tokenizers-0.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a1aa370f978ac0bfb50374c3a40daa93fd56d47c0c70f0c79607fdac2ccbb42"}, - {file = "tokenizers-0.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:241482b940340fff26a2708cb9ba383a5bb8a2996d67a0ff2c4367bf4b86cc3a"}, - {file = "tokenizers-0.15.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:68f30b05f46a4d9aba88489eadd021904afe90e10a7950e28370d6e71b9db021"}, - {file = "tokenizers-0.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5a3c5d8025529670462b881b7b2527aacb6257398c9ec8e170070432c3ae3a82"}, - {file = "tokenizers-0.15.1-cp39-none-win32.whl", hash = "sha256:74d1827830f60a9d78da8f6d49a1fbea5422ce0eea42e2617877d23380a7efbc"}, - {file = "tokenizers-0.15.1-cp39-none-win_amd64.whl", hash = "sha256:9ff499923e4d6876d6b6a63ea84a56805eb35e91dd89b933a7aee0c56a3838c6"}, - {file = "tokenizers-0.15.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b3aa007a0f4408f62a8471bdaa3faccad644cbf2622639f2906b4f9b5339e8b8"}, - {file = "tokenizers-0.15.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f3d4176fa93d8b2070db8f3c70dc21106ae6624fcaaa334be6bdd3a0251e729e"}, - {file = "tokenizers-0.15.1-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1d0e463655ef8b2064df07bd4a445ed7f76f6da3b286b4590812587d42f80e89"}, - {file = "tokenizers-0.15.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:089138fd0351b62215c462a501bd68b8df0e213edcf99ab9efd5dba7b4cb733e"}, - {file = "tokenizers-0.15.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e563ac628f5175ed08e950430e2580e544b3e4b606a0995bb6b52b3a3165728"}, - {file = "tokenizers-0.15.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:244dcc28c5fde221cb4373961b20da30097669005b122384d7f9f22752487a46"}, - {file = "tokenizers-0.15.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d82951d46052dddae1369e68ff799a0e6e29befa9a0b46e387ae710fd4daefb0"}, - {file = "tokenizers-0.15.1-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7b14296bc9059849246ceb256ffbe97f8806a9b5d707e0095c22db312f4fc014"}, - {file = "tokenizers-0.15.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0309357bb9b6c8d86cdf456053479d7112074b470651a997a058cd7ad1c4ea57"}, - {file = "tokenizers-0.15.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:083f06e9d8d01b70b67bcbcb7751b38b6005512cce95808be6bf34803534a7e7"}, - {file = "tokenizers-0.15.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85288aea86ada579789447f0dcec108ebef8da4b450037eb4813d83e4da9371e"}, - {file = "tokenizers-0.15.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:385e6fcb01e8de90c1d157ae2a5338b23368d0b1c4cc25088cdca90147e35d17"}, - {file = "tokenizers-0.15.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:60067edfcbf7d6cd448ac47af41ec6e84377efbef7be0c06f15a7c1dd069e044"}, - {file = "tokenizers-0.15.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5f7e37f89acfe237d4eaf93c3b69b0f01f407a7a5d0b5a8f06ba91943ea3cf10"}, - {file = "tokenizers-0.15.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:6a63a15b523d42ebc1f4028e5a568013388c2aefa4053a263e511cb10aaa02f1"}, - {file = "tokenizers-0.15.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2417d9e4958a6c2fbecc34c27269e74561c55d8823bf914b422e261a11fdd5fd"}, - {file = "tokenizers-0.15.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8550974bace6210e41ab04231e06408cf99ea4279e0862c02b8d47e7c2b2828"}, - {file = "tokenizers-0.15.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:194ba82129b171bcd29235a969e5859a93e491e9b0f8b2581f500f200c85cfdd"}, - {file = "tokenizers-0.15.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:1bfd95eef8b01e6c0805dbccc8eaf41d8c5a84f0cce72c0ab149fe76aae0bce6"}, - {file = "tokenizers-0.15.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b87a15dd72f8216b03c151e3dace00c75c3fe7b0ee9643c25943f31e582f1a34"}, - {file = "tokenizers-0.15.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6ac22f358a0c2a6c685be49136ce7ea7054108986ad444f567712cf274b34cd8"}, - {file = "tokenizers-0.15.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1e9d1f046a9b9d9a95faa103f07db5921d2c1c50f0329ebba4359350ee02b18b"}, - {file = "tokenizers-0.15.1-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a0fd30a4b74485f6a7af89fffb5fb84d6d5f649b3e74f8d37f624cc9e9e97cf"}, - {file = "tokenizers-0.15.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80e45dc206b9447fa48795a1247c69a1732d890b53e2cc51ba42bc2fefa22407"}, - {file = "tokenizers-0.15.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4eaff56ef3e218017fa1d72007184401f04cb3a289990d2b6a0a76ce71c95f96"}, - {file = "tokenizers-0.15.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:b41dc107e4a4e9c95934e79b025228bbdda37d9b153d8b084160e88d5e48ad6f"}, - {file = "tokenizers-0.15.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:1922b8582d0c33488764bcf32e80ef6054f515369e70092729c928aae2284bc2"}, - {file = "tokenizers-0.15.1.tar.gz", hash = "sha256:c0a331d6d5a3d6e97b7f99f562cee8d56797180797bc55f12070e495e717c980"}, -] - -[package.dependencies] -huggingface_hub = ">=0.16.4,<1.0" + {file = "tokenizers-0.19.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:952078130b3d101e05ecfc7fc3640282d74ed26bcf691400f872563fca15ac97"}, + {file = "tokenizers-0.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82c8b8063de6c0468f08e82c4e198763e7b97aabfe573fd4cf7b33930ca4df77"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f03727225feaf340ceeb7e00604825addef622d551cbd46b7b775ac834c1e1c4"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:453e4422efdfc9c6b6bf2eae00d5e323f263fff62b29a8c9cd526c5003f3f642"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:02e81bf089ebf0e7f4df34fa0207519f07e66d8491d963618252f2e0729e0b46"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b07c538ba956843833fee1190cf769c60dc62e1cf934ed50d77d5502194d63b1"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e28cab1582e0eec38b1f38c1c1fb2e56bce5dc180acb1724574fc5f47da2a4fe"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b01afb7193d47439f091cd8f070a1ced347ad0f9144952a30a41836902fe09e"}, + {file = "tokenizers-0.19.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7fb297edec6c6841ab2e4e8f357209519188e4a59b557ea4fafcf4691d1b4c98"}, + {file = "tokenizers-0.19.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2e8a3dd055e515df7054378dc9d6fa8c8c34e1f32777fb9a01fea81496b3f9d3"}, + {file = "tokenizers-0.19.1-cp310-none-win32.whl", hash = "sha256:7ff898780a155ea053f5d934925f3902be2ed1f4d916461e1a93019cc7250837"}, + {file = "tokenizers-0.19.1-cp310-none-win_amd64.whl", hash = "sha256:bea6f9947e9419c2fda21ae6c32871e3d398cba549b93f4a65a2d369662d9403"}, + {file = "tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5c88d1481f1882c2e53e6bb06491e474e420d9ac7bdff172610c4f9ad3898059"}, + {file = "tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ddf672ed719b4ed82b51499100f5417d7d9f6fb05a65e232249268f35de5ed14"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:dadc509cc8a9fe460bd274c0e16ac4184d0958117cf026e0ea8b32b438171594"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfedf31824ca4915b511b03441784ff640378191918264268e6923da48104acc"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac11016d0a04aa6487b1513a3a36e7bee7eec0e5d30057c9c0408067345c48d2"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76951121890fea8330d3a0df9a954b3f2a37e3ec20e5b0530e9a0044ca2e11fe"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b342d2ce8fc8d00f376af068e3274e2e8649562e3bc6ae4a67784ded6b99428d"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d16ff18907f4909dca9b076b9c2d899114dd6abceeb074eca0c93e2353f943aa"}, + {file = "tokenizers-0.19.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:706a37cc5332f85f26efbe2bdc9ef8a9b372b77e4645331a405073e4b3a8c1c6"}, + {file = "tokenizers-0.19.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:16baac68651701364b0289979ecec728546133e8e8fe38f66fe48ad07996b88b"}, + {file = "tokenizers-0.19.1-cp311-none-win32.whl", hash = "sha256:9ed240c56b4403e22b9584ee37d87b8bfa14865134e3e1c3fb4b2c42fafd3256"}, + {file = "tokenizers-0.19.1-cp311-none-win_amd64.whl", hash = "sha256:ad57d59341710b94a7d9dbea13f5c1e7d76fd8d9bcd944a7a6ab0b0da6e0cc66"}, + {file = "tokenizers-0.19.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:621d670e1b1c281a1c9698ed89451395d318802ff88d1fc1accff0867a06f153"}, + {file = "tokenizers-0.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d924204a3dbe50b75630bd16f821ebda6a5f729928df30f582fb5aade90c818a"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4f3fefdc0446b1a1e6d81cd4c07088ac015665d2e812f6dbba4a06267d1a2c95"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9620b78e0b2d52ef07b0d428323fb34e8ea1219c5eac98c2596311f20f1f9266"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04ce49e82d100594715ac1b2ce87d1a36e61891a91de774755f743babcd0dd52"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5c2ff13d157afe413bf7e25789879dd463e5a4abfb529a2d8f8473d8042e28f"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3174c76efd9d08f836bfccaca7cfec3f4d1c0a4cf3acbc7236ad577cc423c840"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c9d5b6c0e7a1e979bec10ff960fae925e947aab95619a6fdb4c1d8ff3708ce3"}, + {file = "tokenizers-0.19.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a179856d1caee06577220ebcfa332af046d576fb73454b8f4d4b0ba8324423ea"}, + {file = "tokenizers-0.19.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:952b80dac1a6492170f8c2429bd11fcaa14377e097d12a1dbe0ef2fb2241e16c"}, + {file = "tokenizers-0.19.1-cp312-none-win32.whl", hash = "sha256:01d62812454c188306755c94755465505836fd616f75067abcae529c35edeb57"}, + {file = "tokenizers-0.19.1-cp312-none-win_amd64.whl", hash = "sha256:b70bfbe3a82d3e3fb2a5e9b22a39f8d1740c96c68b6ace0086b39074f08ab89a"}, + {file = "tokenizers-0.19.1-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:bb9dfe7dae85bc6119d705a76dc068c062b8b575abe3595e3c6276480e67e3f1"}, + {file = "tokenizers-0.19.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:1f0360cbea28ea99944ac089c00de7b2e3e1c58f479fb8613b6d8d511ce98267"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:71e3ec71f0e78780851fef28c2a9babe20270404c921b756d7c532d280349214"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b82931fa619dbad979c0ee8e54dd5278acc418209cc897e42fac041f5366d626"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e8ff5b90eabdcdaa19af697885f70fe0b714ce16709cf43d4952f1f85299e73a"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e742d76ad84acbdb1a8e4694f915fe59ff6edc381c97d6dfdd054954e3478ad4"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d8c5d59d7b59885eab559d5bc082b2985555a54cda04dda4c65528d90ad252ad"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b2da5c32ed869bebd990c9420df49813709e953674c0722ff471a116d97b22d"}, + {file = "tokenizers-0.19.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:638e43936cc8b2cbb9f9d8dde0fe5e7e30766a3318d2342999ae27f68fdc9bd6"}, + {file = "tokenizers-0.19.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:78e769eb3b2c79687d9cb0f89ef77223e8e279b75c0a968e637ca7043a84463f"}, + {file = "tokenizers-0.19.1-cp37-none-win32.whl", hash = "sha256:72791f9bb1ca78e3ae525d4782e85272c63faaef9940d92142aa3eb79f3407a3"}, + {file = "tokenizers-0.19.1-cp37-none-win_amd64.whl", hash = "sha256:f3bbb7a0c5fcb692950b041ae11067ac54826204318922da754f908d95619fbc"}, + {file = "tokenizers-0.19.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:07f9295349bbbcedae8cefdbcfa7f686aa420be8aca5d4f7d1ae6016c128c0c5"}, + {file = "tokenizers-0.19.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:10a707cc6c4b6b183ec5dbfc5c34f3064e18cf62b4a938cb41699e33a99e03c1"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6309271f57b397aa0aff0cbbe632ca9d70430839ca3178bf0f06f825924eca22"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ad23d37d68cf00d54af184586d79b84075ada495e7c5c0f601f051b162112dc"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:427c4f0f3df9109314d4f75b8d1f65d9477033e67ffaec4bca53293d3aca286d"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e83a31c9cf181a0a3ef0abad2b5f6b43399faf5da7e696196ddd110d332519ee"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c27b99889bd58b7e301468c0838c5ed75e60c66df0d4db80c08f43462f82e0d3"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bac0b0eb952412b0b196ca7a40e7dce4ed6f6926489313414010f2e6b9ec2adf"}, + {file = "tokenizers-0.19.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8a6298bde623725ca31c9035a04bf2ef63208d266acd2bed8c2cb7d2b7d53ce6"}, + {file = "tokenizers-0.19.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:08a44864e42fa6d7d76d7be4bec62c9982f6f6248b4aa42f7302aa01e0abfd26"}, + {file = "tokenizers-0.19.1-cp38-none-win32.whl", hash = "sha256:1de5bc8652252d9357a666e609cb1453d4f8e160eb1fb2830ee369dd658e8975"}, + {file = "tokenizers-0.19.1-cp38-none-win_amd64.whl", hash = "sha256:0bcce02bf1ad9882345b34d5bd25ed4949a480cf0e656bbd468f4d8986f7a3f1"}, + {file = "tokenizers-0.19.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:0b9394bd204842a2a1fd37fe29935353742be4a3460b6ccbaefa93f58a8df43d"}, + {file = "tokenizers-0.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4692ab92f91b87769d950ca14dbb61f8a9ef36a62f94bad6c82cc84a51f76f6a"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6258c2ef6f06259f70a682491c78561d492e885adeaf9f64f5389f78aa49a051"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c85cf76561fbd01e0d9ea2d1cbe711a65400092bc52b5242b16cfd22e51f0c58"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:670b802d4d82bbbb832ddb0d41df7015b3e549714c0e77f9bed3e74d42400fbe"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:85aa3ab4b03d5e99fdd31660872249df5e855334b6c333e0bc13032ff4469c4a"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cbf001afbbed111a79ca47d75941e9e5361297a87d186cbfc11ed45e30b5daba"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4c89aa46c269e4e70c4d4f9d6bc644fcc39bb409cb2a81227923404dd6f5227"}, + {file = "tokenizers-0.19.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:39c1ec76ea1027438fafe16ecb0fb84795e62e9d643444c1090179e63808c69d"}, + {file = "tokenizers-0.19.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c2a0d47a89b48d7daa241e004e71fb5a50533718897a4cd6235cb846d511a478"}, + {file = "tokenizers-0.19.1-cp39-none-win32.whl", hash = "sha256:61b7fe8886f2e104d4caf9218b157b106207e0f2a4905c9c7ac98890688aabeb"}, + {file = "tokenizers-0.19.1-cp39-none-win_amd64.whl", hash = "sha256:f97660f6c43efd3e0bfd3f2e3e5615bf215680bad6ee3d469df6454b8c6e8256"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3b11853f17b54c2fe47742c56d8a33bf49ce31caf531e87ac0d7d13d327c9334"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d26194ef6c13302f446d39972aaa36a1dda6450bc8949f5eb4c27f51191375bd"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e8d1ed93beda54bbd6131a2cb363a576eac746d5c26ba5b7556bc6f964425594"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca407133536f19bdec44b3da117ef0d12e43f6d4b56ac4c765f37eca501c7bda"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce05fde79d2bc2e46ac08aacbc142bead21614d937aac950be88dc79f9db9022"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:35583cd46d16f07c054efd18b5d46af4a2f070a2dd0a47914e66f3ff5efb2b1e"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:43350270bfc16b06ad3f6f07eab21f089adb835544417afda0f83256a8bf8b75"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b4399b59d1af5645bcee2072a463318114c39b8547437a7c2d6a186a1b5a0e2d"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6852c5b2a853b8b0ddc5993cd4f33bfffdca4fcc5d52f89dd4b8eada99379285"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcd266ae85c3d39df2f7e7d0e07f6c41a55e9a3123bb11f854412952deacd828"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecb2651956eea2aa0a2d099434134b1b68f1c31f9a5084d6d53f08ed43d45ff2"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:b279ab506ec4445166ac476fb4d3cc383accde1ea152998509a94d82547c8e2a"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:89183e55fb86e61d848ff83753f64cded119f5d6e1f553d14ffee3700d0a4a49"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2edbc75744235eea94d595a8b70fe279dd42f3296f76d5a86dde1d46e35f574"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:0e64bfde9a723274e9a71630c3e9494ed7b4c0f76a1faacf7fe294cd26f7ae7c"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0b5ca92bfa717759c052e345770792d02d1f43b06f9e790ca0a1db62838816f3"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f8a20266e695ec9d7a946a019c1d5ca4eddb6613d4f466888eee04f16eedb85"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63c38f45d8f2a2ec0f3a20073cccb335b9f99f73b3c69483cd52ebc75369d8a1"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:dd26e3afe8a7b61422df3176e06664503d3f5973b94f45d5c45987e1cb711876"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:eddd5783a4a6309ce23432353cdb36220e25cbb779bfa9122320666508b44b88"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:56ae39d4036b753994476a1b935584071093b55c7a72e3b8288e68c313ca26e7"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f9939ca7e58c2758c01b40324a59c034ce0cebad18e0d4563a9b1beab3018243"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6c330c0eb815d212893c67a032e9dc1b38a803eccb32f3e8172c19cc69fbb439"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec11802450a2487cdf0e634b750a04cbdc1c4d066b97d94ce7dd2cb51ebb325b"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2b718f316b596f36e1dae097a7d5b91fc5b85e90bf08b01ff139bd8953b25af"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:ed69af290c2b65169f0ba9034d1dc39a5db9459b32f1dd8b5f3f32a3fcf06eab"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f8a9c828277133af13f3859d1b6bf1c3cb6e9e1637df0e45312e6b7c2e622b1f"}, + {file = "tokenizers-0.19.1.tar.gz", hash = "sha256:ee59e6680ed0fdbe6b724cf38bd70400a0c1dd623b07ac729087270caeac88e3"}, +] + +[package.dependencies] +huggingface-hub = ">=0.16.4,<1.0" [package.extras] dev = ["tokenizers[testing]"] -docs = ["setuptools_rust", "sphinx", "sphinx_rtd_theme"] -testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests"] +docs = ["setuptools-rust", "sphinx", "sphinx-rtd-theme"] +testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests", "ruff"] [[package]] name = "tqdm" -version = "4.66.1" +version = "4.66.4" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.7" files = [ - {file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"}, - {file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"}, + {file = "tqdm-4.66.4-py3-none-any.whl", hash = "sha256:b75ca56b413b030bc3f00af51fd2c1a1a5eac6a0c1cca83cbb37a5c52abce644"}, + {file = "tqdm-4.66.4.tar.gz", hash = "sha256:e4d936c9de8727928f3be6079590e97d9abfe8d39a590be678eb5919ffc186bb"}, ] [package.dependencies] @@ -2205,28 +3263,62 @@ telegram = ["requests"] [[package]] name = "traitlets" -version = "5.14.1" +version = "5.14.3" description = "Traitlets Python configuration system" optional = false python-versions = ">=3.8" files = [ - {file = "traitlets-5.14.1-py3-none-any.whl", hash = "sha256:2e5a030e6eff91737c643231bfcf04a65b0132078dad75e4936700b213652e74"}, - {file = "traitlets-5.14.1.tar.gz", hash = "sha256:8585105b371a04b8316a43d5ce29c098575c2e477850b62b848b964f1444527e"}, + {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}, + {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"}, ] [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"] + +[[package]] +name = "twilio" +version = "9.1.0" +description = "Twilio API client and TwiML generator" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "twilio-9.1.0-py2.py3-none-any.whl", hash = "sha256:eb4687a9f81dc3118e8981c5a46d9f8184baee135c79afed47c714c759c31bbc"}, + {file = "twilio-9.1.0.tar.gz", hash = "sha256:ab2eb19c779855bf02cdca8a7e02ebaa64feee47da7b591ac9088ec07a6962e2"}, +] + +[package.dependencies] +aiohttp = ">=3.8.4" +aiohttp-retry = ">=2.8.3" +PyJWT = ">=2.0.0,<3.0.0" +requests = ">=2.0.0" + +[[package]] +name = "typer" +version = "0.12.3" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +optional = false +python-versions = ">=3.7" +files = [ + {file = "typer-0.12.3-py3-none-any.whl", hash = "sha256:070d7ca53f785acbccba8e7d28b08dcd88f79f1fbda035ade0aecec71ca5c914"}, + {file = "typer-0.12.3.tar.gz", hash = "sha256:49e73131481d804288ef62598d97a1ceef3058905aa536a1134f90891ba35482"}, +] + +[package.dependencies] +click = ">=8.0.0" +rich = ">=10.11.0" +shellingham = ">=1.3.0" +typing-extensions = ">=3.7.4.3" [[package]] name = "typing-extensions" -version = "4.9.0" +version = "4.12.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, - {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, + {file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"}, + {file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"}, ] [[package]] @@ -2244,80 +3336,367 @@ files = [ mypy-extensions = ">=0.3.0" typing-extensions = ">=3.7.4" +[[package]] +name = "ujson" +version = "5.10.0" +description = "Ultra fast JSON encoder and decoder for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "ujson-5.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2601aa9ecdbee1118a1c2065323bda35e2c5a2cf0797ef4522d485f9d3ef65bd"}, + {file = "ujson-5.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:348898dd702fc1c4f1051bc3aacbf894caa0927fe2c53e68679c073375f732cf"}, + {file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22cffecf73391e8abd65ef5f4e4dd523162a3399d5e84faa6aebbf9583df86d6"}, + {file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26b0e2d2366543c1bb4fbd457446f00b0187a2bddf93148ac2da07a53fe51569"}, + {file = "ujson-5.10.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:caf270c6dba1be7a41125cd1e4fc7ba384bf564650beef0df2dd21a00b7f5770"}, + {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a245d59f2ffe750446292b0094244df163c3dc96b3ce152a2c837a44e7cda9d1"}, + {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:94a87f6e151c5f483d7d54ceef83b45d3a9cca7a9cb453dbdbb3f5a6f64033f5"}, + {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:29b443c4c0a113bcbb792c88bea67b675c7ca3ca80c3474784e08bba01c18d51"}, + {file = "ujson-5.10.0-cp310-cp310-win32.whl", hash = "sha256:c18610b9ccd2874950faf474692deee4223a994251bc0a083c114671b64e6518"}, + {file = "ujson-5.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:924f7318c31874d6bb44d9ee1900167ca32aa9b69389b98ecbde34c1698a250f"}, + {file = "ujson-5.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00"}, + {file = "ujson-5.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126"}, + {file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8"}, + {file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b"}, + {file = "ujson-5.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9"}, + {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f"}, + {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4"}, + {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1"}, + {file = "ujson-5.10.0-cp311-cp311-win32.whl", hash = "sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f"}, + {file = "ujson-5.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720"}, + {file = "ujson-5.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5"}, + {file = "ujson-5.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e"}, + {file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043"}, + {file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1"}, + {file = "ujson-5.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3"}, + {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21"}, + {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2"}, + {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e"}, + {file = "ujson-5.10.0-cp312-cp312-win32.whl", hash = "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e"}, + {file = "ujson-5.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc"}, + {file = "ujson-5.10.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287"}, + {file = "ujson-5.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e"}, + {file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557"}, + {file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988"}, + {file = "ujson-5.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816"}, + {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20"}, + {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0"}, + {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f"}, + {file = "ujson-5.10.0-cp313-cp313-win32.whl", hash = "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165"}, + {file = "ujson-5.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539"}, + {file = "ujson-5.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a984a3131da7f07563057db1c3020b1350a3e27a8ec46ccbfbf21e5928a43050"}, + {file = "ujson-5.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73814cd1b9db6fc3270e9d8fe3b19f9f89e78ee9d71e8bd6c9a626aeaeaf16bd"}, + {file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61e1591ed9376e5eddda202ec229eddc56c612b61ac6ad07f96b91460bb6c2fb"}, + {file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2c75269f8205b2690db4572a4a36fe47cd1338e4368bc73a7a0e48789e2e35a"}, + {file = "ujson-5.10.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7223f41e5bf1f919cd8d073e35b229295aa8e0f7b5de07ed1c8fddac63a6bc5d"}, + {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d4dc2fd6b3067c0782e7002ac3b38cf48608ee6366ff176bbd02cf969c9c20fe"}, + {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:232cc85f8ee3c454c115455195a205074a56ff42608fd6b942aa4c378ac14dd7"}, + {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cc6139531f13148055d691e442e4bc6601f6dba1e6d521b1585d4788ab0bfad4"}, + {file = "ujson-5.10.0-cp38-cp38-win32.whl", hash = "sha256:e7ce306a42b6b93ca47ac4a3b96683ca554f6d35dd8adc5acfcd55096c8dfcb8"}, + {file = "ujson-5.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:e82d4bb2138ab05e18f089a83b6564fee28048771eb63cdecf4b9b549de8a2cc"}, + {file = "ujson-5.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dfef2814c6b3291c3c5f10065f745a1307d86019dbd7ea50e83504950136ed5b"}, + {file = "ujson-5.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4734ee0745d5928d0ba3a213647f1c4a74a2a28edc6d27b2d6d5bd9fa4319e27"}, + {file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d47ebb01bd865fdea43da56254a3930a413f0c5590372a1241514abae8aa7c76"}, + {file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dee5e97c2496874acbf1d3e37b521dd1f307349ed955e62d1d2f05382bc36dd5"}, + {file = "ujson-5.10.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7490655a2272a2d0b072ef16b0b58ee462f4973a8f6bbe64917ce5e0a256f9c0"}, + {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba17799fcddaddf5c1f75a4ba3fd6441f6a4f1e9173f8a786b42450851bd74f1"}, + {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2aff2985cef314f21d0fecc56027505804bc78802c0121343874741650a4d3d1"}, + {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ad88ac75c432674d05b61184178635d44901eb749786c8eb08c102330e6e8996"}, + {file = "ujson-5.10.0-cp39-cp39-win32.whl", hash = "sha256:2544912a71da4ff8c4f7ab5606f947d7299971bdd25a45e008e467ca638d13c9"}, + {file = "ujson-5.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:3ff201d62b1b177a46f113bb43ad300b424b7847f9c5d38b1b4ad8f75d4a282a"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5b6fee72fa77dc172a28f21693f64d93166534c263adb3f96c413ccc85ef6e64"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:61d0af13a9af01d9f26d2331ce49bb5ac1fb9c814964018ac8df605b5422dcb3"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecb24f0bdd899d368b715c9e6664166cf694d1e57be73f17759573a6986dd95a"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbd8fd427f57a03cff3ad6574b5e299131585d9727c8c366da4624a9069ed746"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beeaf1c48e32f07d8820c705ff8e645f8afa690cca1544adba4ebfa067efdc88"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:baed37ea46d756aca2955e99525cc02d9181de67f25515c468856c38d52b5f3b"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7663960f08cd5a2bb152f5ee3992e1af7690a64c0e26d31ba7b3ff5b2ee66337"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:d8640fb4072d36b08e95a3a380ba65779d356b2fee8696afeb7794cf0902d0a1"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78778a3aa7aafb11e7ddca4e29f46bc5139131037ad628cc10936764282d6753"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0111b27f2d5c820e7f2dbad7d48e3338c824e7ac4d2a12da3dc6061cc39c8e6"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:c66962ca7565605b355a9ed478292da628b8f18c0f2793021ca4425abf8b01e5"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ba43cc34cce49cf2d4bc76401a754a81202d8aa926d0e2b79f0ee258cb15d3a4"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ac56eb983edce27e7f51d05bc8dd820586c6e6be1c5216a6809b0c668bb312b8"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44bd4b23a0e723bf8b10628288c2c7c335161d6840013d4d5de20e48551773b"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c10f4654e5326ec14a46bcdeb2b685d4ada6911050aa8baaf3501e57024b804"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0de4971a89a762398006e844ae394bd46991f7c385d7a6a3b93ba229e6dac17e"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e1402f0564a97d2a52310ae10a64d25bcef94f8dd643fcf5d310219d915484f7"}, + {file = "ujson-5.10.0.tar.gz", hash = "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1"}, +] + [[package]] name = "urllib3" -version = "2.1.0" +version = "2.2.1" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"}, - {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"}, + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, ] [package.extras] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] [[package]] name = "uvicorn" -version = "0.21.1" +version = "0.30.0" description = "The lightning-fast ASGI server." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "uvicorn-0.21.1-py3-none-any.whl", hash = "sha256:e47cac98a6da10cd41e6fd036d472c6f58ede6c5dbee3dbee3ef7a100ed97742"}, - {file = "uvicorn-0.21.1.tar.gz", hash = "sha256:0fac9cb342ba099e0d582966005f3fdba5b0290579fed4a6266dc702ca7bb032"}, + {file = "uvicorn-0.30.0-py3-none-any.whl", hash = "sha256:78fa0b5f56abb8562024a59041caeb555c86e48d0efdd23c3fe7de7a4075bdab"}, + {file = "uvicorn-0.30.0.tar.gz", hash = "sha256:f678dec4fa3a39706bbf49b9ec5fc40049d42418716cea52b53f07828a60aa37"}, ] [package.dependencies] click = ">=7.0" +colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""} h11 = ">=0.8" +httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""} +python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} +pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} +uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\" and extra == \"standard\""} +watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} +websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""} [package.extras] standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] +[[package]] +name = "uvloop" +version = "0.19.0" +description = "Fast implementation of asyncio event loop on top of libuv" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e"}, + {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428"}, + {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8"}, + {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849"}, + {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957"}, + {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd"}, + {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef"}, + {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2"}, + {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1"}, + {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24"}, + {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533"}, + {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12"}, + {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650"}, + {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec"}, + {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc"}, + {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6"}, + {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593"}, + {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3"}, + {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:78ab247f0b5671cc887c31d33f9b3abfb88d2614b84e4303f1a63b46c046c8bd"}, + {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:472d61143059c84947aa8bb74eabbace30d577a03a1805b77933d6bd13ddebbd"}, + {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45bf4c24c19fb8a50902ae37c5de50da81de4922af65baf760f7c0c42e1088be"}, + {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271718e26b3e17906b28b67314c45d19106112067205119dddbd834c2b7ce797"}, + {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:34175c9fd2a4bc3adc1380e1261f60306344e3407c20a4d684fd5f3be010fa3d"}, + {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e27f100e1ff17f6feeb1f33968bc185bf8ce41ca557deee9d9bbbffeb72030b7"}, + {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13dfdf492af0aa0a0edf66807d2b465607d11c4fa48f4a1fd41cbea5b18e8e8b"}, + {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e3d4e85ac060e2342ff85e90d0c04157acb210b9ce508e784a944f852a40e67"}, + {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ca4956c9ab567d87d59d49fa3704cf29e37109ad348f2d5223c9bf761a332e7"}, + {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f467a5fd23b4fc43ed86342641f3936a68ded707f4627622fa3f82a120e18256"}, + {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:492e2c32c2af3f971473bc22f086513cedfc66a130756145a931a90c3958cb17"}, + {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2df95fca285a9f5bfe730e51945ffe2fa71ccbfdde3b0da5772b4ee4f2e770d5"}, + {file = "uvloop-0.19.0.tar.gz", hash = "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd"}, +] + +[package.extras] +docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] +test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"] + [[package]] name = "vocode" version = "0.1.111" description = "The all-in-one voice SDK" optional = false -python-versions = ">=3.8.1,<3.12" +python-versions = ">=3.9,<3.12" +files = [] +develop = true + +[package.dependencies] +aiohttp = "^3.9.5" +anthropic = {version = "^0.28.0", optional = true} +azure-cognitiveservices-speech = {version = "^1.37.0", optional = true} +elevenlabs = {version = "^1.2.2", optional = true} +fastapi = "^0.111.0" +google-cloud-speech = {version = "^2.26.0", optional = true} +google-cloud-texttospeech = {version = "^2.16.3", optional = true} +janus = "^1.0.0" +jinja2 = "^3.1.4" +jsonschema = "^4.22.0" +langchain = {version = "^0.2.1", optional = true} +langchain-community = {version = "^0.2.1", optional = true} +loguru = "^0.7.2" +miniaudio = {version = "^1.59", optional = true} +nltk = {version = "^3.8.1", optional = true} +openai = {version = "^1.30.5", optional = true} +opentelemetry-sdk = "^1.24.0" +phonenumbers = "^8.13.37" +pvkoala = {version = "^2.0.1", optional = true} +pydantic = "^2.7.2" +pydub = {version = "^0.25.1", optional = true} +pyht = {version = "^0.0.28", optional = true} +redis = {version = "^5.0.4", optional = true} +requests = "^2.32.3" +sentry-sdk = {version = "^2.3.1", extras = ["fastapi"], optional = true} +sounddevice = "^0.4.7" +tiktoken = {version = "0.7.0", optional = true} +twilio = {version = "^9.1.0", optional = true} +uvicorn = "^0.30.0" +vonage = {version = "^3.14.0", optional = true} +websockets = "^12.0" + +[package.extras] +agents = ["anthropic (>=0.28.0,<0.29.0)", "openai (>=1.30.5,<2.0.0)", "tiktoken (==0.7.0)"] +all = ["anthropic (>=0.28.0,<0.29.0)", "azure-cognitiveservices-speech (>=1.37.0,<2.0.0)", "elevenlabs (>=1.2.2,<2.0.0)", "google-cloud-speech (>=2.26.0,<3.0.0)", "google-cloud-texttospeech (>=2.16.3,<3.0.0)", "langchain (>=0.2.1,<0.3.0)", "langchain-community (>=0.2.1,<0.3.0)", "miniaudio (>=1.59,<2.0)", "nltk (>=3.8.1,<4.0.0)", "openai (>=1.30.5,<2.0.0)", "pvkoala (>=2.0.1,<3.0.0)", "pydub (>=0.25.1,<0.26.0)", "pyht (>=0.0.28,<0.0.29)", "redis (>=5.0.4,<6.0.0)", "sentry-sdk[fastapi] (>=2.3.1,<3.0.0)", "tiktoken (==0.7.0)", "twilio (>=9.1.0,<10.0.0)", "vonage (>=3.14.0,<4.0.0)"] +misc = ["langchain (>=0.2.1,<0.3.0)", "langchain-community (>=0.2.1,<0.3.0)", "sentry-sdk[fastapi] (>=2.3.1,<3.0.0)"] +synthesizers = ["azure-cognitiveservices-speech (>=1.37.0,<2.0.0)", "elevenlabs (>=1.2.2,<2.0.0)", "google-cloud-texttospeech (>=2.16.3,<3.0.0)", "miniaudio (>=1.59,<2.0)", "nltk (>=3.8.1,<4.0.0)", "pvkoala (>=2.0.1,<3.0.0)", "pydub (>=0.25.1,<0.26.0)", "pyht (>=0.0.28,<0.0.29)"] +telephony = ["redis (>=5.0.4,<6.0.0)", "twilio (>=9.1.0,<10.0.0)", "vonage (>=3.14.0,<4.0.0)"] +transcribers = ["google-cloud-speech (>=2.26.0,<3.0.0)"] + +[package.source] +type = "directory" +url = "../.." + +[[package]] +name = "vonage" +version = "3.14.0" +description = "Vonage Server SDK for Python" +optional = false +python-versions = ">=3.8" files = [ - {file = "vocode-0.1.111-py3-none-any.whl", hash = "sha256:52b1c22188dbb1526eea490ad86fc11cc50df6442f4dd908939948b13fa66953"}, - {file = "vocode-0.1.111.tar.gz", hash = "sha256:9eb1e6d25c55f2fd7b0e1ee712de61a5f2c2cb8b70b058ce5d0eb7eb86bf8367"}, + {file = "vonage-3.14.0-py2.py3-none-any.whl", hash = "sha256:f8d28b8fcd157c0610d84b880779aadd3ab3768abfb18ef863e08669de163ccf"}, + {file = "vonage-3.14.0.tar.gz", hash = "sha256:ea001e9616abb19670c4250a1ac46288207030ebc9d9ecbcf5fcffef61fa5850"}, ] [package.dependencies] -aiohttp = ">=3.8.4,<4.0.0" -anthropic = ">=0.2.9,<0.3.0" -azure-cognitiveservices-speech = ">=1.27.0,<2.0.0" -fastapi = ">=0.100.1,<0.101.0" -janus = ">=1.0.0,<2.0.0" -jinja2 = ">=3.1.2,<4.0.0" -langchain = ">=0.0.198,<0.0.199" -miniaudio = ">=1.59,<2.0" -nltk = ">=3.8.1,<4.0.0" -openai = ">=0.27.8,<0.28.0" -opentelemetry-sdk = ">=1.17.0,<2.0.0" -pydub = ">=0.25.1,<0.26.0" -python-multipart = ">=0.0.6,<0.0.7" -requests = ">=2.28.2,<3.0.0" -scipy = ">=1.10.1,<2.0.0" -six = ">=1.16.0,<2.0.0" -sounddevice = ">=0.4.6,<0.5.0" -speechrecognition = ">=3.10.0,<4.0.0" -uvicorn = ">=0.21.1,<0.22.0" -websockets = ">=11.0.2,<12.0.0" +Deprecated = "*" +pydantic = ">=2.5.2" +pytz = ">=2018.5" +requests = ">=2.4.2" +vonage-jwt = ">=1.1.0" -[package.extras] -actions = ["nylas (>=5.14.0,<6.0.0)"] -agents = ["google-cloud-aiplatform (>=1.26.0,<2.0.0)"] -all = ["elevenlabs (>=0.2.6,<0.3.0)", "google-cloud-aiplatform (>=1.26.0,<2.0.0)", "google-cloud-speech (>=2.19.0,<3.0.0)", "google-cloud-texttospeech (>=2.14.1,<3.0.0)", "gtts (>=2.3.1,<3.0.0)", "nylas (>=5.14.0,<6.0.0)", "redis (>=4.5.4,<5.0.0)", "twilio (>=8.1.0,<9.0.0)", "vonage (>=3.5.1,<4.0.0)"] -synthesizers = ["elevenlabs (>=0.2.6,<0.3.0)", "google-cloud-texttospeech (>=2.14.1,<3.0.0)", "gtts (>=2.3.1,<3.0.0)"] -telephony = ["redis (>=4.5.4,<5.0.0)", "twilio (>=8.1.0,<9.0.0)", "vonage (>=3.5.1,<4.0.0)"] -transcribers = ["google-cloud-speech (>=2.19.0,<3.0.0)"] +[[package]] +name = "vonage-jwt" +version = "1.1.1" +description = "Tooling for working with JWTs for Vonage APIs in Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "vonage_jwt-1.1.1-py3-none-any.whl", hash = "sha256:4b751571e013deeab9f13b68f9e1478d8aa7f0a91f0cb7f6d793fa7b859859df"}, + {file = "vonage_jwt-1.1.1.tar.gz", hash = "sha256:15f4b1cd8fa5909390a4074a909053ae823df0557b1edb9b675d0a013295dc10"}, +] + +[package.dependencies] +pyjwt = {version = ">=1.6.4", extras = ["crypto"]} +vonage-utils = ">=1.1.2" + +[[package]] +name = "vonage-utils" +version = "1.1.2" +description = "Utils package containing objects for use with Vonage APIs" +optional = false +python-versions = ">=3.8" +files = [ + {file = "vonage_utils-1.1.2-py3-none-any.whl", hash = "sha256:a815a8be8f5fdba558d090d0f81b469a2eb0ded4cccbfe4e27dc9276e84c4b7e"}, + {file = "vonage_utils-1.1.2.tar.gz", hash = "sha256:a86c1eafe62e6f82d18dda6fd4dc78c898dea81888b83f18ea75105365307daf"}, +] + +[package.dependencies] +pydantic = ">=2.7.1" +typing-extensions = ">=4.9.0" + +[[package]] +name = "watchfiles" +version = "0.22.0" +description = "Simple, modern and high performance file watching and code reload in python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "watchfiles-0.22.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:da1e0a8caebf17976e2ffd00fa15f258e14749db5e014660f53114b676e68538"}, + {file = "watchfiles-0.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61af9efa0733dc4ca462347becb82e8ef4945aba5135b1638bfc20fad64d4f0e"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d9188979a58a096b6f8090e816ccc3f255f137a009dd4bbec628e27696d67c1"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2bdadf6b90c099ca079d468f976fd50062905d61fae183f769637cb0f68ba59a"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:067dea90c43bf837d41e72e546196e674f68c23702d3ef80e4e816937b0a3ffd"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbf8a20266136507abf88b0df2328e6a9a7c7309e8daff124dda3803306a9fdb"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1235c11510ea557fe21be5d0e354bae2c655a8ee6519c94617fe63e05bca4171"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2444dc7cb9d8cc5ab88ebe792a8d75709d96eeef47f4c8fccb6df7c7bc5be71"}, + {file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c5af2347d17ab0bd59366db8752d9e037982e259cacb2ba06f2c41c08af02c39"}, + {file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9624a68b96c878c10437199d9a8b7d7e542feddda8d5ecff58fdc8e67b460848"}, + {file = "watchfiles-0.22.0-cp310-none-win32.whl", hash = "sha256:4b9f2a128a32a2c273d63eb1fdbf49ad64852fc38d15b34eaa3f7ca2f0d2b797"}, + {file = "watchfiles-0.22.0-cp310-none-win_amd64.whl", hash = "sha256:2627a91e8110b8de2406d8b2474427c86f5a62bf7d9ab3654f541f319ef22bcb"}, + {file = "watchfiles-0.22.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8c39987a1397a877217be1ac0fb1d8b9f662c6077b90ff3de2c05f235e6a8f96"}, + {file = "watchfiles-0.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a927b3034d0672f62fb2ef7ea3c9fc76d063c4b15ea852d1db2dc75fe2c09696"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052d668a167e9fc345c24203b104c313c86654dd6c0feb4b8a6dfc2462239249"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e45fb0d70dda1623a7045bd00c9e036e6f1f6a85e4ef2c8ae602b1dfadf7550"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c49b76a78c156979759d759339fb62eb0549515acfe4fd18bb151cc07366629c"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4a65474fd2b4c63e2c18ac67a0c6c66b82f4e73e2e4d940f837ed3d2fd9d4da"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc0cba54f47c660d9fa3218158b8963c517ed23bd9f45fe463f08262a4adae1"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ebe84a035993bb7668f58a0ebf998174fb723a39e4ef9fce95baabb42b787f"}, + {file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e0f0a874231e2839abbf473256efffe577d6ee2e3bfa5b540479e892e47c172d"}, + {file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:213792c2cd3150b903e6e7884d40660e0bcec4465e00563a5fc03f30ea9c166c"}, + {file = "watchfiles-0.22.0-cp311-none-win32.whl", hash = "sha256:b44b70850f0073b5fcc0b31ede8b4e736860d70e2dbf55701e05d3227a154a67"}, + {file = "watchfiles-0.22.0-cp311-none-win_amd64.whl", hash = "sha256:00f39592cdd124b4ec5ed0b1edfae091567c72c7da1487ae645426d1b0ffcad1"}, + {file = "watchfiles-0.22.0-cp311-none-win_arm64.whl", hash = "sha256:3218a6f908f6a276941422b035b511b6d0d8328edd89a53ae8c65be139073f84"}, + {file = "watchfiles-0.22.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:c7b978c384e29d6c7372209cbf421d82286a807bbcdeb315427687f8371c340a"}, + {file = "watchfiles-0.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd4c06100bce70a20c4b81e599e5886cf504c9532951df65ad1133e508bf20be"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:425440e55cd735386ec7925f64d5dde392e69979d4c8459f6bb4e920210407f2"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68fe0c4d22332d7ce53ad094622b27e67440dacefbaedd29e0794d26e247280c"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a8a31bfd98f846c3c284ba694c6365620b637debdd36e46e1859c897123aa232"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc2e8fe41f3cac0660197d95216c42910c2b7e9c70d48e6d84e22f577d106fc1"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b7cc10261c2786c41d9207193a85c1db1b725cf87936df40972aab466179b6"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28585744c931576e535860eaf3f2c0ec7deb68e3b9c5a85ca566d69d36d8dd27"}, + {file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:00095dd368f73f8f1c3a7982a9801190cc88a2f3582dd395b289294f8975172b"}, + {file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:52fc9b0dbf54d43301a19b236b4a4614e610605f95e8c3f0f65c3a456ffd7d35"}, + {file = "watchfiles-0.22.0-cp312-none-win32.whl", hash = "sha256:581f0a051ba7bafd03e17127735d92f4d286af941dacf94bcf823b101366249e"}, + {file = "watchfiles-0.22.0-cp312-none-win_amd64.whl", hash = "sha256:aec83c3ba24c723eac14225194b862af176d52292d271c98820199110e31141e"}, + {file = "watchfiles-0.22.0-cp312-none-win_arm64.whl", hash = "sha256:c668228833c5619f6618699a2c12be057711b0ea6396aeaece4ded94184304ea"}, + {file = "watchfiles-0.22.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d47e9ef1a94cc7a536039e46738e17cce058ac1593b2eccdede8bf72e45f372a"}, + {file = "watchfiles-0.22.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28f393c1194b6eaadcdd8f941307fc9bbd7eb567995232c830f6aef38e8a6e88"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd64f3a4db121bc161644c9e10a9acdb836853155a108c2446db2f5ae1778c3d"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2abeb79209630da981f8ebca30a2c84b4c3516a214451bfc5f106723c5f45843"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cc382083afba7918e32d5ef12321421ef43d685b9a67cc452a6e6e18920890e"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d048ad5d25b363ba1d19f92dcf29023988524bee6f9d952130b316c5802069cb"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:103622865599f8082f03af4214eaff90e2426edff5e8522c8f9e93dc17caee13"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3e1f3cf81f1f823e7874ae563457828e940d75573c8fbf0ee66818c8b6a9099"}, + {file = "watchfiles-0.22.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8597b6f9dc410bdafc8bb362dac1cbc9b4684a8310e16b1ff5eee8725d13dcd6"}, + {file = "watchfiles-0.22.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0b04a2cbc30e110303baa6d3ddce8ca3664bc3403be0f0ad513d1843a41c97d1"}, + {file = "watchfiles-0.22.0-cp38-none-win32.whl", hash = "sha256:b610fb5e27825b570554d01cec427b6620ce9bd21ff8ab775fc3a32f28bba63e"}, + {file = "watchfiles-0.22.0-cp38-none-win_amd64.whl", hash = "sha256:fe82d13461418ca5e5a808a9e40f79c1879351fcaeddbede094028e74d836e86"}, + {file = "watchfiles-0.22.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3973145235a38f73c61474d56ad6199124e7488822f3a4fc97c72009751ae3b0"}, + {file = "watchfiles-0.22.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:280a4afbc607cdfc9571b9904b03a478fc9f08bbeec382d648181c695648202f"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a0d883351a34c01bd53cfa75cd0292e3f7e268bacf2f9e33af4ecede7e21d1d"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9165bcab15f2b6d90eedc5c20a7f8a03156b3773e5fb06a790b54ccecdb73385"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc1b9b56f051209be458b87edb6856a449ad3f803315d87b2da4c93b43a6fe72"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dc1fc25a1dedf2dd952909c8e5cb210791e5f2d9bc5e0e8ebc28dd42fed7562"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc92d2d2706d2b862ce0568b24987eba51e17e14b79a1abcd2edc39e48e743c8"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97b94e14b88409c58cdf4a8eaf0e67dfd3ece7e9ce7140ea6ff48b0407a593ec"}, + {file = "watchfiles-0.22.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96eec15e5ea7c0b6eb5bfffe990fc7c6bd833acf7e26704eb18387fb2f5fd087"}, + {file = "watchfiles-0.22.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:28324d6b28bcb8d7c1041648d7b63be07a16db5510bea923fc80b91a2a6cbed6"}, + {file = "watchfiles-0.22.0-cp39-none-win32.whl", hash = "sha256:8c3e3675e6e39dc59b8fe5c914a19d30029e36e9f99468dddffd432d8a7b1c93"}, + {file = "watchfiles-0.22.0-cp39-none-win_amd64.whl", hash = "sha256:25c817ff2a86bc3de3ed2df1703e3d24ce03479b27bb4527c57e722f8554d971"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b810a2c7878cbdecca12feae2c2ae8af59bea016a78bc353c184fa1e09f76b68"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7e1f9c5d1160d03b93fc4b68a0aeb82fe25563e12fbcdc8507f8434ab6f823c"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:030bc4e68d14bcad2294ff68c1ed87215fbd9a10d9dea74e7cfe8a17869785ab"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ace7d060432acde5532e26863e897ee684780337afb775107c0a90ae8dbccfd2"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5834e1f8b71476a26df97d121c0c0ed3549d869124ed2433e02491553cb468c2"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:0bc3b2f93a140df6806c8467c7f51ed5e55a931b031b5c2d7ff6132292e803d6"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fdebb655bb1ba0122402352b0a4254812717a017d2dc49372a1d47e24073795"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c8e0aa0e8cc2a43561e0184c0513e291ca891db13a269d8d47cb9841ced7c71"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2f350cbaa4bb812314af5dab0eb8d538481e2e2279472890864547f3fe2281ed"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7a74436c415843af2a769b36bf043b6ccbc0f8d784814ba3d42fc961cdb0a9dc"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00ad0bcd399503a84cc688590cdffbe7a991691314dde5b57b3ed50a41319a31"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72a44e9481afc7a5ee3291b09c419abab93b7e9c306c9ef9108cb76728ca58d2"}, + {file = "watchfiles-0.22.0.tar.gz", hash = "sha256:988e981aaab4f3955209e7e28c7794acdb690be1efa7f16f8ea5aba7ffdadacb"}, +] + +[package.dependencies] +anyio = ">=3.0.0" [[package]] name = "wcwidth" @@ -2332,83 +3711,99 @@ files = [ [[package]] name = "websockets" -version = "11.0.3" +version = "12.0" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"}, + {file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"}, + {file = "websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603"}, + {file = "websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f"}, + {file = "websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf"}, + {file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"}, + {file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"}, + {file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"}, + {file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"}, + {file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"}, + {file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"}, + {file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"}, + {file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113"}, + {file = "websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d"}, + {file = "websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f"}, + {file = "websockets-12.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438"}, + {file = "websockets-12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2"}, + {file = "websockets-12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7"}, + {file = "websockets-12.0-cp38-cp38-win32.whl", hash = "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62"}, + {file = "websockets-12.0-cp38-cp38-win_amd64.whl", hash = "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892"}, + {file = "websockets-12.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d"}, + {file = "websockets-12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28"}, + {file = "websockets-12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9"}, + {file = "websockets-12.0-cp39-cp39-win32.whl", hash = "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6"}, + {file = "websockets-12.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8"}, + {file = "websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b"}, + {file = "websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30"}, + {file = "websockets-12.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2"}, + {file = "websockets-12.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468"}, + {file = "websockets-12.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611"}, + {file = "websockets-12.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370"}, + {file = "websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e"}, + {file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"}, +] + +[[package]] +name = "win32-setctime" +version = "1.1.0" +description = "A small Python utility to set file creation time on Windows" +optional = false +python-versions = ">=3.5" files = [ - {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3ccc8a0c387629aec40f2fc9fdcb4b9d5431954f934da3eaf16cdc94f67dbfac"}, - {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d67ac60a307f760c6e65dad586f556dde58e683fab03323221a4e530ead6f74d"}, - {file = "websockets-11.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84d27a4832cc1a0ee07cdcf2b0629a8a72db73f4cf6de6f0904f6661227f256f"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffd7dcaf744f25f82190856bc26ed81721508fc5cbf2a330751e135ff1283564"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7622a89d696fc87af8e8d280d9b421db5133ef5b29d3f7a1ce9f1a7bf7fcfa11"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bceab846bac555aff6427d060f2fcfff71042dba6f5fca7dc4f75cac815e57ca"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:54c6e5b3d3a8936a4ab6870d46bdd6ec500ad62bde9e44462c32d18f1e9a8e54"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:41f696ba95cd92dc047e46b41b26dd24518384749ed0d99bea0a941ca87404c4"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:86d2a77fd490ae3ff6fae1c6ceaecad063d3cc2320b44377efdde79880e11526"}, - {file = "websockets-11.0.3-cp310-cp310-win32.whl", hash = "sha256:2d903ad4419f5b472de90cd2d40384573b25da71e33519a67797de17ef849b69"}, - {file = "websockets-11.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:1d2256283fa4b7f4c7d7d3e84dc2ece74d341bce57d5b9bf385df109c2a1a82f"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e848f46a58b9fcf3d06061d17be388caf70ea5b8cc3466251963c8345e13f7eb"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa5003845cdd21ac0dc6c9bf661c5beddd01116f6eb9eb3c8e272353d45b3288"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b58cbf0697721120866820b89f93659abc31c1e876bf20d0b3d03cef14faf84d"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:660e2d9068d2bedc0912af508f30bbeb505bbbf9774d98def45f68278cea20d3"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1f0524f203e3bd35149f12157438f406eff2e4fb30f71221c8a5eceb3617b6b"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:def07915168ac8f7853812cc593c71185a16216e9e4fa886358a17ed0fd9fcf6"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b30c6590146e53149f04e85a6e4fcae068df4289e31e4aee1fdf56a0dead8f97"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:619d9f06372b3a42bc29d0cd0354c9bb9fb39c2cbc1a9c5025b4538738dbffaf"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:01f5567d9cf6f502d655151645d4e8b72b453413d3819d2b6f1185abc23e82dd"}, - {file = "websockets-11.0.3-cp311-cp311-win32.whl", hash = "sha256:e1459677e5d12be8bbc7584c35b992eea142911a6236a3278b9b5ce3326f282c"}, - {file = "websockets-11.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:e7837cb169eca3b3ae94cc5787c4fed99eef74c0ab9506756eea335e0d6f3ed8"}, - {file = "websockets-11.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9f59a3c656fef341a99e3d63189852be7084c0e54b75734cde571182c087b152"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2529338a6ff0eb0b50c7be33dc3d0e456381157a31eefc561771ee431134a97f"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34fd59a4ac42dff6d4681d8843217137f6bc85ed29722f2f7222bd619d15e95b"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:332d126167ddddec94597c2365537baf9ff62dfcc9db4266f263d455f2f031cb"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6505c1b31274723ccaf5f515c1824a4ad2f0d191cec942666b3d0f3aa4cb4007"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f467ba0050b7de85016b43f5a22b46383ef004c4f672148a8abf32bc999a87f0"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9d9acd80072abcc98bd2c86c3c9cd4ac2347b5a5a0cae7ed5c0ee5675f86d9af"}, - {file = "websockets-11.0.3-cp37-cp37m-win32.whl", hash = "sha256:e590228200fcfc7e9109509e4d9125eace2042fd52b595dd22bbc34bb282307f"}, - {file = "websockets-11.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:b16fff62b45eccb9c7abb18e60e7e446998093cdcb50fed33134b9b6878836de"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fb06eea71a00a7af0ae6aefbb932fb8a7df3cb390cc217d51a9ad7343de1b8d0"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8a34e13a62a59c871064dfd8ffb150867e54291e46d4a7cf11d02c94a5275bae"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4841ed00f1026dfbced6fca7d963c4e7043aa832648671b5138008dc5a8f6d99"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a073fc9ab1c8aff37c99f11f1641e16da517770e31a37265d2755282a5d28aa"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68b977f21ce443d6d378dbd5ca38621755f2063d6fdb3335bda981d552cfff86"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a99a7a71631f0efe727c10edfba09ea6bee4166a6f9c19aafb6c0b5917d09c"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bee9fcb41db2a23bed96c6b6ead6489702c12334ea20a297aa095ce6d31370d0"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4b253869ea05a5a073ebfdcb5cb3b0266a57c3764cf6fe114e4cd90f4bfa5f5e"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1553cb82942b2a74dd9b15a018dce645d4e68674de2ca31ff13ebc2d9f283788"}, - {file = "websockets-11.0.3-cp38-cp38-win32.whl", hash = "sha256:f61bdb1df43dc9c131791fbc2355535f9024b9a04398d3bd0684fc16ab07df74"}, - {file = "websockets-11.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:03aae4edc0b1c68498f41a6772d80ac7c1e33c06c6ffa2ac1c27a07653e79d6f"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:777354ee16f02f643a4c7f2b3eff8027a33c9861edc691a2003531f5da4f6bc8"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8c82f11964f010053e13daafdc7154ce7385ecc538989a354ccc7067fd7028fd"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3580dd9c1ad0701169e4d6fc41e878ffe05e6bdcaf3c412f9d559389d0c9e016"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f1a3f10f836fab6ca6efa97bb952300b20ae56b409414ca85bff2ad241d2a61"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df41b9bc27c2c25b486bae7cf42fccdc52ff181c8c387bfd026624a491c2671b"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279e5de4671e79a9ac877427f4ac4ce93751b8823f276b681d04b2156713b9dd"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1fdf26fa8a6a592f8f9235285b8affa72748dc12e964a5518c6c5e8f916716f7"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:69269f3a0b472e91125b503d3c0b3566bda26da0a3261c49f0027eb6075086d1"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:97b52894d948d2f6ea480171a27122d77af14ced35f62e5c892ca2fae9344311"}, - {file = "websockets-11.0.3-cp39-cp39-win32.whl", hash = "sha256:c7f3cb904cce8e1be667c7e6fef4516b98d1a6a0635a58a57528d577ac18a128"}, - {file = "websockets-11.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c792ea4eabc0159535608fc5658a74d1a81020eb35195dd63214dcf07556f67e"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f2e58f2c36cc52d41f2659e4c0cbf7353e28c8c9e63e30d8c6d3494dc9fdedcf"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de36fe9c02995c7e6ae6efe2e205816f5f00c22fd1fbf343d4d18c3d5ceac2f5"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ac56b661e60edd453585f4bd68eb6a29ae25b5184fd5ba51e97652580458998"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e052b8467dd07d4943936009f46ae5ce7b908ddcac3fda581656b1b19c083d9b"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:42cc5452a54a8e46a032521d7365da775823e21bfba2895fb7b77633cce031bb"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e6316827e3e79b7b8e7d8e3b08f4e331af91a48e794d5d8b099928b6f0b85f20"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8531fdcad636d82c517b26a448dcfe62f720e1922b33c81ce695d0edb91eb931"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c114e8da9b475739dde229fd3bc6b05a6537a88a578358bc8eb29b4030fac9c9"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e063b1865974611313a3849d43f2c3f5368093691349cf3c7c8f8f75ad7cb280"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:92b2065d642bf8c0a82d59e59053dd2fdde64d4ed44efe4870fa816c1232647b"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0ee68fe502f9031f19d495dae2c268830df2760c0524cbac5d759921ba8c8e82"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcacf2c7a6c3a84e720d1bb2b543c675bf6c40e460300b628bab1b1efc7c034c"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b67c6f5e5a401fc56394f191f00f9b3811fe843ee93f4a70df3c389d1adf857d"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d5023a4b6a5b183dc838808087033ec5df77580485fc533e7dab2567851b0a4"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ed058398f55163a79bb9f06a90ef9ccc063b204bb346c4de78efc5d15abfe602"}, - {file = "websockets-11.0.3-py3-none-any.whl", hash = "sha256:6681ba9e7f8f3b19440921e99efbb40fc89f26cd71bf539e45d8c8a25c976dc6"}, - {file = "websockets-11.0.3.tar.gz", hash = "sha256:88fc51d9a26b10fc331be344f1781224a375b78488fc343620184e95a4b27016"}, + {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"}, + {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"}, ] +[package.extras] +dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] + [[package]] name = "wrapt" version = "1.16.0" @@ -2593,20 +3988,20 @@ multidict = ">=4.0" [[package]] name = "zipp" -version = "3.17.0" +version = "3.19.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, - {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, + {file = "zipp-3.19.0-py3-none-any.whl", hash = "sha256:96dc6ad62f1441bcaccef23b274ec471518daf4fbbc580341204936a5a3dddec"}, + {file = "zipp-3.19.0.tar.gz", hash = "sha256:952df858fb3164426c976d9338d3961e8e8b3758e2e059e0f754b8c4262625ee"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.12" -content-hash = "1f9bab039c4649c00109eb45a3d2e3ca5ff31cf0cdbabbed9e610c2d2aef9d35" +content-hash = "4f04aff2fd12f06ec9d2cb85b3ee1f4d34aca7ebd40858407f589fef00dab033" diff --git a/apps/client_backend/pyproject.toml b/apps/client_backend/pyproject.toml index 6863fbd16..ab7526566 100644 --- a/apps/client_backend/pyproject.toml +++ b/apps/client_backend/pyproject.toml @@ -7,9 +7,11 @@ readme = "README.md" [tool.poetry.dependencies] python = ">=3.9,<3.12" -python-dotenv = "^1.0.0" -vocode = "0.1.111" -elevenlabs = "^0.2.23" +python-dotenv = "^1.0.1" +vocode = { path = "../..", extras = [ + "all", +], develop = true, python = ">=3.11,<3.12" } +elevenlabs = "^1.2.2" [build-system] diff --git a/apps/telephony_app/Dockerfile b/apps/telephony_app/Dockerfile index d96b3f348..8c25f6140 100644 --- a/apps/telephony_app/Dockerfile +++ b/apps/telephony_app/Dockerfile @@ -16,4 +16,4 @@ RUN poetry install --no-dev --no-interaction --no-ansi COPY main.py /code/main.py COPY speller_agent.py /code/speller_agent.py -CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "3000"] \ No newline at end of file +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "3000"] diff --git a/apps/telephony_app/docker-compose.yml b/apps/telephony_app/docker-compose.yml index a6c5be936..e6a2519bd 100644 --- a/apps/telephony_app/docker-compose.yml +++ b/apps/telephony_app/docker-compose.yml @@ -3,14 +3,14 @@ services: image: redis:7.0.9-alpine command: redis-server --bind 0.0.0.0 ports: - - 6379:6379 + - 6379:6379 app: image: vocode-telephony-app env_file: - - .env + - .env ports: - - 3000:3000 + - 3000:3000 depends_on: - - redis + - redis environment: - - REDISHOST=redis + - REDISHOST=redis diff --git a/apps/telephony_app/main.py b/apps/telephony_app/main.py index b6ed34cbe..5acc6dd28 100644 --- a/apps/telephony_app/main.py +++ b/apps/telephony_app/main.py @@ -1,42 +1,33 @@ # Standard library imports -import logging import os import sys +from dotenv import load_dotenv + # Third-party imports from fastapi import FastAPI -from vocode.streaming.models.telephony import TwilioConfig +from loguru import logger from pyngrok import ngrok -from vocode.streaming.telephony.config_manager.redis_config_manager import ( - RedisConfigManager, -) -from vocode.streaming.models.agent import ChatGPTAgentConfig -from vocode.streaming.models.message import BaseMessage -from vocode.streaming.telephony.server.base import ( - TwilioInboundCallConfig, - TelephonyServer, -) -from dotenv import load_dotenv # Local application/library specific imports -from speller_agent import ( - SpellerAgentFactory, - SpellerAgentConfig, -) +from speller_agent import SpellerAgentFactory + +from vocode.logging import configure_pretty_logging +from vocode.streaming.models.agent import ChatGPTAgentConfig +from vocode.streaming.models.message import BaseMessage +from vocode.streaming.models.telephony import TwilioConfig +from vocode.streaming.telephony.config_manager.redis_config_manager import RedisConfigManager +from vocode.streaming.telephony.server.base import TelephonyServer, TwilioInboundCallConfig # if running from python, this will load the local .env # docker-compose will load the .env file by itself load_dotenv() -app = FastAPI(docs_url=None) +configure_pretty_logging() -logging.basicConfig() -logger = logging.getLogger(__name__) -logger.setLevel(logging.DEBUG) +app = FastAPI(docs_url=None) -config_manager = RedisConfigManager( - logger=logger, -) +config_manager = RedisConfigManager() BASE_URL = os.getenv("BASE_URL") @@ -66,7 +57,9 @@ ), # uncomment this to use the speller agent instead # agent_config=SpellerAgentConfig( - # initial_message=BaseMessage(text="im a speller agent, say something to me and ill spell it out for you"), + # initial_message=BaseMessage( + # text="im a speller agent, say something to me and ill spell it out for you" + # ), # generate_responses=False, # ), twilio_config=TwilioConfig( @@ -76,7 +69,6 @@ ) ], agent_factory=SpellerAgentFactory(), - logger=logger, ) app.include_router(telephony_server.get_router()) diff --git a/apps/telephony_app/outbound_call.py b/apps/telephony_app/outbound_call.py index 4fc6dba7a..6c4ee3568 100644 --- a/apps/telephony_app/outbound_call.py +++ b/apps/telephony_app/outbound_call.py @@ -1,15 +1,18 @@ import os + from dotenv import load_dotenv -load_dotenv() +from vocode.streaming.models.agent import ChatGPTAgentConfig +from vocode.streaming.models.message import BaseMessage +from vocode.streaming.models.telephony import TwilioConfig -from vocode.streaming.telephony.conversation.outbound_call import OutboundCall -from vocode.streaming.telephony.config_manager.redis_config_manager import ( - RedisConfigManager, -) +load_dotenv() from speller_agent import SpellerAgentConfig +from vocode.streaming.telephony.config_manager.redis_config_manager import RedisConfigManager +from vocode.streaming.telephony.conversation.outbound_call import OutboundCall + BASE_URL = os.environ["BASE_URL"] @@ -21,12 +24,22 @@ async def main(): to_phone="+15555555555", from_phone="+15555555555", config_manager=config_manager, - agent_config=SpellerAgentConfig(generate_responses=False), + agent_config=ChatGPTAgentConfig( + initial_message=BaseMessage(text="What up"), + prompt_preamble="Have a pleasant conversation about life", + generate_responses=True, + ), + telephony_config=TwilioConfig( + account_sid=os.environ["TWILIO_ACCOUNT_SID"], + auth_token=os.environ["TWILIO_AUTH_TOKEN"], + ), ) input("Press enter to start call...") await outbound_call.start() + if __name__ == "__main__": import asyncio + asyncio.run(main()) diff --git a/apps/telephony_app/poetry.lock b/apps/telephony_app/poetry.lock index b262a12c2..d851a1835 100644 --- a/apps/telephony_app/poetry.lock +++ b/apps/telephony_app/poetry.lock @@ -2,92 +2,91 @@ [[package]] name = "aiohttp" -version = "3.9.1" +version = "3.9.5" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.8" files = [ - {file = "aiohttp-3.9.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e1f80197f8b0b846a8d5cf7b7ec6084493950d0882cc5537fb7b96a69e3c8590"}, - {file = "aiohttp-3.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c72444d17777865734aa1a4d167794c34b63e5883abb90356a0364a28904e6c0"}, - {file = "aiohttp-3.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9b05d5cbe9dafcdc733262c3a99ccf63d2f7ce02543620d2bd8db4d4f7a22f83"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c4fa235d534b3547184831c624c0b7c1e262cd1de847d95085ec94c16fddcd5"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:289ba9ae8e88d0ba16062ecf02dd730b34186ea3b1e7489046fc338bdc3361c4"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bff7e2811814fa2271be95ab6e84c9436d027a0e59665de60edf44e529a42c1f"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81b77f868814346662c96ab36b875d7814ebf82340d3284a31681085c051320f"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b9c7426923bb7bd66d409da46c41e3fb40f5caf679da624439b9eba92043fa6"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8d44e7bf06b0c0a70a20f9100af9fcfd7f6d9d3913e37754c12d424179b4e48f"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22698f01ff5653fe66d16ffb7658f582a0ac084d7da1323e39fd9eab326a1f26"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ca7ca5abfbfe8d39e653870fbe8d7710be7a857f8a8386fc9de1aae2e02ce7e4"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:8d7f98fde213f74561be1d6d3fa353656197f75d4edfbb3d94c9eb9b0fc47f5d"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5216b6082c624b55cfe79af5d538e499cd5f5b976820eac31951fb4325974501"}, - {file = "aiohttp-3.9.1-cp310-cp310-win32.whl", hash = "sha256:0e7ba7ff228c0d9a2cd66194e90f2bca6e0abca810b786901a569c0de082f489"}, - {file = "aiohttp-3.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:c7e939f1ae428a86e4abbb9a7c4732bf4706048818dfd979e5e2839ce0159f23"}, - {file = "aiohttp-3.9.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:df9cf74b9bc03d586fc53ba470828d7b77ce51b0582d1d0b5b2fb673c0baa32d"}, - {file = "aiohttp-3.9.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ecca113f19d5e74048c001934045a2b9368d77b0b17691d905af18bd1c21275e"}, - {file = "aiohttp-3.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8cef8710fb849d97c533f259103f09bac167a008d7131d7b2b0e3a33269185c0"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bea94403a21eb94c93386d559bce297381609153e418a3ffc7d6bf772f59cc35"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91c742ca59045dce7ba76cab6e223e41d2c70d79e82c284a96411f8645e2afff"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6c93b7c2e52061f0925c3382d5cb8980e40f91c989563d3d32ca280069fd6a87"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee2527134f95e106cc1653e9ac78846f3a2ec1004cf20ef4e02038035a74544d"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11ff168d752cb41e8492817e10fb4f85828f6a0142b9726a30c27c35a1835f01"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b8c3a67eb87394386847d188996920f33b01b32155f0a94f36ca0e0c635bf3e3"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c7b5d5d64e2a14e35a9240b33b89389e0035e6de8dbb7ffa50d10d8b65c57449"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:69985d50a2b6f709412d944ffb2e97d0be154ea90600b7a921f95a87d6f108a2"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:c9110c06eaaac7e1f5562caf481f18ccf8f6fdf4c3323feab28a93d34cc646bd"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d737e69d193dac7296365a6dcb73bbbf53bb760ab25a3727716bbd42022e8d7a"}, - {file = "aiohttp-3.9.1-cp311-cp311-win32.whl", hash = "sha256:4ee8caa925aebc1e64e98432d78ea8de67b2272252b0a931d2ac3bd876ad5544"}, - {file = "aiohttp-3.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:a34086c5cc285be878622e0a6ab897a986a6e8bf5b67ecb377015f06ed316587"}, - {file = "aiohttp-3.9.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f800164276eec54e0af5c99feb9494c295118fc10a11b997bbb1348ba1a52065"}, - {file = "aiohttp-3.9.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:500f1c59906cd142d452074f3811614be04819a38ae2b3239a48b82649c08821"}, - {file = "aiohttp-3.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0b0a6a36ed7e164c6df1e18ee47afbd1990ce47cb428739d6c99aaabfaf1b3af"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69da0f3ed3496808e8cbc5123a866c41c12c15baaaead96d256477edf168eb57"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:176df045597e674fa950bf5ae536be85699e04cea68fa3a616cf75e413737eb5"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b796b44111f0cab6bbf66214186e44734b5baab949cb5fb56154142a92989aeb"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f27fdaadce22f2ef950fc10dcdf8048407c3b42b73779e48a4e76b3c35bca26c"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcb6532b9814ea7c5a6a3299747c49de30e84472fa72821b07f5a9818bce0f66"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:54631fb69a6e44b2ba522f7c22a6fb2667a02fd97d636048478db2fd8c4e98fe"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4b4c452d0190c5a820d3f5c0f3cd8a28ace48c54053e24da9d6041bf81113183"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:cae4c0c2ca800c793cae07ef3d40794625471040a87e1ba392039639ad61ab5b"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:565760d6812b8d78d416c3c7cfdf5362fbe0d0d25b82fed75d0d29e18d7fc30f"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54311eb54f3a0c45efb9ed0d0a8f43d1bc6060d773f6973efd90037a51cd0a3f"}, - {file = "aiohttp-3.9.1-cp312-cp312-win32.whl", hash = "sha256:85c3e3c9cb1d480e0b9a64c658cd66b3cfb8e721636ab8b0e746e2d79a7a9eed"}, - {file = "aiohttp-3.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:11cb254e397a82efb1805d12561e80124928e04e9c4483587ce7390b3866d213"}, - {file = "aiohttp-3.9.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8a22a34bc594d9d24621091d1b91511001a7eea91d6652ea495ce06e27381f70"}, - {file = "aiohttp-3.9.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:598db66eaf2e04aa0c8900a63b0101fdc5e6b8a7ddd805c56d86efb54eb66672"}, - {file = "aiohttp-3.9.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c9376e2b09895c8ca8b95362283365eb5c03bdc8428ade80a864160605715f1"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41473de252e1797c2d2293804e389a6d6986ef37cbb4a25208de537ae32141dd"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9c5857612c9813796960c00767645cb5da815af16dafb32d70c72a8390bbf690"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffcd828e37dc219a72c9012ec44ad2e7e3066bec6ff3aaa19e7d435dbf4032ca"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:219a16763dc0294842188ac8a12262b5671817042b35d45e44fd0a697d8c8361"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f694dc8a6a3112059258a725a4ebe9acac5fe62f11c77ac4dcf896edfa78ca28"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bcc0ea8d5b74a41b621ad4a13d96c36079c81628ccc0b30cfb1603e3dfa3a014"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:90ec72d231169b4b8d6085be13023ece8fa9b1bb495e4398d847e25218e0f431"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:cf2a0ac0615842b849f40c4d7f304986a242f1e68286dbf3bd7a835e4f83acfd"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:0e49b08eafa4f5707ecfb321ab9592717a319e37938e301d462f79b4e860c32a"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2c59e0076ea31c08553e868cec02d22191c086f00b44610f8ab7363a11a5d9d8"}, - {file = "aiohttp-3.9.1-cp38-cp38-win32.whl", hash = "sha256:4831df72b053b1eed31eb00a2e1aff6896fb4485301d4ccb208cac264b648db4"}, - {file = "aiohttp-3.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:3135713c5562731ee18f58d3ad1bf41e1d8883eb68b363f2ffde5b2ea4b84cc7"}, - {file = "aiohttp-3.9.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cfeadf42840c1e870dc2042a232a8748e75a36b52d78968cda6736de55582766"}, - {file = "aiohttp-3.9.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:70907533db712f7aa791effb38efa96f044ce3d4e850e2d7691abd759f4f0ae0"}, - {file = "aiohttp-3.9.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cdefe289681507187e375a5064c7599f52c40343a8701761c802c1853a504558"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7481f581251bb5558ba9f635db70908819caa221fc79ee52a7f58392778c636"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49f0c1b3c2842556e5de35f122fc0f0b721334ceb6e78c3719693364d4af8499"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d406b01a9f5a7e232d1b0d161b40c05275ffbcbd772dc18c1d5a570961a1ca4"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d8e4450e7fe24d86e86b23cc209e0023177b6d59502e33807b732d2deb6975f"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c0266cd6f005e99f3f51e583012de2778e65af6b73860038b968a0a8888487a"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab221850108a4a063c5b8a70f00dd7a1975e5a1713f87f4ab26a46e5feac5a0e"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c88a15f272a0ad3d7773cf3a37cc7b7d077cbfc8e331675cf1346e849d97a4e5"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:237533179d9747080bcaad4d02083ce295c0d2eab3e9e8ce103411a4312991a0"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:02ab6006ec3c3463b528374c4cdce86434e7b89ad355e7bf29e2f16b46c7dd6f"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04fa38875e53eb7e354ece1607b1d2fdee2d175ea4e4d745f6ec9f751fe20c7c"}, - {file = "aiohttp-3.9.1-cp39-cp39-win32.whl", hash = "sha256:82eefaf1a996060602f3cc1112d93ba8b201dbf5d8fd9611227de2003dddb3b7"}, - {file = "aiohttp-3.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:9b05d33ff8e6b269e30a7957bd3244ffbce2a7a35a81b81c382629b80af1a8bf"}, - {file = "aiohttp-3.9.1.tar.gz", hash = "sha256:8fc49a87ac269d4529da45871e2ffb6874e87779c3d0e2ccd813c0899221239d"}, + {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fcde4c397f673fdec23e6b05ebf8d4751314fa7c24f93334bf1f1364c1c69ac7"}, + {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d6b3f1fabe465e819aed2c421a6743d8debbde79b6a8600739300630a01bf2c"}, + {file = "aiohttp-3.9.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ae79c1bc12c34082d92bf9422764f799aee4746fd7a392db46b7fd357d4a17a"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d3ebb9e1316ec74277d19c5f482f98cc65a73ccd5430540d6d11682cd857430"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84dabd95154f43a2ea80deffec9cb44d2e301e38a0c9d331cc4aa0166fe28ae3"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8a02fbeca6f63cb1f0475c799679057fc9268b77075ab7cf3f1c600e81dd46b"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c26959ca7b75ff768e2776d8055bf9582a6267e24556bb7f7bd29e677932be72"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:714d4e5231fed4ba2762ed489b4aec07b2b9953cf4ee31e9871caac895a839c0"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7a6a8354f1b62e15d48e04350f13e726fa08b62c3d7b8401c0a1314f02e3558"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c413016880e03e69d166efb5a1a95d40f83d5a3a648d16486592c49ffb76d0db"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ff84aeb864e0fac81f676be9f4685f0527b660f1efdc40dcede3c251ef1e867f"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ad7f2919d7dac062f24d6f5fe95d401597fbb015a25771f85e692d043c9d7832"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:702e2c7c187c1a498a4e2b03155d52658fdd6fda882d3d7fbb891a5cf108bb10"}, + {file = "aiohttp-3.9.5-cp310-cp310-win32.whl", hash = "sha256:67c3119f5ddc7261d47163ed86d760ddf0e625cd6246b4ed852e82159617b5fb"}, + {file = "aiohttp-3.9.5-cp310-cp310-win_amd64.whl", hash = "sha256:471f0ef53ccedec9995287f02caf0c068732f026455f07db3f01a46e49d76bbb"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ae53e33ee7476dd3d1132f932eeb39bf6125083820049d06edcdca4381f342"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c088c4d70d21f8ca5c0b8b5403fe84a7bc8e024161febdd4ef04575ef35d474d"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:639d0042b7670222f33b0028de6b4e2fad6451462ce7df2af8aee37dcac55424"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f26383adb94da5e7fb388d441bf09c61e5e35f455a3217bfd790c6b6bc64b2ee"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66331d00fb28dc90aa606d9a54304af76b335ae204d1836f65797d6fe27f1ca2"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ff550491f5492ab5ed3533e76b8567f4b37bd2995e780a1f46bca2024223233"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f22eb3a6c1080d862befa0a89c380b4dafce29dc6cd56083f630073d102eb595"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a81b1143d42b66ffc40a441379387076243ef7b51019204fd3ec36b9f69e77d6"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f64fd07515dad67f24b6ea4a66ae2876c01031de91c93075b8093f07c0a2d93d"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:93e22add827447d2e26d67c9ac0161756007f152fdc5210277d00a85f6c92323"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:55b39c8684a46e56ef8c8d24faf02de4a2b2ac60d26cee93bc595651ff545de9"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4715a9b778f4293b9f8ae7a0a7cef9829f02ff8d6277a39d7f40565c737d3771"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:afc52b8d969eff14e069a710057d15ab9ac17cd4b6753042c407dcea0e40bf75"}, + {file = "aiohttp-3.9.5-cp311-cp311-win32.whl", hash = "sha256:b3df71da99c98534be076196791adca8819761f0bf6e08e07fd7da25127150d6"}, + {file = "aiohttp-3.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:88e311d98cc0bf45b62fc46c66753a83445f5ab20038bcc1b8a1cc05666f428a"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c7a4b7a6cf5b6eb11e109a9755fd4fda7d57395f8c575e166d363b9fc3ec4678"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0a158704edf0abcac8ac371fbb54044f3270bdbc93e254a82b6c82be1ef08f3c"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d153f652a687a8e95ad367a86a61e8d53d528b0530ef382ec5aaf533140ed00f"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82a6a97d9771cb48ae16979c3a3a9a18b600a8505b1115cfe354dfb2054468b4"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60cdbd56f4cad9f69c35eaac0fbbdf1f77b0ff9456cebd4902f3dd1cf096464c"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8676e8fd73141ded15ea586de0b7cda1542960a7b9ad89b2b06428e97125d4fa"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da00da442a0e31f1c69d26d224e1efd3a1ca5bcbf210978a2ca7426dfcae9f58"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18f634d540dd099c262e9f887c8bbacc959847cfe5da7a0e2e1cf3f14dbf2daf"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:320e8618eda64e19d11bdb3bd04ccc0a816c17eaecb7e4945d01deee2a22f95f"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:2faa61a904b83142747fc6a6d7ad8fccff898c849123030f8e75d5d967fd4a81"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:8c64a6dc3fe5db7b1b4d2b5cb84c4f677768bdc340611eca673afb7cf416ef5a"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:393c7aba2b55559ef7ab791c94b44f7482a07bf7640d17b341b79081f5e5cd1a"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c671dc117c2c21a1ca10c116cfcd6e3e44da7fcde37bf83b2be485ab377b25da"}, + {file = "aiohttp-3.9.5-cp312-cp312-win32.whl", hash = "sha256:5a7ee16aab26e76add4afc45e8f8206c95d1d75540f1039b84a03c3b3800dd59"}, + {file = "aiohttp-3.9.5-cp312-cp312-win_amd64.whl", hash = "sha256:5ca51eadbd67045396bc92a4345d1790b7301c14d1848feaac1d6a6c9289e888"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:694d828b5c41255e54bc2dddb51a9f5150b4eefa9886e38b52605a05d96566e8"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0605cc2c0088fcaae79f01c913a38611ad09ba68ff482402d3410bf59039bfb8"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4558e5012ee03d2638c681e156461d37b7a113fe13970d438d95d10173d25f78"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dbc053ac75ccc63dc3a3cc547b98c7258ec35a215a92bd9f983e0aac95d3d5b"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4109adee842b90671f1b689901b948f347325045c15f46b39797ae1bf17019de"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6ea1a5b409a85477fd8e5ee6ad8f0e40bf2844c270955e09360418cfd09abac"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3c2890ca8c59ee683fd09adf32321a40fe1cf164e3387799efb2acebf090c11"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3916c8692dbd9d55c523374a3b8213e628424d19116ac4308e434dbf6d95bbdd"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8d1964eb7617907c792ca00b341b5ec3e01ae8c280825deadbbd678447b127e1"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5ab8e1f6bee051a4bf6195e38a5c13e5e161cb7bad83d8854524798bd9fcd6e"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:52c27110f3862a1afbcb2af4281fc9fdc40327fa286c4625dfee247c3ba90156"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:7f64cbd44443e80094309875d4f9c71d0401e966d191c3d469cde4642bc2e031"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8b4f72fbb66279624bfe83fd5eb6aea0022dad8eec62b71e7bf63ee1caadeafe"}, + {file = "aiohttp-3.9.5-cp38-cp38-win32.whl", hash = "sha256:6380c039ec52866c06d69b5c7aad5478b24ed11696f0e72f6b807cfb261453da"}, + {file = "aiohttp-3.9.5-cp38-cp38-win_amd64.whl", hash = "sha256:da22dab31d7180f8c3ac7c7635f3bcd53808f374f6aa333fe0b0b9e14b01f91a"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1732102949ff6087589408d76cd6dea656b93c896b011ecafff418c9661dc4ed"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c6021d296318cb6f9414b48e6a439a7f5d1f665464da507e8ff640848ee2a58a"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:239f975589a944eeb1bad26b8b140a59a3a320067fb3cd10b75c3092405a1372"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b7b30258348082826d274504fbc7c849959f1989d86c29bc355107accec6cfb"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd2adf5c87ff6d8b277814a28a535b59e20bfea40a101db6b3bdca7e9926bc24"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9a3d838441bebcf5cf442700e3963f58b5c33f015341f9ea86dcd7d503c07e2"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e3a1ae66e3d0c17cf65c08968a5ee3180c5a95920ec2731f53343fac9bad106"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c69e77370cce2d6df5d12b4e12bdcca60c47ba13d1cbbc8645dd005a20b738b"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf56238f4bbf49dab8c2dc2e6b1b68502b1e88d335bea59b3f5b9f4c001475"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d1469f228cd9ffddd396d9948b8c9cd8022b6d1bf1e40c6f25b0fb90b4f893ed"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:45731330e754f5811c314901cebdf19dd776a44b31927fa4b4dbecab9e457b0c"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3fcb4046d2904378e3aeea1df51f697b0467f2aac55d232c87ba162709478c46"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8cf142aa6c1a751fcb364158fd710b8a9be874b81889c2bd13aa8893197455e2"}, + {file = "aiohttp-3.9.5-cp39-cp39-win32.whl", hash = "sha256:7b179eea70833c8dee51ec42f3b4097bd6370892fa93f510f76762105568cf09"}, + {file = "aiohttp-3.9.5-cp39-cp39-win_amd64.whl", hash = "sha256:38d80498e2e169bc61418ff36170e0aad0cd268da8b38a17c4cf29d254a8b3f1"}, + {file = "aiohttp-3.9.5.tar.gz", hash = "sha256:edea7d15772ceeb29db4aff55e482d4bcfb6ae160ce144f2682de02f6d693551"}, ] [package.dependencies] aiosignal = ">=1.1.2" -async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""} attrs = ">=17.3.0" frozenlist = ">=1.1.1" multidict = ">=4.5,<7.0" @@ -125,47 +124,78 @@ files = [ frozenlist = ">=1.1.0" [[package]] -name = "anthropic" -version = "0.2.10" -description = "Library for accessing the anthropic API" +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" files = [ - {file = "anthropic-0.2.10-py3-none-any.whl", hash = "sha256:a007496207fd186b0bcb9592b00ca130069d2a427f3d6f602a61dbbd1ac6316e"}, - {file = "anthropic-0.2.10.tar.gz", hash = "sha256:e4da061a86d8ffb86072c0b0feaf219a3a4f7dfddd4224df9ba769e469498c19"}, + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, +] + +[[package]] +name = "anthropic" +version = "0.28.0" +description = "The official Python library for the anthropic API" +optional = false +python-versions = ">=3.7" +files = [ + {file = "anthropic-0.28.0-py3-none-any.whl", hash = "sha256:2b620b21aee3d20c5d8005483c34df239d53ae895687113b26b8a36892a7e20f"}, ] [package.dependencies] -aiohttp = "*" -httpx = "*" -requests = "*" -tokenizers = "*" +anyio = ">=3.5.0,<5" +distro = ">=1.7.0,<2" +httpx = ">=0.23.0,<1" +jiter = ">=0.4.0,<1" +pydantic = ">=1.9.0,<3" +sniffio = "*" +tokenizers = ">=0.13.0" +typing-extensions = ">=4.7,<5" [package.extras] -dev = ["black (>=22.3.0)", "pytest"] +bedrock = ["boto3 (>=1.28.57)", "botocore (>=1.31.57)"] +vertex = ["google-auth (>=2,<3)"] [[package]] name = "anyio" -version = "4.2.0" +version = "4.4.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.8" files = [ - {file = "anyio-4.2.0-py3-none-any.whl", hash = "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee"}, - {file = "anyio-4.2.0.tar.gz", hash = "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f"}, + {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, + {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, ] [package.dependencies] -exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" sniffio = ">=1.1" -typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} [package.extras] doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] trio = ["trio (>=0.23)"] +[[package]] +name = "asttokens" +version = "2.4.1" +description = "Annotate AST trees with source code positions" +optional = false +python-versions = "*" +files = [ + {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, + {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, +] + +[package.dependencies] +six = ">=1.12.0" + +[package.extras] +astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] +test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] + [[package]] name = "async-timeout" version = "4.0.3" @@ -198,28 +228,39 @@ tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "p [[package]] name = "azure-cognitiveservices-speech" -version = "1.34.1" +version = "1.37.0" description = "Microsoft Cognitive Services Speech SDK for Python" optional = false python-versions = ">=3.7" files = [ - {file = "azure_cognitiveservices_speech-1.34.1-py3-none-macosx_10_14_x86_64.whl", hash = "sha256:f0bbdb78b6c48b34b870bb05e7085ae277ef230425b86e25ac62f808480bbbbf"}, - {file = "azure_cognitiveservices_speech-1.34.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:501be52021acea776c23e1fae3fc08b65801008dc6d919959758723ee8114fbf"}, - {file = "azure_cognitiveservices_speech-1.34.1-py3-none-manylinux1_x86_64.whl", hash = "sha256:d28ec35b4e88d5205dda2afb401588d185dabeede9a16432d53f8751bcf853ba"}, - {file = "azure_cognitiveservices_speech-1.34.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:12a243371a133d0299fcebb067ed93e989fdeaa163b5dcf63f6f2d6a2ebcb8e7"}, - {file = "azure_cognitiveservices_speech-1.34.1-py3-none-win32.whl", hash = "sha256:cd0d4b84b6fd1657ad1f2b088fa83bb851c6f1568b514d92f265d9e958e7f83f"}, - {file = "azure_cognitiveservices_speech-1.34.1-py3-none-win_amd64.whl", hash = "sha256:21a1fc84eca697332862af0a1fafe0766e9742c91848e0c3a6cf4f883081721d"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-macosx_10_14_x86_64.whl", hash = "sha256:906d6bf65176e93464e2d763dd074ca00c48cfe1a896371fcdcb155a500910f7"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:54ec8dd55d4dbd9058c61909e08485d3761d6d30954da189e1b17d84daf5e2e0"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:685424689725d2d4115485998c0888c8b5b502259037ff533e5a834575f80b66"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:384f66786c2335165035270897b34d0b91736a1fdf38f7696e9a227075cb2489"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-win32.whl", hash = "sha256:343d5f449ccd6c9b53cd37dd46a70ece0905243517df7a0c047779e55072254c"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-win_amd64.whl", hash = "sha256:a18fb45490cdcd681407ccaad9560fb14dda1c8276de297e219ea1a880467e28"}, +] + +[[package]] +name = "cachetools" +version = "5.3.3" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cachetools-5.3.3-py3-none-any.whl", hash = "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945"}, + {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, ] [[package]] name = "certifi" -version = "2023.11.17" +version = "2024.2.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, - {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, ] [[package]] @@ -412,43 +453,43 @@ files = [ [[package]] name = "cryptography" -version = "42.0.1" +version = "42.0.7" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:265bdc693570b895eb641410b8fc9e8ddbce723a669236162b9d9cfb70bd8d77"}, - {file = "cryptography-42.0.1-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:160fa08dfa6dca9cb8ad9bd84e080c0db6414ba5ad9a7470bc60fb154f60111e"}, - {file = "cryptography-42.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:727387886c9c8de927c360a396c5edcb9340d9e960cda145fca75bdafdabd24c"}, - {file = "cryptography-42.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d84673c012aa698555d4710dcfe5f8a0ad76ea9dde8ef803128cc669640a2e0"}, - {file = "cryptography-42.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e6edc3a568667daf7d349d7e820783426ee4f1c0feab86c29bd1d6fe2755e009"}, - {file = "cryptography-42.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:d50718dd574a49d3ef3f7ef7ece66ef281b527951eb2267ce570425459f6a404"}, - {file = "cryptography-42.0.1-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:9544492e8024f29919eac2117edd8c950165e74eb551a22c53f6fdf6ba5f4cb8"}, - {file = "cryptography-42.0.1-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ab6b302d51fbb1dd339abc6f139a480de14d49d50f65fdc7dff782aa8631d035"}, - {file = "cryptography-42.0.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2fe16624637d6e3e765530bc55caa786ff2cbca67371d306e5d0a72e7c3d0407"}, - {file = "cryptography-42.0.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ed1b2130f5456a09a134cc505a17fc2830a1a48ed53efd37dcc904a23d7b82fa"}, - {file = "cryptography-42.0.1-cp37-abi3-win32.whl", hash = "sha256:e5edf189431b4d51f5c6fb4a95084a75cef6b4646c934eb6e32304fc720e1453"}, - {file = "cryptography-42.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:6bfd823b336fdcd8e06285ae8883d3d2624d3bdef312a0e2ef905f332f8e9302"}, - {file = "cryptography-42.0.1-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:351db02c1938c8e6b1fee8a78d6b15c5ccceca7a36b5ce48390479143da3b411"}, - {file = "cryptography-42.0.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:430100abed6d3652208ae1dd410c8396213baee2e01a003a4449357db7dc9e14"}, - {file = "cryptography-42.0.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dff7a32880a51321f5de7869ac9dde6b1fca00fc1fef89d60e93f215468e824"}, - {file = "cryptography-42.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:b512f33c6ab195852595187af5440d01bb5f8dd57cb7a91e1e009a17f1b7ebca"}, - {file = "cryptography-42.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:95d900d19a370ae36087cc728e6e7be9c964ffd8cbcb517fd1efb9c9284a6abc"}, - {file = "cryptography-42.0.1-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:6ac8924085ed8287545cba89dc472fc224c10cc634cdf2c3e2866fe868108e77"}, - {file = "cryptography-42.0.1-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cb2861a9364fa27d24832c718150fdbf9ce6781d7dc246a516435f57cfa31fe7"}, - {file = "cryptography-42.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25ec6e9e81de5d39f111a4114193dbd39167cc4bbd31c30471cebedc2a92c323"}, - {file = "cryptography-42.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9d61fcdf37647765086030d81872488e4cb3fafe1d2dda1d487875c3709c0a49"}, - {file = "cryptography-42.0.1-cp39-abi3-win32.whl", hash = "sha256:16b9260d04a0bfc8952b00335ff54f471309d3eb9d7e8dbfe9b0bd9e26e67881"}, - {file = "cryptography-42.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:7911586fc69d06cd0ab3f874a169433db1bc2f0e40988661408ac06c4527a986"}, - {file = "cryptography-42.0.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d3594947d2507d4ef7a180a7f49a6db41f75fb874c2fd0e94f36b89bfd678bf2"}, - {file = "cryptography-42.0.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:8d7efb6bf427d2add2f40b6e1e8e476c17508fa8907234775214b153e69c2e11"}, - {file = "cryptography-42.0.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:126e0ba3cc754b200a2fb88f67d66de0d9b9e94070c5bc548318c8dab6383cb6"}, - {file = "cryptography-42.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:802d6f83233cf9696b59b09eb067e6b4d5ae40942feeb8e13b213c8fad47f1aa"}, - {file = "cryptography-42.0.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0b7cacc142260ada944de070ce810c3e2a438963ee3deb45aa26fd2cee94c9a4"}, - {file = "cryptography-42.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:32ea63ceeae870f1a62e87f9727359174089f7b4b01e4999750827bf10e15d60"}, - {file = "cryptography-42.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d3902c779a92151f134f68e555dd0b17c658e13429f270d8a847399b99235a3f"}, - {file = "cryptography-42.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:50aecd93676bcca78379604ed664c45da82bc1241ffb6f97f6b7392ed5bc6f04"}, - {file = "cryptography-42.0.1.tar.gz", hash = "sha256:fd33f53809bb363cf126bebe7a99d97735988d9b0131a2be59fbf83e1259a5b7"}, + {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"}, + {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"}, + {file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"}, + {file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"}, + {file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"}, + {file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"}, + {file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"}, + {file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"}, ] [package.dependencies] @@ -466,19 +507,30 @@ test-randomorder = ["pytest-randomly"] [[package]] name = "dataclasses-json" -version = "0.5.14" +version = "0.6.6" description = "Easily serialize dataclasses to and from JSON." optional = false -python-versions = ">=3.7,<3.13" +python-versions = "<4.0,>=3.7" files = [ - {file = "dataclasses_json-0.5.14-py3-none-any.whl", hash = "sha256:5ec6fed642adb1dbdb4182badb01e0861badfd8fda82e3b67f44b2d1e9d10d21"}, - {file = "dataclasses_json-0.5.14.tar.gz", hash = "sha256:d82896a94c992ffaf689cd1fafc180164e2abdd415b8f94a7f78586af5886236"}, + {file = "dataclasses_json-0.6.6-py3-none-any.whl", hash = "sha256:e54c5c87497741ad454070ba0ed411523d46beb5da102e221efb873801b0ba85"}, + {file = "dataclasses_json-0.6.6.tar.gz", hash = "sha256:0c09827d26fffda27f1be2fed7a7a01a29c5ddcd2eb6393ad5ebf9d77e9deae8"}, ] [package.dependencies] marshmallow = ">=3.18.0,<4.0.0" typing-inspect = ">=0.4.0,<1" +[[package]] +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" +optional = false +python-versions = ">=3.5" +files = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] + [[package]] name = "deprecated" version = "1.2.14" @@ -497,52 +549,142 @@ wrapt = ">=1.10,<2" dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] [[package]] -name = "exceptiongroup" -version = "1.2.0" -description = "Backport of PEP 654 (exception groups)" +name = "distro" +version = "1.9.0" +description = "Distro - an OS platform information API" optional = false -python-versions = ">=3.7" +python-versions = ">=3.6" +files = [ + {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, + {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, +] + +[[package]] +name = "dnspython" +version = "2.6.1" +description = "DNS toolkit" +optional = false +python-versions = ">=3.8" +files = [ + {file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"}, + {file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"}, +] + +[package.extras] +dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "sphinx (>=7.2.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"] +dnssec = ["cryptography (>=41)"] +doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"] +doq = ["aioquic (>=0.9.25)"] +idna = ["idna (>=3.6)"] +trio = ["trio (>=0.23)"] +wmi = ["wmi (>=1.5.1)"] + +[[package]] +name = "elevenlabs" +version = "1.2.2" +description = "" +optional = false +python-versions = "<4.0,>=3.8" +files = [ + {file = "elevenlabs-1.2.2-py3-none-any.whl", hash = "sha256:60b92b0e2aabdfba93a43569f207f8a2ad397492519b8e11a2eebb32807ddefa"}, + {file = "elevenlabs-1.2.2.tar.gz", hash = "sha256:ebd02869b95602b8956874dd727981bb49ad16b9a3c2f5901193d838213694aa"}, +] + +[package.dependencies] +httpx = ">=0.21.2" +ipython = ">=7.0" +pydantic = ">=1.9.2" +requests = ">=2.20" +typing_extensions = ">=4.0.0" +websockets = ">=11.0" + +[[package]] +name = "email-validator" +version = "2.1.1" +description = "A robust email address syntax and deliverability validation library." +optional = false +python-versions = ">=3.8" +files = [ + {file = "email_validator-2.1.1-py3-none-any.whl", hash = "sha256:97d882d174e2a65732fb43bfce81a3a834cbc1bde8bf419e30ef5ea976370a05"}, + {file = "email_validator-2.1.1.tar.gz", hash = "sha256:200a70680ba08904be6d1eef729205cc0d687634399a5924d842533efb824b84"}, +] + +[package.dependencies] +dnspython = ">=2.0.0" +idna = ">=2.0.0" + +[[package]] +name = "executing" +version = "2.0.1" +description = "Get the currently executing AST node of a frame, and other information" +optional = false +python-versions = ">=3.5" files = [ - {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, - {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, + {file = "executing-2.0.1-py2.py3-none-any.whl", hash = "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc"}, + {file = "executing-2.0.1.tar.gz", hash = "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147"}, ] [package.extras] -test = ["pytest (>=6)"] +tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] [[package]] name = "fastapi" -version = "0.100.1" +version = "0.111.0" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "fastapi-0.111.0-py3-none-any.whl", hash = "sha256:97ecbf994be0bcbdadedf88c3150252bed7b2087075ac99735403b1b76cc8fc0"}, + {file = "fastapi-0.111.0.tar.gz", hash = "sha256:b9db9dd147c91cb8b769f7183535773d8741dd46f9dc6676cd82eab510228cd7"}, +] + +[package.dependencies] +email_validator = ">=2.0.0" +fastapi-cli = ">=0.0.2" +httpx = ">=0.23.0" +jinja2 = ">=2.11.2" +orjson = ">=3.2.1" +pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" +python-multipart = ">=0.0.7" +starlette = ">=0.37.2,<0.38.0" +typing-extensions = ">=4.8.0" +ujson = ">=4.0.1,<4.0.2 || >4.0.2,<4.1.0 || >4.1.0,<4.2.0 || >4.2.0,<4.3.0 || >4.3.0,<5.0.0 || >5.0.0,<5.1.0 || >5.1.0" +uvicorn = {version = ">=0.12.0", extras = ["standard"]} + +[package.extras] +all = ["email_validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] + +[[package]] +name = "fastapi-cli" +version = "0.0.4" +description = "Run and manage FastAPI apps from the command line with FastAPI CLI. 🚀" +optional = false +python-versions = ">=3.8" files = [ - {file = "fastapi-0.100.1-py3-none-any.whl", hash = "sha256:ec6dd52bfc4eff3063cfcd0713b43c87640fefb2687bbbe3d8a08d94049cdf32"}, - {file = "fastapi-0.100.1.tar.gz", hash = "sha256:522700d7a469e4a973d92321ab93312448fbe20fca9c8da97effc7e7bc56df23"}, + {file = "fastapi_cli-0.0.4-py3-none-any.whl", hash = "sha256:a2552f3a7ae64058cdbb530be6fa6dbfc975dc165e4fa66d224c3d396e25e809"}, + {file = "fastapi_cli-0.0.4.tar.gz", hash = "sha256:e2e9ffaffc1f7767f488d6da34b6f5a377751c996f397902eb6abb99a67bde32"}, ] [package.dependencies] -pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<3.0.0" -starlette = ">=0.27.0,<0.28.0" -typing-extensions = ">=4.5.0" +typer = ">=0.12.3" [package.extras] -all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +standard = ["fastapi", "uvicorn[standard] (>=0.15.0)"] [[package]] name = "filelock" -version = "3.13.1" +version = "3.14.0" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"}, - {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"}, + {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"}, + {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"}, ] [package.extras] -docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] typing = ["typing-extensions (>=4.8)"] [[package]] @@ -633,13 +775,13 @@ files = [ [[package]] name = "fsspec" -version = "2023.12.2" +version = "2024.5.0" description = "File-system specification" optional = false python-versions = ">=3.8" files = [ - {file = "fsspec-2023.12.2-py3-none-any.whl", hash = "sha256:d800d87f72189a745fa3d6b033b9dc4a34ad069f60ca60b943a63599f5501960"}, - {file = "fsspec-2023.12.2.tar.gz", hash = "sha256:8548d39e8810b59c38014934f6b31e57f40c1b20f911f4cc2b85389c7e9bf0cb"}, + {file = "fsspec-2024.5.0-py3-none-any.whl", hash = "sha256:e0fdbc446d67e182f49a70b82cf7889028a63588fde6b222521f10937b2b670c"}, + {file = "fsspec-2024.5.0.tar.gz", hash = "sha256:1d021b0b0f933e3b3029ed808eb400c08ba101ca2de4b3483fbc9ca23fcee94a"}, ] [package.extras] @@ -647,7 +789,7 @@ abfs = ["adlfs"] adl = ["adlfs"] arrow = ["pyarrow (>=1)"] dask = ["dask", "distributed"] -devel = ["pytest", "pytest-cov"] +dev = ["pre-commit", "ruff"] dropbox = ["dropbox", "dropboxdrivefs", "requests"] full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] fuse = ["fusepy"] @@ -657,15 +799,117 @@ github = ["requests"] gs = ["gcsfs"] gui = ["panel"] hdfs = ["pyarrow (>=1)"] -http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)", "requests"] +http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)"] libarchive = ["libarchive-c"] oci = ["ocifs"] s3 = ["s3fs"] sftp = ["paramiko"] smb = ["smbprotocol"] ssh = ["paramiko"] +test = ["aiohttp (!=4.0.0a0,!=4.0.0a1)", "numpy", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "requests"] +test-downstream = ["aiobotocore (>=2.5.4,<3.0.0)", "dask-expr", "dask[dataframe,test]", "moto[server] (>4,<5)", "pytest-timeout", "xarray"] +test-full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "cloudpickle", "dask", "distributed", "dropbox", "dropboxdrivefs", "fastparquet", "fusepy", "gcsfs", "jinja2", "kerchunk", "libarchive-c", "lz4", "notebook", "numpy", "ocifs", "pandas", "panel", "paramiko", "pyarrow", "pyarrow (>=1)", "pyftpdlib", "pygit2", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "python-snappy", "requests", "smbprotocol", "tqdm", "urllib3", "zarr", "zstandard"] tqdm = ["tqdm"] +[[package]] +name = "google-api-core" +version = "2.19.0" +description = "Google API client core library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-api-core-2.19.0.tar.gz", hash = "sha256:cf1b7c2694047886d2af1128a03ae99e391108a08804f87cfd35970e49c9cd10"}, + {file = "google_api_core-2.19.0-py3-none-any.whl", hash = "sha256:8661eec4078c35428fd3f69a2c7ee29e342896b70f01d1a1cbcb334372dd6251"}, +] + +[package.dependencies] +google-auth = ">=2.14.1,<3.0.dev0" +googleapis-common-protos = ">=1.56.2,<2.0.dev0" +grpcio = {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""} +grpcio-status = {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""} +proto-plus = ">=1.22.3,<2.0.0dev" +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" +requests = ">=2.18.0,<3.0.0.dev0" + +[package.extras] +grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "grpcio-status (>=1.33.2,<2.0.dev0)", "grpcio-status (>=1.49.1,<2.0.dev0)"] +grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] +grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] + +[[package]] +name = "google-auth" +version = "2.29.0" +description = "Google Authentication Library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-auth-2.29.0.tar.gz", hash = "sha256:672dff332d073227550ffc7457868ac4218d6c500b155fe6cc17d2b13602c360"}, + {file = "google_auth-2.29.0-py2.py3-none-any.whl", hash = "sha256:d452ad095688cd52bae0ad6fafe027f6a6d6f560e810fec20914e17a09526415"}, +] + +[package.dependencies] +cachetools = ">=2.0.0,<6.0" +pyasn1-modules = ">=0.2.1" +rsa = ">=3.1.4,<5" + +[package.extras] +aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"] +enterprise-cert = ["cryptography (==36.0.2)", "pyopenssl (==22.0.0)"] +pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] +reauth = ["pyu2f (>=0.1.5)"] +requests = ["requests (>=2.20.0,<3.0.0.dev0)"] + +[[package]] +name = "google-cloud-speech" +version = "2.26.0" +description = "Google Cloud Speech API client library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-cloud-speech-2.26.0.tar.gz", hash = "sha256:d3156a78496aeacff403429408a1b13efe996da6f0544a25567904ad801671d5"}, + {file = "google_cloud_speech-2.26.0-py2.py3-none-any.whl", hash = "sha256:8b61aebcbcc9bd5450933c94c431584a07667e022d12834f9037bb2c0e673c87"}, +] + +[package.dependencies] +google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} +google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev" +proto-plus = ">=1.22.3,<2.0.0dev" +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" + +[[package]] +name = "google-cloud-texttospeech" +version = "2.16.3" +description = "Google Cloud Texttospeech API client library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-cloud-texttospeech-2.16.3.tar.gz", hash = "sha256:fabc315032d137da0710bb4c268734d336212d8fa8316b23b277dd3a84ce721c"}, + {file = "google_cloud_texttospeech-2.16.3-py2.py3-none-any.whl", hash = "sha256:5d1e23f9270908a5d7ecf2af04105fbd3a7ddde60fe48506e397bd18c1ece499"}, +] + +[package.dependencies] +google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} +google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev" +proto-plus = ">=1.22.3,<2.0.0dev" +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" + +[[package]] +name = "googleapis-common-protos" +version = "1.63.0" +description = "Common protobufs used in Google APIs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "googleapis-common-protos-1.63.0.tar.gz", hash = "sha256:17ad01b11d5f1d0171c06d3ba5c04c54474e883b66b949722b4938ee2694ef4e"}, + {file = "googleapis_common_protos-1.63.0-py2.py3-none-any.whl", hash = "sha256:ae45f75702f7c08b541f750854a678bd8f534a1a6bace6afe975f1d0a82d6632"}, +] + +[package.dependencies] +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" + +[package.extras] +grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] + [[package]] name = "greenlet" version = "3.0.3" @@ -737,6 +981,80 @@ files = [ docs = ["Sphinx", "furo"] test = ["objgraph", "psutil"] +[[package]] +name = "grpcio" +version = "1.64.0" +description = "HTTP/2-based RPC framework" +optional = false +python-versions = ">=3.8" +files = [ + {file = "grpcio-1.64.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:3b09c3d9de95461214a11d82cc0e6a46a6f4e1f91834b50782f932895215e5db"}, + {file = "grpcio-1.64.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:7e013428ab472892830287dd082b7d129f4d8afef49227a28223a77337555eaa"}, + {file = "grpcio-1.64.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:02cc9cc3f816d30f7993d0d408043b4a7d6a02346d251694d8ab1f78cc723e7e"}, + {file = "grpcio-1.64.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f5de082d936e0208ce8db9095821361dfa97af8767a6607ae71425ac8ace15c"}, + {file = "grpcio-1.64.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7b7bf346391dffa182fba42506adf3a84f4a718a05e445b37824136047686a1"}, + {file = "grpcio-1.64.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b2cbdfba18408389a1371f8c2af1659119e1831e5ed24c240cae9e27b4abc38d"}, + {file = "grpcio-1.64.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:aca4f15427d2df592e0c8f3d38847e25135e4092d7f70f02452c0e90d6a02d6d"}, + {file = "grpcio-1.64.0-cp310-cp310-win32.whl", hash = "sha256:7c1f5b2298244472bcda49b599be04579f26425af0fd80d3f2eb5fd8bc84d106"}, + {file = "grpcio-1.64.0-cp310-cp310-win_amd64.whl", hash = "sha256:73f84f9e5985a532e47880b3924867de16fa1aa513fff9b26106220c253c70c5"}, + {file = "grpcio-1.64.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:2a18090371d138a57714ee9bffd6c9c9cb2e02ce42c681aac093ae1e7189ed21"}, + {file = "grpcio-1.64.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:59c68df3a934a586c3473d15956d23a618b8f05b5e7a3a904d40300e9c69cbf0"}, + {file = "grpcio-1.64.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:b52e1ec7185512103dd47d41cf34ea78e7a7361ba460187ddd2416b480e0938c"}, + {file = "grpcio-1.64.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d598b5d5e2c9115d7fb7e2cb5508d14286af506a75950762aa1372d60e41851"}, + {file = "grpcio-1.64.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01615bbcae6875eee8091e6b9414072f4e4b00d8b7e141f89635bdae7cf784e5"}, + {file = "grpcio-1.64.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0b2dfe6dcace264807d9123d483d4c43274e3f8c39f90ff51de538245d7a4145"}, + {file = "grpcio-1.64.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7f17572dc9acd5e6dfd3014d10c0b533e9f79cd9517fc10b0225746f4c24b58e"}, + {file = "grpcio-1.64.0-cp311-cp311-win32.whl", hash = "sha256:6ec5ed15b4ffe56e2c6bc76af45e6b591c9be0224b3fb090adfb205c9012367d"}, + {file = "grpcio-1.64.0-cp311-cp311-win_amd64.whl", hash = "sha256:597191370951b477b7a1441e1aaa5cacebeb46a3b0bd240ec3bb2f28298c7553"}, + {file = "grpcio-1.64.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:1ce4cd5a61d4532651079e7aae0fedf9a80e613eed895d5b9743e66b52d15812"}, + {file = "grpcio-1.64.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:650a8150a9b288f40d5b7c1d5400cc11724eae50bd1f501a66e1ea949173649b"}, + {file = "grpcio-1.64.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:8de0399b983f8676a7ccfdd45e5b2caec74a7e3cc576c6b1eecf3b3680deda5e"}, + {file = "grpcio-1.64.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:46b8b43ba6a2a8f3103f103f97996cad507bcfd72359af6516363c48793d5a7b"}, + {file = "grpcio-1.64.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a54362f03d4dcfae63be455d0a7d4c1403673498b92c6bfe22157d935b57c7a9"}, + {file = "grpcio-1.64.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1f8ea18b928e539046bb5f9c124d717fbf00cc4b2d960ae0b8468562846f5aa1"}, + {file = "grpcio-1.64.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c56c91bd2923ddb6e7ed28ebb66d15633b03e0df22206f22dfcdde08047e0a48"}, + {file = "grpcio-1.64.0-cp312-cp312-win32.whl", hash = "sha256:874c741c8a66f0834f653a69e7e64b4e67fcd4a8d40296919b93bab2ccc780ba"}, + {file = "grpcio-1.64.0-cp312-cp312-win_amd64.whl", hash = "sha256:0da1d921f8e4bcee307aeef6c7095eb26e617c471f8cb1c454fd389c5c296d1e"}, + {file = "grpcio-1.64.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:c46fb6bfca17bfc49f011eb53416e61472fa96caa0979b4329176bdd38cbbf2a"}, + {file = "grpcio-1.64.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3d2004e85cf5213995d09408501f82c8534700d2babeb81dfdba2a3bff0bb396"}, + {file = "grpcio-1.64.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:6d5541eb460d73a07418524fb64dcfe0adfbcd32e2dac0f8f90ce5b9dd6c046c"}, + {file = "grpcio-1.64.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f279ad72dd7d64412e10f2443f9f34872a938c67387863c4cd2fb837f53e7d2"}, + {file = "grpcio-1.64.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85fda90b81da25993aa47fae66cae747b921f8f6777550895fb62375b776a231"}, + {file = "grpcio-1.64.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a053584079b793a54bece4a7d1d1b5c0645bdbee729215cd433703dc2532f72b"}, + {file = "grpcio-1.64.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:579dd9fb11bc73f0de061cab5f8b2def21480fd99eb3743ed041ad6a1913ee2f"}, + {file = "grpcio-1.64.0-cp38-cp38-win32.whl", hash = "sha256:23b6887bb21d77649d022fa1859e05853fdc2e60682fd86c3db652a555a282e0"}, + {file = "grpcio-1.64.0-cp38-cp38-win_amd64.whl", hash = "sha256:753cb58683ba0c545306f4e17dabf468d29cb6f6b11832e1e432160bb3f8403c"}, + {file = "grpcio-1.64.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:2186d76a7e383e1466e0ea2b0febc343ffeae13928c63c6ec6826533c2d69590"}, + {file = "grpcio-1.64.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0f30596cdcbed3c98024fb4f1d91745146385b3f9fd10c9f2270cbfe2ed7ed91"}, + {file = "grpcio-1.64.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:d9171f025a196f5bcfec7e8e7ffb7c3535f7d60aecd3503f9e250296c7cfc150"}, + {file = "grpcio-1.64.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf4c8daed18ae2be2f1fc7d613a76ee2a2e28fdf2412d5c128be23144d28283d"}, + {file = "grpcio-1.64.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3550493ac1d23198d46dc9c9b24b411cef613798dc31160c7138568ec26bc9b4"}, + {file = "grpcio-1.64.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3161a8f8bb38077a6470508c1a7301cd54301c53b8a34bb83e3c9764874ecabd"}, + {file = "grpcio-1.64.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e8fabe2cc57a369638ab1ad8e6043721014fdf9a13baa7c0e35995d3a4a7618"}, + {file = "grpcio-1.64.0-cp39-cp39-win32.whl", hash = "sha256:31890b24d47b62cc27da49a462efe3d02f3c120edb0e6c46dcc0025506acf004"}, + {file = "grpcio-1.64.0-cp39-cp39-win_amd64.whl", hash = "sha256:5a56797dea8c02e7d3a85dfea879f286175cf4d14fbd9ab3ef2477277b927baa"}, + {file = "grpcio-1.64.0.tar.gz", hash = "sha256:257baf07f53a571c215eebe9679c3058a313fd1d1f7c4eede5a8660108c52d9c"}, +] + +[package.extras] +protobuf = ["grpcio-tools (>=1.64.0)"] + +[[package]] +name = "grpcio-status" +version = "1.62.2" +description = "Status proto mapping for gRPC" +optional = false +python-versions = ">=3.6" +files = [ + {file = "grpcio-status-1.62.2.tar.gz", hash = "sha256:62e1bfcb02025a1cd73732a2d33672d3e9d0df4d21c12c51e0bbcaf09bab742a"}, + {file = "grpcio_status-1.62.2-py3-none-any.whl", hash = "sha256:206ddf0eb36bc99b033f03b2c8e95d319f0044defae9b41ae21408e7e0cda48f"}, +] + +[package.dependencies] +googleapis-common-protos = ">=1.5.5" +grpcio = ">=1.62.2" +protobuf = ">=4.21.6" + [[package]] name = "h11" version = "0.14.0" @@ -750,13 +1068,13 @@ files = [ [[package]] name = "httpcore" -version = "1.0.2" +version = "1.0.5" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpcore-1.0.2-py3-none-any.whl", hash = "sha256:096cc05bca73b8e459a1fc3dcf585148f63e534eae4339559c9b8a8d6399acc7"}, - {file = "httpcore-1.0.2.tar.gz", hash = "sha256:9fc092e4799b26174648e54b74ed5f683132a464e95643b226e00c2ed2fa6535"}, + {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, + {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, ] [package.dependencies] @@ -767,17 +1085,65 @@ h11 = ">=0.13,<0.15" asyncio = ["anyio (>=4.0,<5.0)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<0.23.0)"] +trio = ["trio (>=0.22.0,<0.26.0)"] + +[[package]] +name = "httptools" +version = "0.6.1" +description = "A collection of framework independent HTTP protocol utils." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d2f6c3c4cb1948d912538217838f6e9960bc4a521d7f9b323b3da579cd14532f"}, + {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:00d5d4b68a717765b1fabfd9ca755bd12bf44105eeb806c03d1962acd9b8e563"}, + {file = "httptools-0.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:639dc4f381a870c9ec860ce5c45921db50205a37cc3334e756269736ff0aac58"}, + {file = "httptools-0.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e57997ac7fb7ee43140cc03664de5f268813a481dff6245e0075925adc6aa185"}, + {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0ac5a0ae3d9f4fe004318d64b8a854edd85ab76cffbf7ef5e32920faef62f142"}, + {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3f30d3ce413088a98b9db71c60a6ada2001a08945cb42dd65a9a9fe228627658"}, + {file = "httptools-0.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:1ed99a373e327f0107cb513b61820102ee4f3675656a37a50083eda05dc9541b"}, + {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7a7ea483c1a4485c71cb5f38be9db078f8b0e8b4c4dc0210f531cdd2ddac1ef1"}, + {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:85ed077c995e942b6f1b07583e4eb0a8d324d418954fc6af913d36db7c05a5a0"}, + {file = "httptools-0.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b0bb634338334385351a1600a73e558ce619af390c2b38386206ac6a27fecfc"}, + {file = "httptools-0.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d9ceb2c957320def533671fc9c715a80c47025139c8d1f3797477decbc6edd2"}, + {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4f0f8271c0a4db459f9dc807acd0eadd4839934a4b9b892f6f160e94da309837"}, + {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6a4f5ccead6d18ec072ac0b84420e95d27c1cdf5c9f1bc8fbd8daf86bd94f43d"}, + {file = "httptools-0.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:5cceac09f164bcba55c0500a18fe3c47df29b62353198e4f37bbcc5d591172c3"}, + {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:75c8022dca7935cba14741a42744eee13ba05db00b27a4b940f0d646bd4d56d0"}, + {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:48ed8129cd9a0d62cf4d1575fcf90fb37e3ff7d5654d3a5814eb3d55f36478c2"}, + {file = "httptools-0.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f58e335a1402fb5a650e271e8c2d03cfa7cea46ae124649346d17bd30d59c90"}, + {file = "httptools-0.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93ad80d7176aa5788902f207a4e79885f0576134695dfb0fefc15b7a4648d503"}, + {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9bb68d3a085c2174c2477eb3ffe84ae9fb4fde8792edb7bcd09a1d8467e30a84"}, + {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b512aa728bc02354e5ac086ce76c3ce635b62f5fbc32ab7082b5e582d27867bb"}, + {file = "httptools-0.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:97662ce7fb196c785344d00d638fc9ad69e18ee4bfb4000b35a52efe5adcc949"}, + {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8e216a038d2d52ea13fdd9b9c9c7459fb80d78302b257828285eca1c773b99b3"}, + {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3e802e0b2378ade99cd666b5bffb8b2a7cc8f3d28988685dc300469ea8dd86cb"}, + {file = "httptools-0.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bd3e488b447046e386a30f07af05f9b38d3d368d1f7b4d8f7e10af85393db97"}, + {file = "httptools-0.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe467eb086d80217b7584e61313ebadc8d187a4d95bb62031b7bab4b205c3ba3"}, + {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3c3b214ce057c54675b00108ac42bacf2ab8f85c58e3f324a4e963bbc46424f4"}, + {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8ae5b97f690badd2ca27cbf668494ee1b6d34cf1c464271ef7bfa9ca6b83ffaf"}, + {file = "httptools-0.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:405784577ba6540fa7d6ff49e37daf104e04f4b4ff2d1ac0469eaa6a20fde084"}, + {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:95fb92dd3649f9cb139e9c56604cc2d7c7bf0fc2e7c8d7fbd58f96e35eddd2a3"}, + {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dcbab042cc3ef272adc11220517278519adf8f53fd3056d0e68f0a6f891ba94e"}, + {file = "httptools-0.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf2372e98406efb42e93bfe10f2948e467edfd792b015f1b4ecd897903d3e8d"}, + {file = "httptools-0.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:678fcbae74477a17d103b7cae78b74800d795d702083867ce160fc202104d0da"}, + {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e0b281cf5a125c35f7f6722b65d8542d2e57331be573e9e88bc8b0115c4a7a81"}, + {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:95658c342529bba4e1d3d2b1a874db16c7cca435e8827422154c9da76ac4e13a"}, + {file = "httptools-0.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ebaec1bf683e4bf5e9fbb49b8cc36da482033596a415b3e4ebab5a4c0d7ec5e"}, + {file = "httptools-0.6.1.tar.gz", hash = "sha256:c6e26c30455600b95d94b1b836085138e82f177351454ee841c148f93a9bad5a"}, +] + +[package.extras] +test = ["Cython (>=0.29.24,<0.30.0)"] [[package]] name = "httpx" -version = "0.26.0" +version = "0.27.0" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpx-0.26.0-py3-none-any.whl", hash = "sha256:8915f5a3627c4d47b73e8202457cb28f1266982d1159bd5779d86a80c0eab1cd"}, - {file = "httpx-0.26.0.tar.gz", hash = "sha256:451b55c30d5185ea6b23c2c793abf9bb237d2a7dfb901ced6ff69ad37ec1dfaf"}, + {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, + {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, ] [package.dependencies] @@ -795,13 +1161,13 @@ socks = ["socksio (==1.*)"] [[package]] name = "huggingface-hub" -version = "0.20.3" +version = "0.23.2" description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" optional = false python-versions = ">=3.8.0" files = [ - {file = "huggingface_hub-0.20.3-py3-none-any.whl", hash = "sha256:d988ae4f00d3e307b0c80c6a05ca6dbb7edba8bba3079f74cda7d9c2e562a7b6"}, - {file = "huggingface_hub-0.20.3.tar.gz", hash = "sha256:94e7f8e074475fbc67d6a71957b678e1b4a74ff1b64a644fd6cbb83da962d05d"}, + {file = "huggingface_hub-0.23.2-py3-none-any.whl", hash = "sha256:48727a16e704d409c4bb5913613308499664f22a99743435dc3a13b23c485827"}, + {file = "huggingface_hub-0.23.2.tar.gz", hash = "sha256:f6829b62d5fdecb452a76fdbec620cba4c1573655a8d710c1df71735fd9edbd2"}, ] [package.dependencies] @@ -814,37 +1180,39 @@ tqdm = ">=4.42.1" typing-extensions = ">=3.7.4.3" [package.extras] -all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] cli = ["InquirerPy (==0.3.4)"] -dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"] -inference = ["aiohttp", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)"] -quality = ["mypy (==1.5.1)", "ruff (>=0.1.3)"] +hf-transfer = ["hf-transfer (>=0.1.4)"] +inference = ["aiohttp", "minijinja (>=1.0)"] +quality = ["mypy (==1.5.1)", "ruff (>=0.3.0)"] tensorflow = ["graphviz", "pydot", "tensorflow"] -testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] -torch = ["torch"] +tensorflow-testing = ["keras (<3.0)", "tensorflow"] +testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] +torch = ["safetensors", "torch"] typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"] [[package]] name = "idna" -version = "3.6" +version = "3.7" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ - {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, - {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, + {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, + {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, ] [[package]] name = "importlib-metadata" -version = "6.11.0" +version = "7.0.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-6.11.0-py3-none-any.whl", hash = "sha256:f0afba6205ad8f8947c7d338b5342d5db2afbfd82f9cbef7879a9539cc12eb9b"}, - {file = "importlib_metadata-6.11.0.tar.gz", hash = "sha256:1231cf92d825c9e03cfc4da076a16de6422c863558229ea0b22b675657463443"}, + {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"}, + {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"}, ] [package.dependencies] @@ -855,6 +1223,43 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.link perf = ["ipython"] testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] +[[package]] +name = "ipython" +version = "8.24.0" +description = "IPython: Productive Interactive Computing" +optional = false +python-versions = ">=3.10" +files = [ + {file = "ipython-8.24.0-py3-none-any.whl", hash = "sha256:d7bf2f6c4314984e3e02393213bab8703cf163ede39672ce5918c51fe253a2a3"}, + {file = "ipython-8.24.0.tar.gz", hash = "sha256:010db3f8a728a578bb641fdd06c063b9fb8e96a9464c63aec6310fbcb5e80501"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +decorator = "*" +jedi = ">=0.16" +matplotlib-inline = "*" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\""} +prompt-toolkit = ">=3.0.41,<3.1.0" +pygments = ">=2.4.0" +stack-data = "*" +traitlets = ">=5.13.0" +typing-extensions = {version = ">=4.6", markers = "python_version < \"3.12\""} + +[package.extras] +all = ["ipython[black,doc,kernel,matplotlib,nbconvert,nbformat,notebook,parallel,qtconsole]", "ipython[test,test-extra]"] +black = ["black"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "stack-data", "typing-extensions"] +kernel = ["ipykernel"] +matplotlib = ["matplotlib"] +nbconvert = ["nbconvert"] +nbformat = ["nbformat"] +notebook = ["ipywidgets", "notebook"] +parallel = ["ipyparallel"] +qtconsole = ["qtconsole"] +test = ["pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "ipython[test]", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "trio"] + [[package]] name = "janus" version = "1.0.0" @@ -869,15 +1274,34 @@ files = [ [package.dependencies] typing-extensions = ">=3.7.4.3" +[[package]] +name = "jedi" +version = "0.19.1" +description = "An autocompletion tool for Python that can be used for text editors." +optional = false +python-versions = ">=3.6" +files = [ + {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"}, + {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"}, +] + +[package.dependencies] +parso = ">=0.8.3,<0.9.0" + +[package.extras] +docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] + [[package]] name = "jinja2" -version = "3.1.3" +version = "3.1.4" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" files = [ - {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, - {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, ] [package.dependencies] @@ -886,190 +1310,452 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "jiter" +version = "0.4.0" +description = "Fast iterable JSON parser." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jiter-0.4.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:4aa6226d82a4a4505078c0bd5947bad65399635fc5cd4b226512e41753624edf"}, + {file = "jiter-0.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:947111ac906740a948e7b63799481acd3d5ef666ccb178d146e25718640b7408"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69572ffb4e84ae289a7422b9af4ea123cae2ce0772228859b37d4b26b4bc92ea"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ba6046cbb5d1baa5a781b846f7e5438596a332f249a857d63f86ef5d1d9563b0"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4f346e54602782e66d07df0d1c7389384fd93680052ed6170da2c6dc758409e"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:49110ce693f07e97d61089d894cea05a0b9894d5ccc6ac6fc583028726c8c8af"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e358df6fd129f3a4e087539f086355ad0107e5da16dbc8bc857d94222eaeed5"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7eb852ca39a48f3c049def56f0d1771b32e948e4f429a782d14ef4cc64cfd26e"}, + {file = "jiter-0.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:44dc045decb2545bffe2da04ea4c36d9438d3f3d49fc47ed423ea75c352b712e"}, + {file = "jiter-0.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:413adb15372ac63db04373240f40925788e4282c997eeafc2040530049a0a599"}, + {file = "jiter-0.4.0-cp310-none-win32.whl", hash = "sha256:0b48ea71673a97b897e4b94bbc871e62495a5a85f836c9f90712a4c70aa3ef7e"}, + {file = "jiter-0.4.0-cp310-none-win_amd64.whl", hash = "sha256:6a1c84b44afafaf0ba6223679cf17af664b889da14da31d8af3595fd977d96fa"}, + {file = "jiter-0.4.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b2cc498345fa37ca23fbc20271a553aa46e6eb00924600f49b7dc4b2aa8952ee"}, + {file = "jiter-0.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:69f7221ac09ab421abf04f89942026868297c568133998fb181bcf435760cbf3"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef7d01c52f3e5a56ae73af36bd13797dd1a56711eb522748e5e84d15425b3f10"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:39be97d5ce0c4d0dae28c23c03a0af0501a725589427e99763f99c42e18aa402"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eac2ed1ec1e577b92b7ea2d4e6de8aec0c1164defd8af8affdc8ec0f0ec2904a"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6258837d184c92c9cb91c983c310ad7269d41afb49d34f00ca9246e073943a03"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:123c2a77b066bf17a4d021e238e8351058cfa56b90ac04f2522d120dc64ea055"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2df939f792c7a40e55f36700417db551b9f6b84d348990fa0f2c608adeb1f11b"}, + {file = "jiter-0.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cb1b09b16d40cf9ba1d11ba11e5b96ad29286a6a1c4ad5e6a2aef5e352a89f5d"}, + {file = "jiter-0.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0efb4208889ebdbf933bf08dbcbc16e64ffd34c8e2b28044ee142789a9dc3a67"}, + {file = "jiter-0.4.0-cp311-none-win32.whl", hash = "sha256:20545ac1b68e7e5b066a1e8347840c9cebdd02ace65faae2e655fc02ec5c915c"}, + {file = "jiter-0.4.0-cp311-none-win_amd64.whl", hash = "sha256:6b300f9887c8e4431cd03a974ea3e4f9958885636003c3864220a9b2d2f8462b"}, + {file = "jiter-0.4.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:923432a0563bbae404ff25bb010e348514a69bfab979f2f8119b23b625dbf6d9"}, + {file = "jiter-0.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab8bb0ec8b97cec4422dc8b37b525442d969244488c805b834609ab0ccd788e2"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b857adb127b9c533907226791eafa79c5038c3eb5a477984994bf7c4715ba518"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2609cc0d1d8d470e921ff9a604afeb4c701bbe13e00bd9834d5aa6e7ea732a9b"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d39e99f8b7df46a119b6f84321f6ba01f16fa46abfa765d44c05c486d8e66829"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:56de8b518ebfe76a70f856741f6de248ce396c50a87acef827b6e8388e3a502d"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:488b7e777be47f67ce1a1f8f8eb907f9bbd81af5c03784a9bab09d025c250233"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7ea35e0ecbb5dadd457855eb980dcc548c14cf5341bcd22a43814cb56f2bcc79"}, + {file = "jiter-0.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e1a9e9ee69c80b63951c93226b68d0e955953f64fe758bad2afe7ef7f9016af9"}, + {file = "jiter-0.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:78e2f3cc2a32a21d43ccc5afcf66f5d17e827ccc4e6d21c0b353bdad2c7dcc9c"}, + {file = "jiter-0.4.0-cp312-none-win32.whl", hash = "sha256:eeaa7a2b47a99f4ebbb4142bb58b95617e09f24c87570f6a57d2770687c9ddbe"}, + {file = "jiter-0.4.0-cp312-none-win_amd64.whl", hash = "sha256:8d4a78b385b93ff59a67215d26000fcb4789a388fca3730d1b60fab17fc81e3c"}, + {file = "jiter-0.4.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:ebf20a3fac1089ce26963bf04140da0f803d55332ec69d59c5a87cf1a87d29c4"}, + {file = "jiter-0.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d62244ffc6a168187452277adeefb7b2c30170689c6bf543a51e98e8c17ddab7"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40b2cde77446a41cec595739fd168be87edff2428eaf7c3438231224dd0ab7a5"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e51fc0a22021ec8905b9b00a2f7d25756f2ff7a653e35a790a2067ae126b51f6"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a56e6f980b89d7cfe5c43811dcf52d6f37b319428a4540511235dafda9ea7808"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0fec16adab8d3d3d6d74e3711a1f380836ebeab2a20e3f88cfe2ec5094d8b84"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19e3de515801c954e8f1dc1f575282a4a86df9e782d4993ea1ed2be9a8dedaa0"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17e0ad8abf0bb04d81810eaeaab35d2c99b5da11fcd1058e0a389607ff6503b0"}, + {file = "jiter-0.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8dc0132b728f3b3e90ff0d1874504cd49c78f3553bf3745168a7fc0b4cf674e1"}, + {file = "jiter-0.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:81a883104aa96e494d3d28eaf7070780d03ecee8ccfdfaf7e4899710340c47f1"}, + {file = "jiter-0.4.0-cp38-none-win32.whl", hash = "sha256:a044c53ab1aaa4af624ac9574181b5bad8e260aea7e03104738156511433deba"}, + {file = "jiter-0.4.0-cp38-none-win_amd64.whl", hash = "sha256:d920035c869053e3d9a0b3ff94384d16a8ef5fde3dea55f97bd29916f6e27554"}, + {file = "jiter-0.4.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:091e978f4e586a2f1c69bf940d45f4e6a23455877172a0ab7d6de04a3b119299"}, + {file = "jiter-0.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:79134b2d601309bcbe3304a262d7d228ad61d53c80883231c637773000a6d683"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c471473e0b05058b5d729ff04271b6d45a575ac8bd9948563268c734b380ac7e"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb84b8930da8b32b0b1fdff9817e2c4b47e8981b5647ad11c4975403416e4112"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f2805e28941751ebfe0948596a64cde4cfb9b84bea5282affd020063e659c96"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:42ef59f9e513bf081a8b5c5578933ea9c3a63e559e6e3501a3e72edcd456ff5e"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ae12e3906f9e565120ab569de261b738e3a1ec50c40e30c67499e4f893e9a8c"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:264dc1324f45a793bc89af4f653225229eb17bca9ec7107dce6c8fb4fe68d20f"}, + {file = "jiter-0.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9a1c172ec47d846e25881dfbd52438ddb690da4ea04d185e477abd3db6c32f8a"}, + {file = "jiter-0.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ccde31d0bc114aedad0dbd71b7f63ba0f0eecd7ec9ae1926a0ca01c1eb2854e7"}, + {file = "jiter-0.4.0-cp39-none-win32.whl", hash = "sha256:13139b05792fbc13a0f9a5b4c89823ea0874141decae1b8f693f12bb1d28e061"}, + {file = "jiter-0.4.0-cp39-none-win_amd64.whl", hash = "sha256:3a729b2631c6d5551a41069697415fee9659c3eadc9ab87369376ba51930cd00"}, + {file = "jiter-0.4.0.tar.gz", hash = "sha256:68203e02e0419bc3eca717c580c2d8f615aeee1150e2a1fb68d6600a7e52a37c"}, +] + [[package]] name = "joblib" -version = "1.3.2" +version = "1.4.2" description = "Lightweight pipelining with Python functions" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "joblib-1.4.2-py3-none-any.whl", hash = "sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6"}, + {file = "joblib-1.4.2.tar.gz", hash = "sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e"}, +] + +[[package]] +name = "jsonpatch" +version = "1.33" +description = "Apply JSON-Patches (RFC 6902)" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +files = [ + {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, + {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"}, +] + +[package.dependencies] +jsonpointer = ">=1.9" + +[[package]] +name = "jsonpointer" +version = "2.4" +description = "Identify specific nodes in a JSON document (RFC 6901)" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +files = [ + {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, + {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, +] + +[[package]] +name = "jsonschema" +version = "4.22.0" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema-4.22.0-py3-none-any.whl", hash = "sha256:ff4cfd6b1367a40e7bc6411caec72effadd3db0bbe5017de188f2d6108335802"}, + {file = "jsonschema-4.22.0.tar.gz", hash = "sha256:5b22d434a45935119af990552c862e5d6d564e8f6601206b305a61fdf661a2b7"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] + +[[package]] +name = "jsonschema-specifications" +version = "2023.12.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +optional = false +python-versions = ">=3.8" files = [ - {file = "joblib-1.3.2-py3-none-any.whl", hash = "sha256:ef4331c65f239985f3f2220ecc87db222f08fd22097a3dd5698f693875f8cbb9"}, - {file = "joblib-1.3.2.tar.gz", hash = "sha256:92f865e621e17784e7955080b6d042489e3b8e294949cc44c6eac304f59772b1"}, + {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, + {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, ] +[package.dependencies] +referencing = ">=0.31.0" + [[package]] name = "langchain" -version = "0.0.198" +version = "0.2.1" description = "Building applications with LLMs through composability" optional = false -python-versions = ">=3.8.1,<4.0" +python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain-0.0.198-py3-none-any.whl", hash = "sha256:9d8e57ec25901989339ffac2ea7e759333d084100c90526e8ad57fb61b2003c9"}, - {file = "langchain-0.0.198.tar.gz", hash = "sha256:656385c23aeec1f8f4efbce598f729c817c60eb3f7c9fd77c03a8d28e7d0fa81"}, + {file = "langchain-0.2.1-py3-none-any.whl", hash = "sha256:3e13bf97c5717bce2c281f5117e8778823e8ccf62d949e73d3869448962b1c97"}, + {file = "langchain-0.2.1.tar.gz", hash = "sha256:5758a315e1ac92eb26dafec5ad0fafa03cafa686aba197d5bb0b1dd28cc03ebe"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" -async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""} -dataclasses-json = ">=0.5.7,<0.6.0" -langchainplus-sdk = ">=0.0.7" -numexpr = ">=2.8.4,<3.0.0" +langchain-core = ">=0.2.0,<0.3.0" +langchain-text-splitters = ">=0.2.0,<0.3.0" +langsmith = ">=0.1.17,<0.2.0" numpy = ">=1,<2" -openapi-schema-pydantic = ">=1.2,<2.0" -pydantic = ">=1,<2" -PyYAML = ">=5.4.1" +pydantic = ">=1,<3" +PyYAML = ">=5.3" requests = ">=2,<3" SQLAlchemy = ">=1.4,<3" tenacity = ">=8.1.0,<9.0.0" [package.extras] -all = ["O365 (>=2.0.26,<3.0.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.2.6,<0.3.0)", "arxiv (>=1.4,<2.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "awadb (>=0.3.2,<0.4.0)", "azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-vision (>=0.11.1b1,<0.12.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "beautifulsoup4 (>=4,<5)", "clickhouse-connect (>=0.5.14,<0.6.0)", "cohere (>=3,<4)", "deeplake (>=3.3.0,<4.0.0)", "docarray[hnswlib] (>=0.32.0,<0.33.0)", "duckduckgo-search (>=2.8.6,<3.0.0)", "elasticsearch (>=8,<9)", "faiss-cpu (>=1,<2)", "google-api-python-client (==2.70.0)", "google-auth (>=2.18.1,<3.0.0)", "google-search-results (>=2,<3)", "gptcache (>=0.1.7)", "html2text (>=2020.1.16,<2021.0.0)", "huggingface_hub (>=0,<1)", "jina (>=3.14,<4.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "lancedb (>=0.1,<0.2)", "langkit (>=0.0.1.dev3,<0.1.0)", "lark (>=1.1.5,<2.0.0)", "lxml (>=4.9.2,<5.0.0)", "manifest-ml (>=0.0.1,<0.0.2)", "momento (>=1.5.0,<2.0.0)", "nebula3-python (>=3.4.0,<4.0.0)", "neo4j (>=5.8.1,<6.0.0)", "networkx (>=2.6.3,<3.0.0)", "nlpcloud (>=1,<2)", "nltk (>=3,<4)", "nomic (>=1.0.43,<2.0.0)", "openai (>=0,<1)", "openlm (>=0.0.5,<0.0.6)", "opensearch-py (>=2.0.0,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pexpect (>=4.8.0,<5.0.0)", "pgvector (>=0.1.6,<0.2.0)", "pinecone-client (>=2,<3)", "pinecone-text (>=0.4.2,<0.5.0)", "psycopg2-binary (>=2.9.5,<3.0.0)", "pymongo (>=4.3.3,<5.0.0)", "pyowm (>=3.3.0,<4.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pytesseract (>=0.3.10,<0.4.0)", "pyvespa (>=0.33.0,<0.34.0)", "qdrant-client (>=1.1.2,<2.0.0)", "redis (>=4,<5)", "requests-toolbelt (>=1.0.0,<2.0.0)", "sentence-transformers (>=2,<3)", "singlestoredb (>=0.6.1,<0.7.0)", "spacy (>=3,<4)", "steamship (>=2.16.9,<3.0.0)", "tensorflow-text (>=2.11.0,<3.0.0)", "tigrisdb (>=1.0.0b6,<2.0.0)", "tiktoken (>=0.3.2,<0.4.0)", "torch (>=1,<3)", "transformers (>=4,<5)", "weaviate-client (>=3,<4)", "wikipedia (>=1,<2)", "wolframalpha (==5.0.0)"] -azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-vision (>=0.11.1b1,<0.12.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0a20230509004)", "openai (>=0,<1)"] -cohere = ["cohere (>=3,<4)"] +azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-textanalytics (>=5.3.0,<6.0.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b8)", "openai (<2)"] +clarifai = ["clarifai (>=9.1.0)"] +cli = ["typer (>=0.9.0,<0.10.0)"] +cohere = ["cohere (>=4,<6)"] docarray = ["docarray[hnswlib] (>=0.32.0,<0.33.0)"] embeddings = ["sentence-transformers (>=2,<3)"] -extended-testing = ["atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "chardet (>=5.1.0,<6.0.0)", "gql (>=3.4.1,<4.0.0)", "html2text (>=2020.1.16,<2021.0.0)", "jq (>=1.4.1,<2.0.0)", "lxml (>=4.9.2,<5.0.0)", "openai (>=0,<1)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "psychicapi (>=0.5,<0.6)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "telethon (>=1.28.5,<2.0.0)", "tqdm (>=4.48.0)", "zep-python (>=0.31)"] -llms = ["anthropic (>=0.2.6,<0.3.0)", "cohere (>=3,<4)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (>=0,<1)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] -openai = ["openai (>=0,<1)", "tiktoken (>=0.3.2,<0.4.0)"] -qdrant = ["qdrant-client (>=1.1.2,<2.0.0)"] +extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<6)", "couchbase (>=4.1.9,<5.0.0)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "langchain-openai (>=0.1,<0.2)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] +javascript = ["esprima (>=4.0.1,<5.0.0)"] +llms = ["clarifai (>=9.1.0)", "cohere (>=4,<6)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (<2)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] +openai = ["openai (<2)", "tiktoken (>=0.7,<1.0)"] +qdrant = ["qdrant-client (>=1.3.1,<2.0.0)"] text-helpers = ["chardet (>=5.1.0,<6.0.0)"] [[package]] -name = "langchainplus-sdk" -version = "0.0.20" -description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." +name = "langchain-community" +version = "0.2.1" +description = "Community contributed LangChain integrations." optional = false -python-versions = ">=3.8.1,<4.0" +python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchainplus_sdk-0.0.20-py3-none-any.whl", hash = "sha256:07a869d476755803aa04c4986ce78d00c2fe4ff584c0eaa57d7570c9664188db"}, - {file = "langchainplus_sdk-0.0.20.tar.gz", hash = "sha256:3d300e2e3290f68cc9d842c059f9458deba60e776c9e790309688cad1bfbb219"}, + {file = "langchain_community-0.2.1-py3-none-any.whl", hash = "sha256:b834e2c5ded6903b839fcaf566eee90a0ffae53405a0f7748202725e701d39cd"}, + {file = "langchain_community-0.2.1.tar.gz", hash = "sha256:079942e8f15da975769ccaae19042b7bba5481c42020bbbd7d8cad73a9393261"}, ] [package.dependencies] -pydantic = ">=1,<2" +aiohttp = ">=3.8.3,<4.0.0" +dataclasses-json = ">=0.5.7,<0.7" +langchain = ">=0.2.0,<0.3.0" +langchain-core = ">=0.2.0,<0.3.0" +langsmith = ">=0.1.0,<0.2.0" +numpy = ">=1,<2" +PyYAML = ">=5.3" requests = ">=2,<3" +SQLAlchemy = ">=1.4,<3" tenacity = ">=8.1.0,<9.0.0" +[package.extras] +cli = ["typer (>=0.9.0,<0.10.0)"] +extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "azure-identity (>=1.15.0,<2.0.0)", "azure-search-documents (==11.4.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.6,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cloudpathlib (>=0.18,<0.19)", "cloudpickle (>=2.0.0)", "cohere (>=4,<5)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "friendli-client (>=1.2.4,<2.0.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "httpx (>=0.24.1,<0.25.0)", "httpx-sse (>=0.4.0,<0.5.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "nvidia-riva-client (>=2.14.0,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "oracledb (>=2.2.0,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "premai (>=0.3.25,<0.4.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pyjwt (>=2.8.0,<3.0.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "tidb-vector (>=0.0.3,<1.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "tree-sitter (>=0.20.2,<0.21.0)", "tree-sitter-languages (>=1.8.0,<2.0.0)", "upstash-redis (>=0.15.0,<0.16.0)", "vdms (>=0.0.20,<0.0.21)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] + [[package]] -name = "markupsafe" -version = "2.1.4" -description = "Safely add untrusted strings to HTML/XML markup." +name = "langchain-core" +version = "0.2.3" +description = "Building applications with LLMs through composability" optional = false -python-versions = ">=3.7" +python-versions = "<4.0,>=3.8.1" files = [ - {file = "MarkupSafe-2.1.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de8153a7aae3835484ac168a9a9bdaa0c5eee4e0bc595503c95d53b942879c84"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e888ff76ceb39601c59e219f281466c6d7e66bd375b4ec1ce83bcdc68306796b"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0b838c37ba596fcbfca71651a104a611543077156cb0a26fe0c475e1f152ee8"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac1ebf6983148b45b5fa48593950f90ed6d1d26300604f321c74a9ca1609f8e"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0fbad3d346df8f9d72622ac71b69565e621ada2ce6572f37c2eae8dacd60385d"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5291d98cd3ad9a562883468c690a2a238c4a6388ab3bd155b0c75dd55ece858"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a7cc49ef48a3c7a0005a949f3c04f8baa5409d3f663a1b36f0eba9bfe2a0396e"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b83041cda633871572f0d3c41dddd5582ad7d22f65a72eacd8d3d6d00291df26"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-win32.whl", hash = "sha256:0c26f67b3fe27302d3a412b85ef696792c4a2386293c53ba683a89562f9399b0"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-win_amd64.whl", hash = "sha256:a76055d5cb1c23485d7ddae533229039b850db711c554a12ea64a0fd8a0129e2"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9e9e3c4020aa2dc62d5dd6743a69e399ce3de58320522948af6140ac959ab863"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0042d6a9880b38e1dd9ff83146cc3c9c18a059b9360ceae207805567aacccc69"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55d03fea4c4e9fd0ad75dc2e7e2b6757b80c152c032ea1d1de487461d8140efc"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ab3a886a237f6e9c9f4f7d272067e712cdb4efa774bef494dccad08f39d8ae6"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abf5ebbec056817057bfafc0445916bb688a255a5146f900445d081db08cbabb"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e1a0d1924a5013d4f294087e00024ad25668234569289650929ab871231668e7"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e7902211afd0af05fbadcc9a312e4cf10f27b779cf1323e78d52377ae4b72bea"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c669391319973e49a7c6230c218a1e3044710bc1ce4c8e6eb71f7e6d43a2c131"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-win32.whl", hash = "sha256:31f57d64c336b8ccb1966d156932f3daa4fee74176b0fdc48ef580be774aae74"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-win_amd64.whl", hash = "sha256:54a7e1380dfece8847c71bf7e33da5d084e9b889c75eca19100ef98027bd9f56"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:a76cd37d229fc385738bd1ce4cba2a121cf26b53864c1772694ad0ad348e509e"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:987d13fe1d23e12a66ca2073b8d2e2a75cec2ecb8eab43ff5624ba0ad42764bc"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5244324676254697fe5c181fc762284e2c5fceeb1c4e3e7f6aca2b6f107e60dc"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78bc995e004681246e85e28e068111a4c3f35f34e6c62da1471e844ee1446250"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4d176cfdfde84f732c4a53109b293d05883e952bbba68b857ae446fa3119b4f"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f9917691f410a2e0897d1ef99619fd3f7dd503647c8ff2475bf90c3cf222ad74"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f06e5a9e99b7df44640767842f414ed5d7bedaaa78cd817ce04bbd6fd86e2dd6"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:396549cea79e8ca4ba65525470d534e8a41070e6b3500ce2414921099cb73e8d"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-win32.whl", hash = "sha256:f6be2d708a9d0e9b0054856f07ac7070fbe1754be40ca8525d5adccdbda8f475"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-win_amd64.whl", hash = "sha256:5045e892cfdaecc5b4c01822f353cf2c8feb88a6ec1c0adef2a2e705eef0f656"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7a07f40ef8f0fbc5ef1000d0c78771f4d5ca03b4953fc162749772916b298fc4"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d18b66fe626ac412d96c2ab536306c736c66cf2a31c243a45025156cc190dc8a"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:698e84142f3f884114ea8cf83e7a67ca8f4ace8454e78fe960646c6c91c63bfa"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49a3b78a5af63ec10d8604180380c13dcd870aba7928c1fe04e881d5c792dc4e"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:15866d7f2dc60cfdde12ebb4e75e41be862348b4728300c36cdf405e258415ec"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6aa5e2e7fc9bc042ae82d8b79d795b9a62bd8f15ba1e7594e3db243f158b5565"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:54635102ba3cf5da26eb6f96c4b8c53af8a9c0d97b64bdcb592596a6255d8518"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-win32.whl", hash = "sha256:3583a3a3ab7958e354dc1d25be74aee6228938312ee875a22330c4dc2e41beb0"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-win_amd64.whl", hash = "sha256:d6e427c7378c7f1b2bef6a344c925b8b63623d3321c09a237b7cc0e77dd98ceb"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:bf1196dcc239e608605b716e7b166eb5faf4bc192f8a44b81e85251e62584bd2"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4df98d4a9cd6a88d6a585852f56f2155c9cdb6aec78361a19f938810aa020954"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b835aba863195269ea358cecc21b400276747cc977492319fd7682b8cd2c253d"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23984d1bdae01bee794267424af55eef4dfc038dc5d1272860669b2aa025c9e3"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c98c33ffe20e9a489145d97070a435ea0679fddaabcafe19982fe9c971987d5"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9896fca4a8eb246defc8b2a7ac77ef7553b638e04fbf170bff78a40fa8a91474"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b0fe73bac2fed83839dbdbe6da84ae2a31c11cfc1c777a40dbd8ac8a6ed1560f"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c7556bafeaa0a50e2fe7dc86e0382dea349ebcad8f010d5a7dc6ba568eaaa789"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-win32.whl", hash = "sha256:fc1a75aa8f11b87910ffd98de62b29d6520b6d6e8a3de69a70ca34dea85d2a8a"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-win_amd64.whl", hash = "sha256:3a66c36a3864df95e4f62f9167c734b3b1192cb0851b43d7cc08040c074c6279"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:765f036a3d00395a326df2835d8f86b637dbaf9832f90f5d196c3b8a7a5080cb"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:21e7af8091007bf4bebf4521184f4880a6acab8df0df52ef9e513d8e5db23411"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5c31fe855c77cad679b302aabc42d724ed87c043b1432d457f4976add1c2c3e"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7653fa39578957bc42e5ebc15cf4361d9e0ee4b702d7d5ec96cdac860953c5b4"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47bb5f0142b8b64ed1399b6b60f700a580335c8e1c57f2f15587bd072012decc"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fe8512ed897d5daf089e5bd010c3dc03bb1bdae00b35588c49b98268d4a01e00"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:36d7626a8cca4d34216875aee5a1d3d654bb3dac201c1c003d182283e3205949"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b6f14a9cd50c3cb100eb94b3273131c80d102e19bb20253ac7bd7336118a673a"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-win32.whl", hash = "sha256:c8f253a84dbd2c63c19590fa86a032ef3d8cc18923b8049d91bcdeeb2581fbf6"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-win_amd64.whl", hash = "sha256:8b570a1537367b52396e53325769608f2a687ec9a4363647af1cded8928af959"}, - {file = "MarkupSafe-2.1.4.tar.gz", hash = "sha256:3aae9af4cac263007fd6309c64c6ab4506dd2b79382d9d19a1994f9240b8db4f"}, + {file = "langchain_core-0.2.3-py3-none-any.whl", hash = "sha256:22189b5a3a30bfd65eb995f95e627f7c2c3acb322feb89f5f5f2fb7df21833a7"}, + {file = "langchain_core-0.2.3.tar.gz", hash = "sha256:fbc75a64b9c0b7655d96ca57a707df1e6c09efc1539c36adbd73260612549810"}, ] +[package.dependencies] +jsonpatch = ">=1.33,<2.0" +langsmith = ">=0.1.65,<0.2.0" +packaging = ">=23.2,<24.0" +pydantic = ">=1,<3" +PyYAML = ">=5.3" +tenacity = ">=8.1.0,<9.0.0" + +[package.extras] +extended-testing = ["jinja2 (>=3,<4)"] + [[package]] -name = "marshmallow" -version = "3.20.2" -description = "A lightweight library for converting complex datatypes to and from native Python datatypes." +name = "langchain-text-splitters" +version = "0.2.0" +description = "LangChain text splitting utilities" optional = false -python-versions = ">=3.8" +python-versions = "<4.0,>=3.8.1" files = [ - {file = "marshmallow-3.20.2-py3-none-any.whl", hash = "sha256:c21d4b98fee747c130e6bc8f45c4b3199ea66bc00c12ee1f639f0aeca034d5e9"}, - {file = "marshmallow-3.20.2.tar.gz", hash = "sha256:4c1daff273513dc5eb24b219a8035559dc573c8f322558ef85f5438ddd1236dd"}, + {file = "langchain_text_splitters-0.2.0-py3-none-any.whl", hash = "sha256:7b4c6a45f8471630a882b321e138329b6897102a5bc62f4c12be1c0b05bb9199"}, + {file = "langchain_text_splitters-0.2.0.tar.gz", hash = "sha256:b32ab4f7397f7d42c1fa3283fefc2547ba356bd63a68ee9092865e5ad83c82f9"}, ] [package.dependencies] -packaging = ">=17.0" +langchain-core = ">=0.2.0,<0.3.0" [package.extras] -dev = ["pre-commit (>=2.4,<4.0)", "pytest", "pytz", "simplejson", "tox"] -docs = ["alabaster (==0.7.15)", "autodocsumm (==0.2.12)", "sphinx (==7.2.6)", "sphinx-issues (==3.0.1)", "sphinx-version-warning (==1.1.2)"] -lint = ["pre-commit (>=2.4,<4.0)"] -tests = ["pytest", "pytz", "simplejson"] +extended-testing = ["beautifulsoup4 (>=4.12.3,<5.0.0)", "lxml (>=4.9.3,<6.0)"] [[package]] -name = "miniaudio" -version = "1.59" -description = "python bindings for the miniaudio library and its decoders (mp3, flac, ogg vorbis, wav)" +name = "langsmith" +version = "0.1.65" +description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = false -python-versions = "*" +python-versions = "<4.0,>=3.8.1" files = [ - {file = "miniaudio-1.59-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:028d7e8e6d99441340c0bfb60660db7bd5789cae7c95fa599d830344901d6d72"}, - {file = "miniaudio-1.59-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ba6f802376f49977e9698740411db46092ea005894ff86d805aeddde7e505c1e"}, - {file = "miniaudio-1.59-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9f24b44bd28ca631b830bc91bd910cb0209fba005401effa64cee9a8ba580992"}, - {file = "miniaudio-1.59-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8980dda51e92ea750ca8bcfb1d2c198eca7e4c844ab857faac12e20245322aa6"}, - {file = "miniaudio-1.59-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e21f56d51c627cef612d1a7bbc73fc7c5e03908f5ebc22c98494951ab8ccd3c8"}, - {file = "miniaudio-1.59-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1f6f1665ce8ed46caac48beec64c70e248a0b4e001590c698695cd22c1f634a0"}, - {file = "miniaudio-1.59-cp310-cp310-win32.whl", hash = "sha256:799b393adce56c8df1df16e7dc692a83125888df9ecf8ec0242c4905df6275ef"}, - {file = "miniaudio-1.59-cp310-cp310-win_amd64.whl", hash = "sha256:44c6b48f01d934784da282f7a17c40be9110ee6bc723f5f90916d2b2e729c9cc"}, - {file = "miniaudio-1.59-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2a9387e85e6a63d66a873f4208fbaba93179d11423da08dc83c78dd1b68ba504"}, - {file = "miniaudio-1.59-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:12fbbe3934856ab54fa8889ab6ec6b62a97faa2f85a8830e286fe5a4e9584ca4"}, - {file = "miniaudio-1.59-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4a9a1dc4352af4198f6ca0c20bac8b5b6a89d0d67e3535149ef08420a1ab3c9"}, - {file = "miniaudio-1.59-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4eb9eac3f23fd4c94925830fa9c172e98aebfb12cec1dbfa6a7693b9e4c1e555"}, - {file = "miniaudio-1.59-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:52882c36126c3a97fcdd8d753e4b1b07934bba9d4d3c431aa7f4914849090cac"}, - {file = "miniaudio-1.59-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d6bb6deee6d5969292d22730d31ee85ed0edc2997ca79978db0cca269ab73761"}, - {file = "miniaudio-1.59-cp311-cp311-win32.whl", hash = "sha256:6afe7449d7d593ba3f8bd91085a392d0c6ca3be4c03b62af37cb46f6c0c0d9f4"}, - {file = "miniaudio-1.59-cp311-cp311-win_amd64.whl", hash = "sha256:a22832e449a31620317ae657f7fd20a42466e5768c48373f8f28c53f2b36f5cd"}, - {file = "miniaudio-1.59-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fbfb3c853641c8bd835e0654f49fe0c09b4018b1ecc7e4c2436e02fbaf748c4b"}, - {file = "miniaudio-1.59-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:45ce3596c693053a578db725848a90ba0dfcc03d1d94124b9fddaa9e50a7533e"}, - {file = "miniaudio-1.59-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d07228047352b655a82711704a635eee41eb3977ceaaf672ee17d64a3ba261b7"}, - {file = "miniaudio-1.59-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:586f95f1d10f5d4f58b272c15c601c3ba13128bd34a839bce5bd28a839d5cf3c"}, - {file = "miniaudio-1.59-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7644f19b1dc00bca3ec9e6066eb8879c0e638091955092a1d7085a38d7de6e0f"}, - {file = "miniaudio-1.59-cp37-cp37m-win32.whl", hash = "sha256:055fb3a2e00ddcce2a2809cd2a3d5e68234588a00c70533fa4b68f0178829dce"}, - {file = "miniaudio-1.59-cp37-cp37m-win_amd64.whl", hash = "sha256:e1acea13830a53c026e58d44856ba4951a26eb0d0a2fda2ce6dc7280b6f57f81"}, - {file = "miniaudio-1.59-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7a8b6f1d4a2551061721cc7b22fb0eb3839aad9137553e01b4dde1a31c91ca45"}, + {file = "langsmith-0.1.65-py3-none-any.whl", hash = "sha256:ab4487029240e69cca30da1065f1e9138e5a7ca2bbe8c697f0bd7d5839f71cf7"}, + {file = "langsmith-0.1.65.tar.gz", hash = "sha256:d3c2eb2391478bd79989f02652cf66e29a7959d677614b6993a47cef43f7f43b"}, +] + +[package.dependencies] +orjson = ">=3.9.14,<4.0.0" +pydantic = ">=1,<3" +requests = ">=2,<3" + +[[package]] +name = "loguru" +version = "0.7.2" +description = "Python logging made (stupidly) simple" +optional = false +python-versions = ">=3.5" +files = [ + {file = "loguru-0.7.2-py3-none-any.whl", hash = "sha256:003d71e3d3ed35f0f8984898359d65b79e5b21943f78af86aa5491210429b8eb"}, + {file = "loguru-0.7.2.tar.gz", hash = "sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"}, +] + +[package.dependencies] +colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} +win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} + +[package.extras] +dev = ["Sphinx (==7.2.5)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.2.2)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.4.1)", "mypy (==v1.5.1)", "pre-commit (==3.4.0)", "pytest (==6.1.2)", "pytest (==7.4.0)", "pytest-cov (==2.12.1)", "pytest-cov (==4.1.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.0.0)", "sphinx-autobuild (==2021.3.14)", "sphinx-rtd-theme (==1.3.0)", "tox (==3.27.1)", "tox (==4.11.0)"] + +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.8" +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + +[[package]] +name = "markupsafe" +version = "2.1.5" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, +] + +[[package]] +name = "marshmallow" +version = "3.21.2" +description = "A lightweight library for converting complex datatypes to and from native Python datatypes." +optional = false +python-versions = ">=3.8" +files = [ + {file = "marshmallow-3.21.2-py3-none-any.whl", hash = "sha256:70b54a6282f4704d12c0a41599682c5c5450e843b9ec406308653b47c59648a1"}, + {file = "marshmallow-3.21.2.tar.gz", hash = "sha256:82408deadd8b33d56338d2182d455db632c6313aa2af61916672146bb32edc56"}, +] + +[package.dependencies] +packaging = ">=17.0" + +[package.extras] +dev = ["marshmallow[tests]", "pre-commit (>=3.5,<4.0)", "tox"] +docs = ["alabaster (==0.7.16)", "autodocsumm (==0.2.12)", "sphinx (==7.3.7)", "sphinx-issues (==4.1.0)", "sphinx-version-warning (==1.1.2)"] +tests = ["pytest", "pytz", "simplejson"] + +[[package]] +name = "matplotlib-inline" +version = "0.1.7" +description = "Inline Matplotlib backend for Jupyter" +optional = false +python-versions = ">=3.8" +files = [ + {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"}, + {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"}, +] + +[package.dependencies] +traitlets = "*" + +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + +[[package]] +name = "miniaudio" +version = "1.59" +description = "python bindings for the miniaudio library and its decoders (mp3, flac, ogg vorbis, wav)" +optional = false +python-versions = "*" +files = [ + {file = "miniaudio-1.59-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:028d7e8e6d99441340c0bfb60660db7bd5789cae7c95fa599d830344901d6d72"}, + {file = "miniaudio-1.59-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ba6f802376f49977e9698740411db46092ea005894ff86d805aeddde7e505c1e"}, + {file = "miniaudio-1.59-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9f24b44bd28ca631b830bc91bd910cb0209fba005401effa64cee9a8ba580992"}, + {file = "miniaudio-1.59-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8980dda51e92ea750ca8bcfb1d2c198eca7e4c844ab857faac12e20245322aa6"}, + {file = "miniaudio-1.59-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e21f56d51c627cef612d1a7bbc73fc7c5e03908f5ebc22c98494951ab8ccd3c8"}, + {file = "miniaudio-1.59-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1f6f1665ce8ed46caac48beec64c70e248a0b4e001590c698695cd22c1f634a0"}, + {file = "miniaudio-1.59-cp310-cp310-win32.whl", hash = "sha256:799b393adce56c8df1df16e7dc692a83125888df9ecf8ec0242c4905df6275ef"}, + {file = "miniaudio-1.59-cp310-cp310-win_amd64.whl", hash = "sha256:44c6b48f01d934784da282f7a17c40be9110ee6bc723f5f90916d2b2e729c9cc"}, + {file = "miniaudio-1.59-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2a9387e85e6a63d66a873f4208fbaba93179d11423da08dc83c78dd1b68ba504"}, + {file = "miniaudio-1.59-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:12fbbe3934856ab54fa8889ab6ec6b62a97faa2f85a8830e286fe5a4e9584ca4"}, + {file = "miniaudio-1.59-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4a9a1dc4352af4198f6ca0c20bac8b5b6a89d0d67e3535149ef08420a1ab3c9"}, + {file = "miniaudio-1.59-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4eb9eac3f23fd4c94925830fa9c172e98aebfb12cec1dbfa6a7693b9e4c1e555"}, + {file = "miniaudio-1.59-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:52882c36126c3a97fcdd8d753e4b1b07934bba9d4d3c431aa7f4914849090cac"}, + {file = "miniaudio-1.59-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d6bb6deee6d5969292d22730d31ee85ed0edc2997ca79978db0cca269ab73761"}, + {file = "miniaudio-1.59-cp311-cp311-win32.whl", hash = "sha256:6afe7449d7d593ba3f8bd91085a392d0c6ca3be4c03b62af37cb46f6c0c0d9f4"}, + {file = "miniaudio-1.59-cp311-cp311-win_amd64.whl", hash = "sha256:a22832e449a31620317ae657f7fd20a42466e5768c48373f8f28c53f2b36f5cd"}, + {file = "miniaudio-1.59-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fbfb3c853641c8bd835e0654f49fe0c09b4018b1ecc7e4c2436e02fbaf748c4b"}, + {file = "miniaudio-1.59-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:45ce3596c693053a578db725848a90ba0dfcc03d1d94124b9fddaa9e50a7533e"}, + {file = "miniaudio-1.59-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d07228047352b655a82711704a635eee41eb3977ceaaf672ee17d64a3ba261b7"}, + {file = "miniaudio-1.59-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:586f95f1d10f5d4f58b272c15c601c3ba13128bd34a839bce5bd28a839d5cf3c"}, + {file = "miniaudio-1.59-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7644f19b1dc00bca3ec9e6066eb8879c0e638091955092a1d7085a38d7de6e0f"}, + {file = "miniaudio-1.59-cp37-cp37m-win32.whl", hash = "sha256:055fb3a2e00ddcce2a2809cd2a3d5e68234588a00c70533fa4b68f0178829dce"}, + {file = "miniaudio-1.59-cp37-cp37m-win_amd64.whl", hash = "sha256:e1acea13830a53c026e58d44856ba4951a26eb0d0a2fda2ce6dc7280b6f57f81"}, + {file = "miniaudio-1.59-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7a8b6f1d4a2551061721cc7b22fb0eb3839aad9137553e01b4dde1a31c91ca45"}, {file = "miniaudio-1.59-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:011b2b8d5c57a485a6b86476e24c1c6be4a61ec8c33c456e3052929269857d0d"}, {file = "miniaudio-1.59-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9b270e9e1df5ec05d03659febffaa704709d7c9cb0b3597cb0a993875d73be84"}, {file = "miniaudio-1.59-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ab9d0468790109bafc88ce9d1c93454b2d384af0c14a6657620315115390c8d"}, @@ -1105,85 +1791,101 @@ cffi = ">=1.12.0" [[package]] name = "multidict" -version = "6.0.4" +version = "6.0.5" description = "multidict implementation" optional = false python-versions = ">=3.7" files = [ - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, - {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, - {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, - {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, - {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, - {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, - {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, - {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, - {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, - {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, - {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, - {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, - {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, + {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, + {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, + {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, + {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, + {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, + {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, + {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, + {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, + {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, + {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, + {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, + {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, + {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, + {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, + {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, ] [[package]] @@ -1222,168 +1924,169 @@ plot = ["matplotlib"] tgrep = ["pyparsing"] twitter = ["twython"] -[[package]] -name = "numexpr" -version = "2.8.8" -description = "Fast numerical expression evaluator for NumPy" -optional = false -python-versions = ">=3.9" -files = [ - {file = "numexpr-2.8.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:85c9f79e346c26aa0d425ecfc9e5de7184567d5e48d0bdb02d468bb927e92525"}, - {file = "numexpr-2.8.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dbac846f713b4c82333e6af0814ebea0b4e74dfb2649e76c58953fd4862322dd"}, - {file = "numexpr-2.8.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d7bfc8b77d8a7b04cd64ae42b62b3bf824a8c751ca235692bfd5231c6e90127"}, - {file = "numexpr-2.8.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:307b49fd15ef2ca292f381e67759e5b477410341f2f499a377234f1b42f529a6"}, - {file = "numexpr-2.8.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:aab17d65751c039d13ed9d49c9a7517b130ef488c1885c4666af9b5c6ad59520"}, - {file = "numexpr-2.8.8-cp310-cp310-win32.whl", hash = "sha256:6459dc6ed6abcdeab3cd3667c79f29e4a0f0a02c29ad71ee5cff065e880ee9ef"}, - {file = "numexpr-2.8.8-cp310-cp310-win_amd64.whl", hash = "sha256:22ccd67c0fbeae091f2c577f5b9c8046de6631d46b1cbe22aad46a08d2b42c2d"}, - {file = "numexpr-2.8.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:47c05007cd1c553515492c1a78b5477eaaba9cadc5d7b795d49f7aae53ccdf68"}, - {file = "numexpr-2.8.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b4649c1dcf9b0c2ae0a7b767dbbbde4e05ee68480c1ba7f06fc7963f1f73acf4"}, - {file = "numexpr-2.8.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a82d710145b0fbaec919dde9c90ed9df1e6785625cc36d1c71f3a53112b66fc5"}, - {file = "numexpr-2.8.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a92f230dd9d6c42803f855970e93677b44290b6dad15cb6796fd85edee171ce"}, - {file = "numexpr-2.8.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ccef9b09432d59229c2a737882e55de7906006452003323e107576f264cec373"}, - {file = "numexpr-2.8.8-cp311-cp311-win32.whl", hash = "sha256:bf8c517bbbb82c07c23c17f9d52b4c9f86601f57d48e87c0cbda24af5907f4dd"}, - {file = "numexpr-2.8.8-cp311-cp311-win_amd64.whl", hash = "sha256:4f01d71db6fdb97a68def5407e2dbd748eaea9d98929db08816de40aa4ae3084"}, - {file = "numexpr-2.8.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:76f0f010f9c6318bae213b21c5c0e381c2fc9c9ecb8b35f99f5030e7ac96c9ce"}, - {file = "numexpr-2.8.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3f168b4b42d4cb120fe1993676dcf74b77a3e8e45b58855566da037cfd938ca3"}, - {file = "numexpr-2.8.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f031ac4e70f9ad867543bfbde8452e9d1a14f0525346b4b8bd4e5c0f1380a11c"}, - {file = "numexpr-2.8.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:121b049b6909787111daf92919c052c4fd87b5691172e8f19f702b96f20aaafa"}, - {file = "numexpr-2.8.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2ae264c35fa67cd510191ab8144f131fddd0f1d13413af710913ea6fc0c6aa61"}, - {file = "numexpr-2.8.8-cp312-cp312-win32.whl", hash = "sha256:399cb914b41c4027ba88a18f6b8ccfc3af5c32bc3b1758403a7c44c72530618a"}, - {file = "numexpr-2.8.8-cp312-cp312-win_amd64.whl", hash = "sha256:925927cd1f610593e7783d8f2e12e3d800d5928601e077e4910e2b50bde624b6"}, - {file = "numexpr-2.8.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cd07793b074cc38e478637cbe738dff7d8eb92b5cf8ffaacff0c4f0bca5270a0"}, - {file = "numexpr-2.8.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:290f91c7ba7772abaf7107f3cc0601d93d6a3f21c13ee3da93f1b8a9ca3e8d39"}, - {file = "numexpr-2.8.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:296dc1f79d386166dec3bdb45f51caba29ffd8dc91db15447108c04d3001d921"}, - {file = "numexpr-2.8.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7badc50efbb2f1c8b78cd68089031e0fd29cbafa6a9e6d730533f22d88168406"}, - {file = "numexpr-2.8.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4d83a542d9deefb050e389aacaddea0f09d68ec617dd37e45b9a7cfbcba6d729"}, - {file = "numexpr-2.8.8-cp39-cp39-win32.whl", hash = "sha256:17104051f0bd83fd350212e268d8b48017d5eff522b09b573fdbcc560c5e7ab3"}, - {file = "numexpr-2.8.8-cp39-cp39-win_amd64.whl", hash = "sha256:12146521b1730073859a20454e75004e38cd0cb61333e763c58ef5171e101eb2"}, - {file = "numexpr-2.8.8.tar.gz", hash = "sha256:e76ce4d25372f46170cf7eb1ff14ed5d9c69a0b162a405063cbe481bafe3af34"}, -] - -[package.dependencies] -numpy = ">=1.13.3" - [[package]] name = "numpy" -version = "1.26.3" +version = "1.26.4" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.9" files = [ - {file = "numpy-1.26.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:806dd64230dbbfaca8a27faa64e2f414bf1c6622ab78cc4264f7f5f028fee3bf"}, - {file = "numpy-1.26.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02f98011ba4ab17f46f80f7f8f1c291ee7d855fcef0a5a98db80767a468c85cd"}, - {file = "numpy-1.26.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d45b3ec2faed4baca41c76617fcdcfa4f684ff7a151ce6fc78ad3b6e85af0a6"}, - {file = "numpy-1.26.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdd2b45bf079d9ad90377048e2747a0c82351989a2165821f0c96831b4a2a54b"}, - {file = "numpy-1.26.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:211ddd1e94817ed2d175b60b6374120244a4dd2287f4ece45d49228b4d529178"}, - {file = "numpy-1.26.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b1240f767f69d7c4c8a29adde2310b871153df9b26b5cb2b54a561ac85146485"}, - {file = "numpy-1.26.3-cp310-cp310-win32.whl", hash = "sha256:21a9484e75ad018974a2fdaa216524d64ed4212e418e0a551a2d83403b0531d3"}, - {file = "numpy-1.26.3-cp310-cp310-win_amd64.whl", hash = "sha256:9e1591f6ae98bcfac2a4bbf9221c0b92ab49762228f38287f6eeb5f3f55905ce"}, - {file = "numpy-1.26.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b831295e5472954104ecb46cd98c08b98b49c69fdb7040483aff799a755a7374"}, - {file = "numpy-1.26.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9e87562b91f68dd8b1c39149d0323b42e0082db7ddb8e934ab4c292094d575d6"}, - {file = "numpy-1.26.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c66d6fec467e8c0f975818c1796d25c53521124b7cfb760114be0abad53a0a2"}, - {file = "numpy-1.26.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f25e2811a9c932e43943a2615e65fc487a0b6b49218899e62e426e7f0a57eeda"}, - {file = "numpy-1.26.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:af36e0aa45e25c9f57bf684b1175e59ea05d9a7d3e8e87b7ae1a1da246f2767e"}, - {file = "numpy-1.26.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:51c7f1b344f302067b02e0f5b5d2daa9ed4a721cf49f070280ac202738ea7f00"}, - {file = "numpy-1.26.3-cp311-cp311-win32.whl", hash = "sha256:7ca4f24341df071877849eb2034948459ce3a07915c2734f1abb4018d9c49d7b"}, - {file = "numpy-1.26.3-cp311-cp311-win_amd64.whl", hash = "sha256:39763aee6dfdd4878032361b30b2b12593fb445ddb66bbac802e2113eb8a6ac4"}, - {file = "numpy-1.26.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a7081fd19a6d573e1a05e600c82a1c421011db7935ed0d5c483e9dd96b99cf13"}, - {file = "numpy-1.26.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12c70ac274b32bc00c7f61b515126c9205323703abb99cd41836e8125ea0043e"}, - {file = "numpy-1.26.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f784e13e598e9594750b2ef6729bcd5a47f6cfe4a12cca13def35e06d8163e3"}, - {file = "numpy-1.26.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f24750ef94d56ce6e33e4019a8a4d68cfdb1ef661a52cdaee628a56d2437419"}, - {file = "numpy-1.26.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:77810ef29e0fb1d289d225cabb9ee6cf4d11978a00bb99f7f8ec2132a84e0166"}, - {file = "numpy-1.26.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8ed07a90f5450d99dad60d3799f9c03c6566709bd53b497eb9ccad9a55867f36"}, - {file = "numpy-1.26.3-cp312-cp312-win32.whl", hash = "sha256:f73497e8c38295aaa4741bdfa4fda1a5aedda5473074369eca10626835445511"}, - {file = "numpy-1.26.3-cp312-cp312-win_amd64.whl", hash = "sha256:da4b0c6c699a0ad73c810736303f7fbae483bcb012e38d7eb06a5e3b432c981b"}, - {file = "numpy-1.26.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1666f634cb3c80ccbd77ec97bc17337718f56d6658acf5d3b906ca03e90ce87f"}, - {file = "numpy-1.26.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18c3319a7d39b2c6a9e3bb75aab2304ab79a811ac0168a671a62e6346c29b03f"}, - {file = "numpy-1.26.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b7e807d6888da0db6e7e75838444d62495e2b588b99e90dd80c3459594e857b"}, - {file = "numpy-1.26.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4d362e17bcb0011738c2d83e0a65ea8ce627057b2fdda37678f4374a382a137"}, - {file = "numpy-1.26.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b8c275f0ae90069496068c714387b4a0eba5d531aace269559ff2b43655edd58"}, - {file = "numpy-1.26.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cc0743f0302b94f397a4a65a660d4cd24267439eb16493fb3caad2e4389bccbb"}, - {file = "numpy-1.26.3-cp39-cp39-win32.whl", hash = "sha256:9bc6d1a7f8cedd519c4b7b1156d98e051b726bf160715b769106661d567b3f03"}, - {file = "numpy-1.26.3-cp39-cp39-win_amd64.whl", hash = "sha256:867e3644e208c8922a3be26fc6bbf112a035f50f0a86497f98f228c50c607bb2"}, - {file = "numpy-1.26.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3c67423b3703f8fbd90f5adaa37f85b5794d3366948efe9a5190a5f3a83fc34e"}, - {file = "numpy-1.26.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46f47ee566d98849323f01b349d58f2557f02167ee301e5e28809a8c0e27a2d0"}, - {file = "numpy-1.26.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a8474703bffc65ca15853d5fd4d06b18138ae90c17c8d12169968e998e448bb5"}, - {file = "numpy-1.26.3.tar.gz", hash = "sha256:697df43e2b6310ecc9d95f05d5ef20eacc09c7c4ecc9da3f235d39e71b7da1e4"}, + {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, + {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, + {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, + {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, + {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, + {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, + {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, + {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, + {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, + {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, + {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, ] [[package]] name = "openai" -version = "0.27.10" -description = "Python client library for the OpenAI API" +version = "1.30.5" +description = "The official Python library for the openai API" optional = false python-versions = ">=3.7.1" files = [ - {file = "openai-0.27.10-py3-none-any.whl", hash = "sha256:beabd1757e3286fa166dde3b70ebb5ad8081af046876b47c14c41e203ed22a14"}, - {file = "openai-0.27.10.tar.gz", hash = "sha256:60e09edf7100080283688748c6803b7b3b52d5a55d21890f3815292a0552d83b"}, + {file = "openai-1.30.5-py3-none-any.whl", hash = "sha256:2ad95e926de0d2e09cde632a9204b0a6dca4a03c2cdcc84329b01f355784355a"}, + {file = "openai-1.30.5.tar.gz", hash = "sha256:5366562eb2c5917e6116ae0391b7ae6e3acd62b0ae3f565ada32b35d8fcfa106"}, ] [package.dependencies] -aiohttp = "*" -requests = ">=2.20" -tqdm = "*" +anyio = ">=3.5.0,<5" +distro = ">=1.7.0,<2" +httpx = ">=0.23.0,<1" +pydantic = ">=1.9.0,<3" +sniffio = "*" +tqdm = ">4" +typing-extensions = ">=4.7,<5" [package.extras] -datalib = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] -dev = ["black (>=21.6b0,<22.0)", "pytest (==6.*)", "pytest-asyncio", "pytest-mock"] -embeddings = ["matplotlib", "numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "plotly", "scikit-learn (>=1.0.2)", "scipy", "tenacity (>=8.0.1)"] -wandb = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "wandb"] - -[[package]] -name = "openapi-schema-pydantic" -version = "1.2.4" -description = "OpenAPI (v3) specification schema as pydantic class" -optional = false -python-versions = ">=3.6.1" -files = [ - {file = "openapi-schema-pydantic-1.2.4.tar.gz", hash = "sha256:3e22cf58b74a69f752cc7e5f1537f6e44164282db2700cbbcd3bb99ddd065196"}, - {file = "openapi_schema_pydantic-1.2.4-py3-none-any.whl", hash = "sha256:a932ecc5dcbb308950282088956e94dea069c9823c84e507d64f6b622222098c"}, -] - -[package.dependencies] -pydantic = ">=1.8.2" +datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] [[package]] name = "opentelemetry-api" -version = "1.22.0" +version = "1.24.0" description = "OpenTelemetry Python API" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "opentelemetry_api-1.22.0-py3-none-any.whl", hash = "sha256:43621514301a7e9f5d06dd8013a1b450f30c2e9372b8e30aaeb4562abf2ce034"}, - {file = "opentelemetry_api-1.22.0.tar.gz", hash = "sha256:15ae4ca925ecf9cfdfb7a709250846fbb08072260fca08ade78056c502b86bed"}, + {file = "opentelemetry_api-1.24.0-py3-none-any.whl", hash = "sha256:0f2c363d98d10d1ce93330015ca7fd3a65f60be64e05e30f557c61de52c80ca2"}, + {file = "opentelemetry_api-1.24.0.tar.gz", hash = "sha256:42719f10ce7b5a9a73b10a4baf620574fb8ad495a9cbe5c18d76b75d8689c67e"}, ] [package.dependencies] deprecated = ">=1.2.6" -importlib-metadata = ">=6.0,<7.0" +importlib-metadata = ">=6.0,<=7.0" [[package]] name = "opentelemetry-sdk" -version = "1.22.0" +version = "1.24.0" description = "OpenTelemetry Python SDK" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "opentelemetry_sdk-1.22.0-py3-none-any.whl", hash = "sha256:a730555713d7c8931657612a88a141e3a4fe6eb5523d9e2d5a8b1e673d76efa6"}, - {file = "opentelemetry_sdk-1.22.0.tar.gz", hash = "sha256:45267ac1f38a431fc2eb5d6e0c0d83afc0b78de57ac345488aa58c28c17991d0"}, + {file = "opentelemetry_sdk-1.24.0-py3-none-any.whl", hash = "sha256:fa731e24efe832e98bcd90902085b359dcfef7d9c9c00eb5b9a18587dae3eb59"}, + {file = "opentelemetry_sdk-1.24.0.tar.gz", hash = "sha256:75bc0563affffa827700e0f4f4a68e1e257db0df13372344aebc6f8a64cde2e5"}, ] [package.dependencies] -opentelemetry-api = "1.22.0" -opentelemetry-semantic-conventions = "0.43b0" +opentelemetry-api = "1.24.0" +opentelemetry-semantic-conventions = "0.45b0" typing-extensions = ">=3.7.4" [[package]] name = "opentelemetry-semantic-conventions" -version = "0.43b0" +version = "0.45b0" description = "OpenTelemetry Semantic Conventions" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_semantic_conventions-0.45b0-py3-none-any.whl", hash = "sha256:a4a6fb9a7bacd9167c082aa4681009e9acdbfa28ffb2387af50c2fef3d30c864"}, + {file = "opentelemetry_semantic_conventions-0.45b0.tar.gz", hash = "sha256:7c84215a44ac846bc4b8e32d5e78935c5c43482e491812a0bb8aaf87e4d92118"}, +] + +[[package]] +name = "orjson" +version = "3.10.3" +description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" +optional = false +python-versions = ">=3.8" files = [ - {file = "opentelemetry_semantic_conventions-0.43b0-py3-none-any.whl", hash = "sha256:291284d7c1bf15fdaddf309b3bd6d3b7ce12a253cec6d27144439819a15d8445"}, - {file = "opentelemetry_semantic_conventions-0.43b0.tar.gz", hash = "sha256:b9576fb890df479626fa624e88dde42d3d60b8b6c8ae1152ad157a8b97358635"}, + {file = "orjson-3.10.3-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9fb6c3f9f5490a3eb4ddd46fc1b6eadb0d6fc16fb3f07320149c3286a1409dd8"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:252124b198662eee80428f1af8c63f7ff077c88723fe206a25df8dc57a57b1fa"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f3e87733823089a338ef9bbf363ef4de45e5c599a9bf50a7a9b82e86d0228da"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8334c0d87103bb9fbbe59b78129f1f40d1d1e8355bbed2ca71853af15fa4ed3"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1952c03439e4dce23482ac846e7961f9d4ec62086eb98ae76d97bd41d72644d7"}, + {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c0403ed9c706dcd2809f1600ed18f4aae50be263bd7112e54b50e2c2bc3ebd6d"}, + {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:382e52aa4270a037d41f325e7d1dfa395b7de0c367800b6f337d8157367bf3a7"}, + {file = "orjson-3.10.3-cp310-none-win32.whl", hash = "sha256:be2aab54313752c04f2cbaab4515291ef5af8c2256ce22abc007f89f42f49109"}, + {file = "orjson-3.10.3-cp310-none-win_amd64.whl", hash = "sha256:416b195f78ae461601893f482287cee1e3059ec49b4f99479aedf22a20b1098b"}, + {file = "orjson-3.10.3-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:73100d9abbbe730331f2242c1fc0bcb46a3ea3b4ae3348847e5a141265479700"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a12eee96e3ab828dbfcb4d5a0023aa971b27143a1d35dc214c176fdfb29b3"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520de5e2ef0b4ae546bea25129d6c7c74edb43fc6cf5213f511a927f2b28148b"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccaa0a401fc02e8828a5bedfd80f8cd389d24f65e5ca3954d72c6582495b4bcf"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7bc9e8bc11bac40f905640acd41cbeaa87209e7e1f57ade386da658092dc16"}, + {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3582b34b70543a1ed6944aca75e219e1192661a63da4d039d088a09c67543b08"}, + {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c23dfa91481de880890d17aa7b91d586a4746a4c2aa9a145bebdbaf233768d5"}, + {file = "orjson-3.10.3-cp311-none-win32.whl", hash = "sha256:1770e2a0eae728b050705206d84eda8b074b65ee835e7f85c919f5705b006c9b"}, + {file = "orjson-3.10.3-cp311-none-win_amd64.whl", hash = "sha256:93433b3c1f852660eb5abdc1f4dd0ced2be031ba30900433223b28ee0140cde5"}, + {file = "orjson-3.10.3-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a39aa73e53bec8d410875683bfa3a8edf61e5a1c7bb4014f65f81d36467ea098"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0943a96b3fa09bee1afdfccc2cb236c9c64715afa375b2af296c73d91c23eab2"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e852baafceff8da3c9defae29414cc8513a1586ad93e45f27b89a639c68e8176"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18566beb5acd76f3769c1d1a7ec06cdb81edc4d55d2765fb677e3eaa10fa99e0"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd2218d5a3aa43060efe649ec564ebedec8ce6ae0a43654b81376216d5ebd42"}, + {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cf20465e74c6e17a104ecf01bf8cd3b7b252565b4ccee4548f18b012ff2f8069"}, + {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba7f67aa7f983c4345eeda16054a4677289011a478ca947cd69c0a86ea45e534"}, + {file = "orjson-3.10.3-cp312-none-win32.whl", hash = "sha256:17e0713fc159abc261eea0f4feda611d32eabc35708b74bef6ad44f6c78d5ea0"}, + {file = "orjson-3.10.3-cp312-none-win_amd64.whl", hash = "sha256:4c895383b1ec42b017dd2c75ae8a5b862fc489006afde06f14afbdd0309b2af0"}, + {file = "orjson-3.10.3-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:be2719e5041e9fb76c8c2c06b9600fe8e8584e6980061ff88dcbc2691a16d20d"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0175a5798bdc878956099f5c54b9837cb62cfbf5d0b86ba6d77e43861bcec2"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:978be58a68ade24f1af7758626806e13cff7748a677faf95fbb298359aa1e20d"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16bda83b5c61586f6f788333d3cf3ed19015e3b9019188c56983b5a299210eb5"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ad1f26bea425041e0a1adad34630c4825a9e3adec49079b1fb6ac8d36f8b754"}, + {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9e253498bee561fe85d6325ba55ff2ff08fb5e7184cd6a4d7754133bd19c9195"}, + {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0a62f9968bab8a676a164263e485f30a0b748255ee2f4ae49a0224be95f4532b"}, + {file = "orjson-3.10.3-cp38-none-win32.whl", hash = "sha256:8d0b84403d287d4bfa9bf7d1dc298d5c1c5d9f444f3737929a66f2fe4fb8f134"}, + {file = "orjson-3.10.3-cp38-none-win_amd64.whl", hash = "sha256:8bc7a4df90da5d535e18157220d7915780d07198b54f4de0110eca6b6c11e290"}, + {file = "orjson-3.10.3-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9059d15c30e675a58fdcd6f95465c1522b8426e092de9fff20edebfdc15e1cb0"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d40c7f7938c9c2b934b297412c067936d0b54e4b8ab916fd1a9eb8f54c02294"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4a654ec1de8fdaae1d80d55cee65893cb06494e124681ab335218be6a0691e7"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:831c6ef73f9aa53c5f40ae8f949ff7681b38eaddb6904aab89dca4d85099cb78"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99b880d7e34542db89f48d14ddecbd26f06838b12427d5a25d71baceb5ba119d"}, + {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e5e176c994ce4bd434d7aafb9ecc893c15f347d3d2bbd8e7ce0b63071c52e25"}, + {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b69a58a37dab856491bf2d3bbf259775fdce262b727f96aafbda359cb1d114d8"}, + {file = "orjson-3.10.3-cp39-none-win32.whl", hash = "sha256:b8d4d1a6868cde356f1402c8faeb50d62cee765a1f7ffcfd6de732ab0581e063"}, + {file = "orjson-3.10.3-cp39-none-win_amd64.whl", hash = "sha256:5102f50c5fc46d94f2033fe00d392588564378260d64377aec702f21a7a22912"}, + {file = "orjson-3.10.3.tar.gz", hash = "sha256:2b166507acae7ba2f7c315dcf185a9111ad5e992ac81f2d507aac39193c2c818"}, ] [[package]] @@ -1397,68 +2100,278 @@ files = [ {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] +[[package]] +name = "parso" +version = "0.8.4" +description = "A Python Parser" +optional = false +python-versions = ">=3.6" +files = [ + {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, + {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"}, +] + +[package.extras] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["docopt", "pytest"] + +[[package]] +name = "pexpect" +version = "4.9.0" +description = "Pexpect allows easy control of interactive console applications." +optional = false +python-versions = "*" +files = [ + {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, + {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, +] + +[package.dependencies] +ptyprocess = ">=0.5" + +[[package]] +name = "phonenumbers" +version = "8.13.37" +description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers." +optional = false +python-versions = "*" +files = [ + {file = "phonenumbers-8.13.37-py2.py3-none-any.whl", hash = "sha256:4ea00ef5012422c08c7955c21131e7ae5baa9a3ef52cf2d561e963f023006b80"}, + {file = "phonenumbers-8.13.37.tar.gz", hash = "sha256:bd315fed159aea0516f7c367231810fe8344d5bec26156b88fa18374c11d1cf2"}, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.45" +description = "Library for building powerful interactive command lines in Python" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "prompt_toolkit-3.0.45-py3-none-any.whl", hash = "sha256:a29b89160e494e3ea8622b09fa5897610b437884dcdcd054fdc1308883326c2a"}, + {file = "prompt_toolkit-3.0.45.tar.gz", hash = "sha256:07c60ee4ab7b7e90824b61afa840c8f5aad2d46b3e2e10acc33d8ecc94a49089"}, +] + +[package.dependencies] +wcwidth = "*" + +[[package]] +name = "proto-plus" +version = "1.23.0" +description = "Beautiful, Pythonic protocol buffers." +optional = false +python-versions = ">=3.6" +files = [ + {file = "proto-plus-1.23.0.tar.gz", hash = "sha256:89075171ef11988b3fa157f5dbd8b9cf09d65fffee97e29ce403cd8defba19d2"}, + {file = "proto_plus-1.23.0-py3-none-any.whl", hash = "sha256:a829c79e619e1cf632de091013a4173deed13a55f326ef84f05af6f50ff4c82c"}, +] + +[package.dependencies] +protobuf = ">=3.19.0,<5.0.0dev" + +[package.extras] +testing = ["google-api-core[grpc] (>=1.31.5)"] + +[[package]] +name = "protobuf" +version = "4.25.3" +description = "" +optional = false +python-versions = ">=3.8" +files = [ + {file = "protobuf-4.25.3-cp310-abi3-win32.whl", hash = "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa"}, + {file = "protobuf-4.25.3-cp310-abi3-win_amd64.whl", hash = "sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8"}, + {file = "protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c"}, + {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019"}, + {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d"}, + {file = "protobuf-4.25.3-cp38-cp38-win32.whl", hash = "sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2"}, + {file = "protobuf-4.25.3-cp38-cp38-win_amd64.whl", hash = "sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4"}, + {file = "protobuf-4.25.3-cp39-cp39-win32.whl", hash = "sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4"}, + {file = "protobuf-4.25.3-cp39-cp39-win_amd64.whl", hash = "sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c"}, + {file = "protobuf-4.25.3-py3-none-any.whl", hash = "sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9"}, + {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, +] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +description = "Run a subprocess in a pseudo terminal" +optional = false +python-versions = "*" +files = [ + {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, + {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, +] + +[[package]] +name = "pure-eval" +version = "0.2.2" +description = "Safely evaluate AST nodes without side effects" +optional = false +python-versions = "*" +files = [ + {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, + {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, +] + +[package.extras] +tests = ["pytest"] + +[[package]] +name = "pvkoala" +version = "2.0.1" +description = "Koala Noise Suppression Engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pvkoala-2.0.1-py3-none-any.whl", hash = "sha256:8b153e076b4d14adccdcb4d800aa84e8d2f91e0640b959677582d3128cbcb249"}, + {file = "pvkoala-2.0.1.tar.gz", hash = "sha256:5e017c671fc1338d42dc20f9dee003d0144bbba1757b6f1fcd6272c5308da242"}, +] + +[[package]] +name = "pyasn1" +version = "0.6.0" +description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyasn1-0.6.0-py2.py3-none-any.whl", hash = "sha256:cca4bb0f2df5504f02f6f8a775b6e416ff9b0b3b16f7ee80b5a3153d9b804473"}, + {file = "pyasn1-0.6.0.tar.gz", hash = "sha256:3a35ab2c4b5ef98e17dfdec8ab074046fbda76e281c5a706ccd82328cfc8f64c"}, +] + +[[package]] +name = "pyasn1-modules" +version = "0.4.0" +description = "A collection of ASN.1-based protocols modules" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyasn1_modules-0.4.0-py3-none-any.whl", hash = "sha256:be04f15b66c206eed667e0bb5ab27e2b1855ea54a842e5037738099e8ca4ae0b"}, + {file = "pyasn1_modules-0.4.0.tar.gz", hash = "sha256:831dbcea1b177b28c9baddf4c6d1013c24c3accd14a1873fffaa6a2e905f17b6"}, +] + +[package.dependencies] +pyasn1 = ">=0.4.6,<0.7.0" + [[package]] name = "pycparser" -version = "2.21" +version = "2.22" description = "C parser in Python" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.8" files = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, ] [[package]] name = "pydantic" -version = "1.10.14" -description = "Data validation and settings management using python type hints" +version = "2.7.2" +description = "Data validation using Python type hints" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pydantic-1.10.14-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7f4fcec873f90537c382840f330b90f4715eebc2bc9925f04cb92de593eae054"}, - {file = "pydantic-1.10.14-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e3a76f571970fcd3c43ad982daf936ae39b3e90b8a2e96c04113a369869dc87"}, - {file = "pydantic-1.10.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d886bd3c3fbeaa963692ef6b643159ccb4b4cefaf7ff1617720cbead04fd1d"}, - {file = "pydantic-1.10.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:798a3d05ee3b71967844a1164fd5bdb8c22c6d674f26274e78b9f29d81770c4e"}, - {file = "pydantic-1.10.14-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:23d47a4b57a38e8652bcab15a658fdb13c785b9ce217cc3a729504ab4e1d6bc9"}, - {file = "pydantic-1.10.14-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f9f674b5c3bebc2eba401de64f29948ae1e646ba2735f884d1594c5f675d6f2a"}, - {file = "pydantic-1.10.14-cp310-cp310-win_amd64.whl", hash = "sha256:24a7679fab2e0eeedb5a8924fc4a694b3bcaac7d305aeeac72dd7d4e05ecbebf"}, - {file = "pydantic-1.10.14-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9d578ac4bf7fdf10ce14caba6f734c178379bd35c486c6deb6f49006e1ba78a7"}, - {file = "pydantic-1.10.14-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa7790e94c60f809c95602a26d906eba01a0abee9cc24150e4ce2189352deb1b"}, - {file = "pydantic-1.10.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aad4e10efa5474ed1a611b6d7f0d130f4aafadceb73c11d9e72823e8f508e663"}, - {file = "pydantic-1.10.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1245f4f61f467cb3dfeced2b119afef3db386aec3d24a22a1de08c65038b255f"}, - {file = "pydantic-1.10.14-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:21efacc678a11114c765eb52ec0db62edffa89e9a562a94cbf8fa10b5db5c046"}, - {file = "pydantic-1.10.14-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:412ab4a3f6dbd2bf18aefa9f79c7cca23744846b31f1d6555c2ee2b05a2e14ca"}, - {file = "pydantic-1.10.14-cp311-cp311-win_amd64.whl", hash = "sha256:e897c9f35281f7889873a3e6d6b69aa1447ceb024e8495a5f0d02ecd17742a7f"}, - {file = "pydantic-1.10.14-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d604be0f0b44d473e54fdcb12302495fe0467c56509a2f80483476f3ba92b33c"}, - {file = "pydantic-1.10.14-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a42c7d17706911199798d4c464b352e640cab4351efe69c2267823d619a937e5"}, - {file = "pydantic-1.10.14-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:596f12a1085e38dbda5cbb874d0973303e34227b400b6414782bf205cc14940c"}, - {file = "pydantic-1.10.14-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bfb113860e9288d0886e3b9e49d9cf4a9d48b441f52ded7d96db7819028514cc"}, - {file = "pydantic-1.10.14-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bc3ed06ab13660b565eed80887fcfbc0070f0aa0691fbb351657041d3e874efe"}, - {file = "pydantic-1.10.14-cp37-cp37m-win_amd64.whl", hash = "sha256:ad8c2bc677ae5f6dbd3cf92f2c7dc613507eafe8f71719727cbc0a7dec9a8c01"}, - {file = "pydantic-1.10.14-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c37c28449752bb1f47975d22ef2882d70513c546f8f37201e0fec3a97b816eee"}, - {file = "pydantic-1.10.14-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:49a46a0994dd551ec051986806122767cf144b9702e31d47f6d493c336462597"}, - {file = "pydantic-1.10.14-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53e3819bd20a42470d6dd0fe7fc1c121c92247bca104ce608e609b59bc7a77ee"}, - {file = "pydantic-1.10.14-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0fbb503bbbbab0c588ed3cd21975a1d0d4163b87e360fec17a792f7d8c4ff29f"}, - {file = "pydantic-1.10.14-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:336709883c15c050b9c55a63d6c7ff09be883dbc17805d2b063395dd9d9d0022"}, - {file = "pydantic-1.10.14-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4ae57b4d8e3312d486e2498d42aed3ece7b51848336964e43abbf9671584e67f"}, - {file = "pydantic-1.10.14-cp38-cp38-win_amd64.whl", hash = "sha256:dba49d52500c35cfec0b28aa8b3ea5c37c9df183ffc7210b10ff2a415c125c4a"}, - {file = "pydantic-1.10.14-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c66609e138c31cba607d8e2a7b6a5dc38979a06c900815495b2d90ce6ded35b4"}, - {file = "pydantic-1.10.14-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d986e115e0b39604b9eee3507987368ff8148222da213cd38c359f6f57b3b347"}, - {file = "pydantic-1.10.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:646b2b12df4295b4c3148850c85bff29ef6d0d9621a8d091e98094871a62e5c7"}, - {file = "pydantic-1.10.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282613a5969c47c83a8710cc8bfd1e70c9223feb76566f74683af889faadc0ea"}, - {file = "pydantic-1.10.14-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:466669501d08ad8eb3c4fecd991c5e793c4e0bbd62299d05111d4f827cded64f"}, - {file = "pydantic-1.10.14-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:13e86a19dca96373dcf3190fcb8797d40a6f12f154a244a8d1e8e03b8f280593"}, - {file = "pydantic-1.10.14-cp39-cp39-win_amd64.whl", hash = "sha256:08b6ec0917c30861e3fe71a93be1648a2aa4f62f866142ba21670b24444d7fd8"}, - {file = "pydantic-1.10.14-py3-none-any.whl", hash = "sha256:8ee853cd12ac2ddbf0ecbac1c289f95882b2d4482258048079d13be700aa114c"}, - {file = "pydantic-1.10.14.tar.gz", hash = "sha256:46f17b832fe27de7850896f3afee50ea682220dd218f7e9c88d436788419dca6"}, -] - -[package.dependencies] -typing-extensions = ">=4.2.0" - -[package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] + {file = "pydantic-2.7.2-py3-none-any.whl", hash = "sha256:834ab954175f94e6e68258537dc49402c4a5e9d0409b9f1b86b7e934a8372de7"}, + {file = "pydantic-2.7.2.tar.gz", hash = "sha256:71b2945998f9c9b7919a45bde9a50397b289937d215ae141c1d0903ba7149fd7"}, +] + +[package.dependencies] +annotated-types = ">=0.4.0" +pydantic-core = "2.18.3" +typing-extensions = ">=4.6.1" + +[package.extras] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.18.3" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_core-2.18.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:744697428fcdec6be5670460b578161d1ffe34743a5c15656be7ea82b008197c"}, + {file = "pydantic_core-2.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b40c05ced1ba4218b14986fe6f283d22e1ae2ff4c8e28881a70fb81fbfcda7"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a9a75622357076efb6b311983ff190fbfb3c12fc3a853122b34d3d358126c"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e2e253af04ceaebde8eb201eb3f3e3e7e390f2d275a88300d6a1959d710539e2"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:855ec66589c68aa367d989da5c4755bb74ee92ccad4fdb6af942c3612c067e34"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d3e42bb54e7e9d72c13ce112e02eb1b3b55681ee948d748842171201a03a98a"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6ac9ffccc9d2e69d9fba841441d4259cb668ac180e51b30d3632cd7abca2b9b"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c56eca1686539fa0c9bda992e7bd6a37583f20083c37590413381acfc5f192d6"}, + {file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:17954d784bf8abfc0ec2a633108207ebc4fa2df1a0e4c0c3ccbaa9bb01d2c426"}, + {file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:98ed737567d8f2ecd54f7c8d4f8572ca7c7921ede93a2e52939416170d357812"}, + {file = "pydantic_core-2.18.3-cp310-none-win32.whl", hash = "sha256:9f9e04afebd3ed8c15d67a564ed0a34b54e52136c6d40d14c5547b238390e779"}, + {file = "pydantic_core-2.18.3-cp310-none-win_amd64.whl", hash = "sha256:45e4ffbae34f7ae30d0047697e724e534a7ec0a82ef9994b7913a412c21462a0"}, + {file = "pydantic_core-2.18.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b9ebe8231726c49518b16b237b9fe0d7d361dd221302af511a83d4ada01183ab"}, + {file = "pydantic_core-2.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b8e20e15d18bf7dbb453be78a2d858f946f5cdf06c5072453dace00ab652e2b2"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0d9ff283cd3459fa0bf9b0256a2b6f01ac1ff9ffb034e24457b9035f75587cb"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f7ef5f0ebb77ba24c9970da18b771711edc5feaf00c10b18461e0f5f5949231"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73038d66614d2e5cde30435b5afdced2b473b4c77d4ca3a8624dd3e41a9c19be"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6afd5c867a74c4d314c557b5ea9520183fadfbd1df4c2d6e09fd0d990ce412cd"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd7df92f28d351bb9f12470f4c533cf03d1b52ec5a6e5c58c65b183055a60106"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:80aea0ffeb1049336043d07799eace1c9602519fb3192916ff525b0287b2b1e4"}, + {file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaee40f25bba38132e655ffa3d1998a6d576ba7cf81deff8bfa189fb43fd2bbe"}, + {file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9128089da8f4fe73f7a91973895ebf2502539d627891a14034e45fb9e707e26d"}, + {file = "pydantic_core-2.18.3-cp311-none-win32.whl", hash = "sha256:fec02527e1e03257aa25b1a4dcbe697b40a22f1229f5d026503e8b7ff6d2eda7"}, + {file = "pydantic_core-2.18.3-cp311-none-win_amd64.whl", hash = "sha256:58ff8631dbab6c7c982e6425da8347108449321f61fe427c52ddfadd66642af7"}, + {file = "pydantic_core-2.18.3-cp311-none-win_arm64.whl", hash = "sha256:3fc1c7f67f34c6c2ef9c213e0f2a351797cda98249d9ca56a70ce4ebcaba45f4"}, + {file = "pydantic_core-2.18.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f0928cde2ae416a2d1ebe6dee324709c6f73e93494d8c7aea92df99aab1fc40f"}, + {file = "pydantic_core-2.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0bee9bb305a562f8b9271855afb6ce00223f545de3d68560b3c1649c7c5295e9"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e862823be114387257dacbfa7d78547165a85d7add33b446ca4f4fae92c7ff5c"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a36f78674cbddc165abab0df961b5f96b14461d05feec5e1f78da58808b97e7"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba905d184f62e7ddbb7a5a751d8a5c805463511c7b08d1aca4a3e8c11f2e5048"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fdd362f6a586e681ff86550b2379e532fee63c52def1c666887956748eaa326"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24b214b7ee3bd3b865e963dbed0f8bc5375f49449d70e8d407b567af3222aae4"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:691018785779766127f531674fa82bb368df5b36b461622b12e176c18e119022"}, + {file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:60e4c625e6f7155d7d0dcac151edf5858102bc61bf959d04469ca6ee4e8381bd"}, + {file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4e651e47d981c1b701dcc74ab8fec5a60a5b004650416b4abbef13db23bc7be"}, + {file = "pydantic_core-2.18.3-cp312-none-win32.whl", hash = "sha256:ffecbb5edb7f5ffae13599aec33b735e9e4c7676ca1633c60f2c606beb17efc5"}, + {file = "pydantic_core-2.18.3-cp312-none-win_amd64.whl", hash = "sha256:2c8333f6e934733483c7eddffdb094c143b9463d2af7e6bd85ebcb2d4a1b82c6"}, + {file = "pydantic_core-2.18.3-cp312-none-win_arm64.whl", hash = "sha256:7a20dded653e516a4655f4c98e97ccafb13753987434fe7cf044aa25f5b7d417"}, + {file = "pydantic_core-2.18.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:eecf63195be644b0396f972c82598cd15693550f0ff236dcf7ab92e2eb6d3522"}, + {file = "pydantic_core-2.18.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c44efdd3b6125419c28821590d7ec891c9cb0dff33a7a78d9d5c8b6f66b9702"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e59fca51ffbdd1638b3856779342ed69bcecb8484c1d4b8bdb237d0eb5a45e2"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70cf099197d6b98953468461d753563b28e73cf1eade2ffe069675d2657ed1d5"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63081a49dddc6124754b32a3774331467bfc3d2bd5ff8f10df36a95602560361"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:370059b7883485c9edb9655355ff46d912f4b03b009d929220d9294c7fd9fd60"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a64faeedfd8254f05f5cf6fc755023a7e1606af3959cfc1a9285744cc711044"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19d2e725de0f90d8671f89e420d36c3dd97639b98145e42fcc0e1f6d492a46dc"}, + {file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:67bc078025d70ec5aefe6200ef094576c9d86bd36982df1301c758a9fff7d7f4"}, + {file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:adf952c3f4100e203cbaf8e0c907c835d3e28f9041474e52b651761dc248a3c0"}, + {file = "pydantic_core-2.18.3-cp38-none-win32.whl", hash = "sha256:9a46795b1f3beb167eaee91736d5d17ac3a994bf2215a996aed825a45f897558"}, + {file = "pydantic_core-2.18.3-cp38-none-win_amd64.whl", hash = "sha256:200ad4e3133cb99ed82342a101a5abf3d924722e71cd581cc113fe828f727fbc"}, + {file = "pydantic_core-2.18.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:304378b7bf92206036c8ddd83a2ba7b7d1a5b425acafff637172a3aa72ad7083"}, + {file = "pydantic_core-2.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c826870b277143e701c9ccf34ebc33ddb4d072612683a044e7cce2d52f6c3fef"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e201935d282707394f3668380e41ccf25b5794d1b131cdd96b07f615a33ca4b1"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5560dda746c44b48bf82b3d191d74fe8efc5686a9ef18e69bdabccbbb9ad9442"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b32c2a1f8032570842257e4c19288eba9a2bba4712af542327de9a1204faff8"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:929c24e9dea3990bc8bcd27c5f2d3916c0c86f5511d2caa69e0d5290115344a9"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a8376fef60790152564b0eab376b3e23dd6e54f29d84aad46f7b264ecca943"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dccf3ef1400390ddd1fb55bf0632209d39140552d068ee5ac45553b556780e06"}, + {file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:41dbdcb0c7252b58fa931fec47937edb422c9cb22528f41cb8963665c372caf6"}, + {file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:666e45cf071669fde468886654742fa10b0e74cd0fa0430a46ba6056b24fb0af"}, + {file = "pydantic_core-2.18.3-cp39-none-win32.whl", hash = "sha256:f9c08cabff68704a1b4667d33f534d544b8a07b8e5d039c37067fceb18789e78"}, + {file = "pydantic_core-2.18.3-cp39-none-win_amd64.whl", hash = "sha256:4afa5f5973e8572b5c0dcb4e2d4fda7890e7cd63329bd5cc3263a25c92ef0026"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:77319771a026f7c7d29c6ebc623de889e9563b7087911b46fd06c044a12aa5e9"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:df11fa992e9f576473038510d66dd305bcd51d7dd508c163a8c8fe148454e059"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d531076bdfb65af593326ffd567e6ab3da145020dafb9187a1d131064a55f97c"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d33ce258e4e6e6038f2b9e8b8a631d17d017567db43483314993b3ca345dcbbb"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1f9cd7f5635b719939019be9bda47ecb56e165e51dd26c9a217a433e3d0d59a9"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cd4a032bb65cc132cae1fe3e52877daecc2097965cd3914e44fbd12b00dae7c5"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f2718430098bcdf60402136c845e4126a189959d103900ebabb6774a5d9fdb"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c0037a92cf0c580ed14e10953cdd26528e8796307bb8bb312dc65f71547df04d"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b95a0972fac2b1ff3c94629fc9081b16371dad870959f1408cc33b2f78ad347a"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a62e437d687cc148381bdd5f51e3e81f5b20a735c55f690c5be94e05da2b0d5c"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b367a73a414bbb08507da102dc2cde0fa7afe57d09b3240ce82a16d608a7679c"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ecce4b2360aa3f008da3327d652e74a0e743908eac306198b47e1c58b03dd2b"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd4435b8d83f0c9561a2a9585b1de78f1abb17cb0cef5f39bf6a4b47d19bafe3"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:616221a6d473c5b9aa83fa8982745441f6a4a62a66436be9445c65f241b86c94"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7e6382ce89a92bc1d0c0c5edd51e931432202b9080dc921d8d003e616402efd1"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ff58f379345603d940e461eae474b6bbb6dab66ed9a851ecd3cb3709bf4dcf6a"}, + {file = "pydantic_core-2.18.3.tar.gz", hash = "sha256:432e999088d85c8f36b9a3f769a8e2b57aabd817bbb729a90d1fe7f18f6f1f39"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pydub" @@ -1471,6 +2384,37 @@ files = [ {file = "pydub-0.25.1.tar.gz", hash = "sha256:980a33ce9949cab2a569606b65674d748ecbca4f0796887fd6f46173a7b0d30f"}, ] +[[package]] +name = "pygments" +version = "2.18.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pyht" +version = "0.0.28" +description = "" +optional = false +python-versions = "<4.0,>=3.8" +files = [ + {file = "pyht-0.0.28-py3-none-any.whl", hash = "sha256:ad8801acaa906eff5d6b39ce5ca76a08c154f705a2d0b2b6e841b219ef7875be"}, + {file = "pyht-0.0.28.tar.gz", hash = "sha256:00792e8c068fc905557525de9db0dbd7dcb651e15f05c6cc49490340b95a444a"}, +] + +[package.dependencies] +filelock = ">=3.12.4,<4.0.0" +grpcio = ">=1.58.0,<2.0.0" +protobuf = ">=4.24.3,<5.0.0" +requests = ">=2.31.0,<3.0.0" + [[package]] name = "pyjwt" version = "2.8.0" @@ -1493,16 +2437,21 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] [[package]] name = "pyngrok" -version = "6.1.2" +version = "7.1.6" description = "A Python wrapper for ngrok." optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" files = [ - {file = "pyngrok-6.1.2.tar.gz", hash = "sha256:f5f4f67e79ed050ef2f9ce76b6ea8733b89502aa0b83002cea2ce6b994543622"}, + {file = "pyngrok-7.1.6-py3-none-any.whl", hash = "sha256:422ac7c339622fef51308f0c493a1f5a05d0f403eee5bdd183fb4021a6cb90d4"}, + {file = "pyngrok-7.1.6.tar.gz", hash = "sha256:05c0fca6340913658abddc623a0a53927aced93e27ffef801d24814bcb180eaa"}, ] [package.dependencies] -PyYAML = "*" +PyYAML = ">=5.1" + +[package.extras] +dev = ["coverage[toml]", "flake8", "flake8-pyproject", "pep8-naming", "psutil"] +docs = ["Sphinx", "mypy", "sphinx-autodoc-typehints (==1.25.2)", "sphinx-notfound-page", "sphinx-substitution-extensions", "types-PyYAML"] [[package]] name = "python-dotenv" @@ -1520,27 +2469,27 @@ cli = ["click (>=5.0)"] [[package]] name = "python-multipart" -version = "0.0.6" +version = "0.0.9" description = "A streaming multipart parser for Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "python_multipart-0.0.6-py3-none-any.whl", hash = "sha256:ee698bab5ef148b0a760751c261902cd096e57e10558e11aca17646b74ee1c18"}, - {file = "python_multipart-0.0.6.tar.gz", hash = "sha256:e9925a80bb668529f1b67c7fdb0a5dacdd7cbfc6fb0bff3ea443fe22bdd62132"}, + {file = "python_multipart-0.0.9-py3-none-any.whl", hash = "sha256:97ca7b8ea7b05f977dc3849c3ba99d51689822fab725c3703af7c866a0c2b215"}, + {file = "python_multipart-0.0.9.tar.gz", hash = "sha256:03f54688c663f1b7977105f021043b0793151e4cb1c1a9d4a11fc13d622c4026"}, ] [package.extras] -dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==1.7.3)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"] +dev = ["atomicwrites (==1.4.1)", "attrs (==23.2.0)", "coverage (==7.4.1)", "hatch", "invoke (==2.2.0)", "more-itertools (==10.2.0)", "pbr (==6.0.0)", "pluggy (==1.4.0)", "py (==1.11.0)", "pytest (==8.0.0)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.2.0)", "pyyaml (==6.0.1)", "ruff (==0.2.1)"] [[package]] name = "pytz" -version = "2023.3.post1" +version = "2024.1" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" files = [ - {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, - {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, ] [[package]] @@ -1555,6 +2504,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -1562,8 +2512,16 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -1580,6 +2538,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -1587,6 +2546,7 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -1594,133 +2554,134 @@ files = [ [[package]] name = "redis" -version = "4.6.0" +version = "5.0.4" description = "Python client for Redis database and key-value store" optional = false python-versions = ">=3.7" files = [ - {file = "redis-4.6.0-py3-none-any.whl", hash = "sha256:e2b03db868160ee4591de3cb90d40ebb50a90dd302138775937f6a42b7ed183c"}, - {file = "redis-4.6.0.tar.gz", hash = "sha256:585dc516b9eb042a619ef0a39c3d7d55fe81bdb4df09a52c9cdde0d07bf1aa7d"}, + {file = "redis-5.0.4-py3-none-any.whl", hash = "sha256:7adc2835c7a9b5033b7ad8f8918d09b7344188228809c98df07af226d39dec91"}, + {file = "redis-5.0.4.tar.gz", hash = "sha256:ec31f2ed9675cc54c21ba854cfe0462e6faf1d83c8ce5944709db8a4700b9c61"}, ] [package.dependencies] -async-timeout = {version = ">=4.0.2", markers = "python_full_version <= \"3.11.2\""} +async-timeout = {version = ">=4.0.3", markers = "python_full_version < \"3.11.3\""} [package.extras] hiredis = ["hiredis (>=1.0.0)"] ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"] +[[package]] +name = "referencing" +version = "0.35.1" +description = "JSON Referencing + Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"}, + {file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + [[package]] name = "regex" -version = "2023.12.25" +version = "2024.5.15" description = "Alternative regular expression module, to replace re." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"}, - {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"}, - {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"}, - {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"}, - {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"}, - {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"}, - {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"}, - {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"}, - {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"}, - {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"}, - {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"}, - {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"}, - {file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"}, - {file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"}, - {file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"}, - {file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"}, - {file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53"}, + {file = "regex-2024.5.15-cp310-cp310-win32.whl", hash = "sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3"}, + {file = "regex-2024.5.15-cp310-cp310-win_amd64.whl", hash = "sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68"}, + {file = "regex-2024.5.15-cp311-cp311-win32.whl", hash = "sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa"}, + {file = "regex-2024.5.15-cp311-cp311-win_amd64.whl", hash = "sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80"}, + {file = "regex-2024.5.15-cp312-cp312-win32.whl", hash = "sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe"}, + {file = "regex-2024.5.15-cp312-cp312-win_amd64.whl", hash = "sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741"}, + {file = "regex-2024.5.15-cp38-cp38-win32.whl", hash = "sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9"}, + {file = "regex-2024.5.15-cp38-cp38-win_amd64.whl", hash = "sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456"}, + {file = "regex-2024.5.15-cp39-cp39-win32.whl", hash = "sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694"}, + {file = "regex-2024.5.15-cp39-cp39-win_amd64.whl", hash = "sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388"}, + {file = "regex-2024.5.15.tar.gz", hash = "sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c"}, ] [[package]] name = "requests" -version = "2.31.0" +version = "2.32.3" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -1734,46 +2695,206 @@ socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] -name = "scipy" -version = "1.12.0" -description = "Fundamental algorithms for scientific computing in Python" +name = "rich" +version = "13.7.1" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false -python-versions = ">=3.9" +python-versions = ">=3.7.0" files = [ - {file = "scipy-1.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:78e4402e140879387187f7f25d91cc592b3501a2e51dfb320f48dfb73565f10b"}, - {file = "scipy-1.12.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:f5f00ebaf8de24d14b8449981a2842d404152774c1a1d880c901bf454cb8e2a1"}, - {file = "scipy-1.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e53958531a7c695ff66c2e7bb7b79560ffdc562e2051644c5576c39ff8efb563"}, - {file = "scipy-1.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e32847e08da8d895ce09d108a494d9eb78974cf6de23063f93306a3e419960c"}, - {file = "scipy-1.12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4c1020cad92772bf44b8e4cdabc1df5d87376cb219742549ef69fc9fd86282dd"}, - {file = "scipy-1.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:75ea2a144096b5e39402e2ff53a36fecfd3b960d786b7efd3c180e29c39e53f2"}, - {file = "scipy-1.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:408c68423f9de16cb9e602528be4ce0d6312b05001f3de61fe9ec8b1263cad08"}, - {file = "scipy-1.12.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:5adfad5dbf0163397beb4aca679187d24aec085343755fcdbdeb32b3679f254c"}, - {file = "scipy-1.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3003652496f6e7c387b1cf63f4bb720951cfa18907e998ea551e6de51a04467"}, - {file = "scipy-1.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b8066bce124ee5531d12a74b617d9ac0ea59245246410e19bca549656d9a40a"}, - {file = "scipy-1.12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8bee4993817e204d761dba10dbab0774ba5a8612e57e81319ea04d84945375ba"}, - {file = "scipy-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:a24024d45ce9a675c1fb8494e8e5244efea1c7a09c60beb1eeb80373d0fecc70"}, - {file = "scipy-1.12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e7e76cc48638228212c747ada851ef355c2bb5e7f939e10952bc504c11f4e372"}, - {file = "scipy-1.12.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:f7ce148dffcd64ade37b2df9315541f9adad6efcaa86866ee7dd5db0c8f041c3"}, - {file = "scipy-1.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c39f92041f490422924dfdb782527a4abddf4707616e07b021de33467f917bc"}, - {file = "scipy-1.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7ebda398f86e56178c2fa94cad15bf457a218a54a35c2a7b4490b9f9cb2676c"}, - {file = "scipy-1.12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:95e5c750d55cf518c398a8240571b0e0782c2d5a703250872f36eaf737751338"}, - {file = "scipy-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:e646d8571804a304e1da01040d21577685ce8e2db08ac58e543eaca063453e1c"}, - {file = "scipy-1.12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:913d6e7956c3a671de3b05ccb66b11bc293f56bfdef040583a7221d9e22a2e35"}, - {file = "scipy-1.12.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba1b0c7256ad75401c73e4b3cf09d1f176e9bd4248f0d3112170fb2ec4db067"}, - {file = "scipy-1.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:730badef9b827b368f351eacae2e82da414e13cf8bd5051b4bdfd720271a5371"}, - {file = "scipy-1.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6546dc2c11a9df6926afcbdd8a3edec28566e4e785b915e849348c6dd9f3f490"}, - {file = "scipy-1.12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:196ebad3a4882081f62a5bf4aeb7326aa34b110e533aab23e4374fcccb0890dc"}, - {file = "scipy-1.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:b360f1b6b2f742781299514e99ff560d1fe9bd1bff2712894b52abe528d1fd1e"}, - {file = "scipy-1.12.0.tar.gz", hash = "sha256:4bf5abab8a36d20193c698b0f1fc282c1d083c94723902c447e5d2f1780936a3"}, -] - -[package.dependencies] -numpy = ">=1.22.4,<1.29.0" - -[package.extras] -dev = ["click", "cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pydevtool", "rich-click", "ruff", "types-psutil", "typing_extensions"] -doc = ["jupytext", "matplotlib (>2)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] -test = ["asv", "gmpy2", "hypothesis", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] + {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"}, + {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + +[[package]] +name = "rpds-py" +version = "0.18.1" +description = "Python bindings to Rust's persistent data structures (rpds)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "rpds_py-0.18.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:d31dea506d718693b6b2cffc0648a8929bdc51c70a311b2770f09611caa10d53"}, + {file = "rpds_py-0.18.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:732672fbc449bab754e0b15356c077cc31566df874964d4801ab14f71951ea80"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a98a1f0552b5f227a3d6422dbd61bc6f30db170939bd87ed14f3c339aa6c7c9"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f1944ce16401aad1e3f7d312247b3d5de7981f634dc9dfe90da72b87d37887d"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38e14fb4e370885c4ecd734f093a2225ee52dc384b86fa55fe3f74638b2cfb09"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08d74b184f9ab6289b87b19fe6a6d1a97fbfea84b8a3e745e87a5de3029bf944"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d70129cef4a8d979caa37e7fe957202e7eee8ea02c5e16455bc9808a59c6b2f0"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ce0bb20e3a11bd04461324a6a798af34d503f8d6f1aa3d2aa8901ceaf039176d"}, + {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81c5196a790032e0fc2464c0b4ab95f8610f96f1f2fa3d4deacce6a79852da60"}, + {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f3027be483868c99b4985fda802a57a67fdf30c5d9a50338d9db646d590198da"}, + {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d44607f98caa2961bab4fa3c4309724b185b464cdc3ba6f3d7340bac3ec97cc1"}, + {file = "rpds_py-0.18.1-cp310-none-win32.whl", hash = "sha256:c273e795e7a0f1fddd46e1e3cb8be15634c29ae8ff31c196debb620e1edb9333"}, + {file = "rpds_py-0.18.1-cp310-none-win_amd64.whl", hash = "sha256:8352f48d511de5f973e4f2f9412736d7dea76c69faa6d36bcf885b50c758ab9a"}, + {file = "rpds_py-0.18.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6b5ff7e1d63a8281654b5e2896d7f08799378e594f09cf3674e832ecaf396ce8"}, + {file = "rpds_py-0.18.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8927638a4d4137a289e41d0fd631551e89fa346d6dbcfc31ad627557d03ceb6d"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:154bf5c93d79558b44e5b50cc354aa0459e518e83677791e6adb0b039b7aa6a7"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07f2139741e5deb2c5154a7b9629bc5aa48c766b643c1a6750d16f865a82c5fc"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c7672e9fba7425f79019db9945b16e308ed8bc89348c23d955c8c0540da0a07"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:489bdfe1abd0406eba6b3bb4fdc87c7fa40f1031de073d0cfb744634cc8fa261"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c20f05e8e3d4fc76875fc9cb8cf24b90a63f5a1b4c5b9273f0e8225e169b100"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:967342e045564cef76dfcf1edb700b1e20838d83b1aa02ab313e6a497cf923b8"}, + {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2cc7c1a47f3a63282ab0f422d90ddac4aa3034e39fc66a559ab93041e6505da7"}, + {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f7afbfee1157e0f9376c00bb232e80a60e59ed716e3211a80cb8506550671e6e"}, + {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9e6934d70dc50f9f8ea47081ceafdec09245fd9f6032669c3b45705dea096b88"}, + {file = "rpds_py-0.18.1-cp311-none-win32.whl", hash = "sha256:c69882964516dc143083d3795cb508e806b09fc3800fd0d4cddc1df6c36e76bb"}, + {file = "rpds_py-0.18.1-cp311-none-win_amd64.whl", hash = "sha256:70a838f7754483bcdc830444952fd89645569e7452e3226de4a613a4c1793fb2"}, + {file = "rpds_py-0.18.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3dd3cd86e1db5aadd334e011eba4e29d37a104b403e8ca24dcd6703c68ca55b3"}, + {file = "rpds_py-0.18.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:05f3d615099bd9b13ecf2fc9cf2d839ad3f20239c678f461c753e93755d629ee"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35b2b771b13eee8729a5049c976197ff58a27a3829c018a04341bcf1ae409b2b"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ee17cd26b97d537af8f33635ef38be873073d516fd425e80559f4585a7b90c43"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b646bf655b135ccf4522ed43d6902af37d3f5dbcf0da66c769a2b3938b9d8184"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19ba472b9606c36716062c023afa2484d1e4220548751bda14f725a7de17b4f6"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e30ac5e329098903262dc5bdd7e2086e0256aa762cc8b744f9e7bf2a427d3f8"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d58ad6317d188c43750cb76e9deacf6051d0f884d87dc6518e0280438648a9ac"}, + {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e1735502458621921cee039c47318cb90b51d532c2766593be6207eec53e5c4c"}, + {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f5bab211605d91db0e2995a17b5c6ee5edec1270e46223e513eaa20da20076ac"}, + {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2fc24a329a717f9e2448f8cd1f960f9dac4e45b6224d60734edeb67499bab03a"}, + {file = "rpds_py-0.18.1-cp312-none-win32.whl", hash = "sha256:1805d5901779662d599d0e2e4159d8a82c0b05faa86ef9222bf974572286b2b6"}, + {file = "rpds_py-0.18.1-cp312-none-win_amd64.whl", hash = "sha256:720edcb916df872d80f80a1cc5ea9058300b97721efda8651efcd938a9c70a72"}, + {file = "rpds_py-0.18.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:c827576e2fa017a081346dce87d532a5310241648eb3700af9a571a6e9fc7e74"}, + {file = "rpds_py-0.18.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aa3679e751408d75a0b4d8d26d6647b6d9326f5e35c00a7ccd82b78ef64f65f8"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0abeee75434e2ee2d142d650d1e54ac1f8b01e6e6abdde8ffd6eeac6e9c38e20"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed402d6153c5d519a0faf1bb69898e97fb31613b49da27a84a13935ea9164dfc"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:338dee44b0cef8b70fd2ef54b4e09bb1b97fc6c3a58fea5db6cc083fd9fc2724"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7750569d9526199c5b97e5a9f8d96a13300950d910cf04a861d96f4273d5b104"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:607345bd5912aacc0c5a63d45a1f73fef29e697884f7e861094e443187c02be5"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:207c82978115baa1fd8d706d720b4a4d2b0913df1c78c85ba73fe6c5804505f0"}, + {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6d1e42d2735d437e7e80bab4d78eb2e459af48c0a46e686ea35f690b93db792d"}, + {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5463c47c08630007dc0fe99fb480ea4f34a89712410592380425a9b4e1611d8e"}, + {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:06d218939e1bf2ca50e6b0ec700ffe755e5216a8230ab3e87c059ebb4ea06afc"}, + {file = "rpds_py-0.18.1-cp38-none-win32.whl", hash = "sha256:312fe69b4fe1ffbe76520a7676b1e5ac06ddf7826d764cc10265c3b53f96dbe9"}, + {file = "rpds_py-0.18.1-cp38-none-win_amd64.whl", hash = "sha256:9437ca26784120a279f3137ee080b0e717012c42921eb07861b412340f85bae2"}, + {file = "rpds_py-0.18.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:19e515b78c3fc1039dd7da0a33c28c3154458f947f4dc198d3c72db2b6b5dc93"}, + {file = "rpds_py-0.18.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7b28c5b066bca9a4eb4e2f2663012debe680f097979d880657f00e1c30875a0"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:673fdbbf668dd958eff750e500495ef3f611e2ecc209464f661bc82e9838991e"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d960de62227635d2e61068f42a6cb6aae91a7fe00fca0e3aeed17667c8a34611"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:352a88dc7892f1da66b6027af06a2e7e5d53fe05924cc2cfc56495b586a10b72"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e0ee01ad8260184db21468a6e1c37afa0529acc12c3a697ee498d3c2c4dcaf3"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4c39ad2f512b4041343ea3c7894339e4ca7839ac38ca83d68a832fc8b3748ab"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aaa71ee43a703c321906813bb252f69524f02aa05bf4eec85f0c41d5d62d0f4c"}, + {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6cd8098517c64a85e790657e7b1e509b9fe07487fd358e19431cb120f7d96338"}, + {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:4adec039b8e2928983f885c53b7cc4cda8965b62b6596501a0308d2703f8af1b"}, + {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:32b7daaa3e9389db3695964ce8e566e3413b0c43e3394c05e4b243a4cd7bef26"}, + {file = "rpds_py-0.18.1-cp39-none-win32.whl", hash = "sha256:2625f03b105328729f9450c8badda34d5243231eef6535f80064d57035738360"}, + {file = "rpds_py-0.18.1-cp39-none-win_amd64.whl", hash = "sha256:bf18932d0003c8c4d51a39f244231986ab23ee057d235a12b2684ea26a353590"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cbfbea39ba64f5e53ae2915de36f130588bba71245b418060ec3330ebf85678e"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:a3d456ff2a6a4d2adcdf3c1c960a36f4fd2fec6e3b4902a42a384d17cf4e7a65"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7700936ef9d006b7ef605dc53aa364da2de5a3aa65516a1f3ce73bf82ecfc7ae"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:51584acc5916212e1bf45edd17f3a6b05fe0cbb40482d25e619f824dccb679de"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:942695a206a58d2575033ff1e42b12b2aece98d6003c6bc739fbf33d1773b12f"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b906b5f58892813e5ba5c6056d6a5ad08f358ba49f046d910ad992196ea61397"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6f8e3fecca256fefc91bb6765a693d96692459d7d4c644660a9fff32e517843"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7732770412bab81c5a9f6d20aeb60ae943a9b36dcd990d876a773526468e7163"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:bd1105b50ede37461c1d51b9698c4f4be6e13e69a908ab7751e3807985fc0346"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:618916f5535784960f3ecf8111581f4ad31d347c3de66d02e728de460a46303c"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:17c6d2155e2423f7e79e3bb18151c686d40db42d8645e7977442170c360194d4"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c4c4c3f878df21faf5fac86eda32671c27889e13570645a9eea0a1abdd50922"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:fab6ce90574645a0d6c58890e9bcaac8d94dff54fb51c69e5522a7358b80ab64"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:531796fb842b53f2695e94dc338929e9f9dbf473b64710c28af5a160b2a8927d"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:740884bc62a5e2bbb31e584f5d23b32320fd75d79f916f15a788d527a5e83644"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:998125738de0158f088aef3cb264a34251908dd2e5d9966774fdab7402edfab7"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e2be6e9dd4111d5b31ba3b74d17da54a8319d8168890fbaea4b9e5c3de630ae5"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0cee71bc618cd93716f3c1bf56653740d2d13ddbd47673efa8bf41435a60daa"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2c3caec4ec5cd1d18e5dd6ae5194d24ed12785212a90b37f5f7f06b8bedd7139"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:27bba383e8c5231cd559affe169ca0b96ec78d39909ffd817f28b166d7ddd4d8"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:a888e8bdb45916234b99da2d859566f1e8a1d2275a801bb8e4a9644e3c7e7909"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6031b25fb1b06327b43d841f33842b383beba399884f8228a6bb3df3088485ff"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48c2faaa8adfacefcbfdb5f2e2e7bdad081e5ace8d182e5f4ade971f128e6bb3"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:d85164315bd68c0806768dc6bb0429c6f95c354f87485ee3593c4f6b14def2bd"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6afd80f6c79893cfc0574956f78a0add8c76e3696f2d6a15bca2c66c415cf2d4"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa242ac1ff583e4ec7771141606aafc92b361cd90a05c30d93e343a0c2d82a89"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21be4770ff4e08698e1e8e0bce06edb6ea0626e7c8f560bc08222880aca6a6f"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c45a639e93a0c5d4b788b2613bd637468edd62f8f95ebc6fcc303d58ab3f0a8"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910e71711d1055b2768181efa0a17537b2622afeb0424116619817007f8a2b10"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b9bb1f182a97880f6078283b3505a707057c42bf55d8fca604f70dedfdc0772a"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d54f74f40b1f7aaa595a02ff42ef38ca654b1469bef7d52867da474243cc633"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:8d2e182c9ee01135e11e9676e9a62dfad791a7a467738f06726872374a83db49"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:636a15acc588f70fda1661234761f9ed9ad79ebed3f2125d44be0862708b666e"}, + {file = "rpds_py-0.18.1.tar.gz", hash = "sha256:dc48b479d540770c811fbd1eb9ba2bb66951863e448efec2e2c102625328e92f"}, +] + +[[package]] +name = "rsa" +version = "4.9" +description = "Pure-Python RSA implementation" +optional = false +python-versions = ">=3.6,<4" +files = [ + {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, + {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, +] + +[package.dependencies] +pyasn1 = ">=0.1.3" + +[[package]] +name = "sentry-sdk" +version = "2.3.1" +description = "Python client for Sentry (https://sentry.io)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "sentry_sdk-2.3.1-py2.py3-none-any.whl", hash = "sha256:c5aeb095ba226391d337dd42a6f9470d86c9fc236ecc71cfc7cd1942b45010c6"}, + {file = "sentry_sdk-2.3.1.tar.gz", hash = "sha256:139a71a19f5e9eb5d3623942491ce03cf8ebc14ea2e39ba3e6fe79560d8a5b1f"}, +] + +[package.dependencies] +certifi = "*" +fastapi = {version = ">=0.79.0", optional = true, markers = "extra == \"fastapi\""} +urllib3 = ">=1.26.11" + +[package.extras] +aiohttp = ["aiohttp (>=3.5)"] +anthropic = ["anthropic (>=0.16)"] +arq = ["arq (>=0.23)"] +asyncpg = ["asyncpg (>=0.23)"] +beam = ["apache-beam (>=2.12)"] +bottle = ["bottle (>=0.12.13)"] +celery = ["celery (>=3)"] +celery-redbeat = ["celery-redbeat (>=2)"] +chalice = ["chalice (>=1.16.0)"] +clickhouse-driver = ["clickhouse-driver (>=0.2.0)"] +django = ["django (>=1.8)"] +falcon = ["falcon (>=1.4)"] +fastapi = ["fastapi (>=0.79.0)"] +flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"] +grpcio = ["grpcio (>=1.21.1)", "protobuf (>=3.8.0)"] +httpx = ["httpx (>=0.16.0)"] +huey = ["huey (>=2)"] +huggingface-hub = ["huggingface-hub (>=0.22)"] +langchain = ["langchain (>=0.0.210)"] +loguru = ["loguru (>=0.5)"] +openai = ["openai (>=1.0.0)", "tiktoken (>=0.3.0)"] +opentelemetry = ["opentelemetry-distro (>=0.35b0)"] +opentelemetry-experimental = ["opentelemetry-distro (>=0.40b0,<1.0)", "opentelemetry-instrumentation-aiohttp-client (>=0.40b0,<1.0)", "opentelemetry-instrumentation-django (>=0.40b0,<1.0)", "opentelemetry-instrumentation-fastapi (>=0.40b0,<1.0)", "opentelemetry-instrumentation-flask (>=0.40b0,<1.0)", "opentelemetry-instrumentation-requests (>=0.40b0,<1.0)", "opentelemetry-instrumentation-sqlite3 (>=0.40b0,<1.0)", "opentelemetry-instrumentation-urllib (>=0.40b0,<1.0)"] +pure-eval = ["asttokens", "executing", "pure-eval"] +pymongo = ["pymongo (>=3.1)"] +pyspark = ["pyspark (>=2.4.4)"] +quart = ["blinker (>=1.1)", "quart (>=0.16.1)"] +rq = ["rq (>=0.6)"] +sanic = ["sanic (>=0.8)"] +sqlalchemy = ["sqlalchemy (>=1.2)"] +starlette = ["starlette (>=0.19.1)"] +starlite = ["starlite (>=1.48)"] +tornado = ["tornado (>=5)"] + +[[package]] +name = "shellingham" +version = "1.5.4" +description = "Tool to Detect Surrounding Shell" +optional = false +python-versions = ">=3.7" +files = [ + {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, + {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, +] [[package]] name = "six" @@ -1788,27 +2909,27 @@ files = [ [[package]] name = "sniffio" -version = "1.3.0" +version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" files = [ - {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, - {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] [[package]] name = "sounddevice" -version = "0.4.6" +version = "0.4.7" description = "Play and Record Sound with Python" optional = false python-versions = ">=3.7" files = [ - {file = "sounddevice-0.4.6-py3-none-any.whl", hash = "sha256:5de768ba6fe56ad2b5aaa2eea794b76b73e427961c95acad2ee2ed7f866a4b20"}, - {file = "sounddevice-0.4.6-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl", hash = "sha256:8b0b806c205dd3e3cd5a97262b2482624fd21db7d47083b887090148a08051c8"}, - {file = "sounddevice-0.4.6-py3-none-win32.whl", hash = "sha256:e3ba6e674ffa8f79a591d744a1d4ab922fe5bdfd4faf8b25069a08e051010b7b"}, - {file = "sounddevice-0.4.6-py3-none-win_amd64.whl", hash = "sha256:7830d4f8f8570f2e5552942f81d96999c5fcd9a0b682d6fc5d5c5529df23be2c"}, - {file = "sounddevice-0.4.6.tar.gz", hash = "sha256:3236b78f15f0415bdf006a620cef073d0c0522851d66f4a961ed6d8eb1482fe9"}, + {file = "sounddevice-0.4.7-py3-none-any.whl", hash = "sha256:1c3f18bfa4d9a257f5715f2ab83f2c0eb412a09f3e6a9fa73720886ca88f6bc7"}, + {file = "sounddevice-0.4.7-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl", hash = "sha256:d6ddfd341ad7412b14ca001f2c4dbf5fa2503bdc9eb15ad2c3105f6c260b698a"}, + {file = "sounddevice-0.4.7-py3-none-win32.whl", hash = "sha256:1ec1df094c468a210113aa22c4f390d5b4d9c7a73e41a6cb6ecfec83db59b380"}, + {file = "sounddevice-0.4.7-py3-none-win_amd64.whl", hash = "sha256:0c8b3543da1496f282b66a7bc54b755577ba638b1af06c146d4ac7f39d86b548"}, + {file = "sounddevice-0.4.7.tar.gz", hash = "sha256:69b386818d50a2d518607d4b973442e8d524760c7cd6c8b8be03d8c98fc4bce7"}, ] [package.dependencies] @@ -1817,80 +2938,62 @@ CFFI = ">=1.0" [package.extras] numpy = ["NumPy"] -[[package]] -name = "speechrecognition" -version = "3.10.1" -description = "Library for performing speech recognition, with support for several engines and APIs, online and offline." -optional = false -python-versions = ">=3.8" -files = [ - {file = "SpeechRecognition-3.10.1-py2.py3-none-any.whl", hash = "sha256:69898b2b0bbd5bc65647c5ef833fe318ad74f02e8a6af5c9fd671933083660bc"}, - {file = "SpeechRecognition-3.10.1.tar.gz", hash = "sha256:718731886b7836e20a06b9a2c6cace12a9e130971bb6af1b1dd130b22bad9f82"}, -] - -[package.dependencies] -requests = ">=2.26.0" -typing-extensions = "*" - -[package.extras] -whisper-api = ["openai"] - [[package]] name = "sqlalchemy" -version = "2.0.25" +version = "2.0.30" description = "Database Abstraction Library" optional = false python-versions = ">=3.7" files = [ - {file = "SQLAlchemy-2.0.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4344d059265cc8b1b1be351bfb88749294b87a8b2bbe21dfbe066c4199541ebd"}, - {file = "SQLAlchemy-2.0.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6f9e2e59cbcc6ba1488404aad43de005d05ca56e069477b33ff74e91b6319735"}, - {file = "SQLAlchemy-2.0.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84daa0a2055df9ca0f148a64fdde12ac635e30edbca80e87df9b3aaf419e144a"}, - {file = "SQLAlchemy-2.0.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc8b7dabe8e67c4832891a5d322cec6d44ef02f432b4588390017f5cec186a84"}, - {file = "SQLAlchemy-2.0.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f5693145220517b5f42393e07a6898acdfe820e136c98663b971906120549da5"}, - {file = "SQLAlchemy-2.0.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:db854730a25db7c956423bb9fb4bdd1216c839a689bf9cc15fada0a7fb2f4570"}, - {file = "SQLAlchemy-2.0.25-cp310-cp310-win32.whl", hash = "sha256:14a6f68e8fc96e5e8f5647ef6cda6250c780612a573d99e4d881581432ef1669"}, - {file = "SQLAlchemy-2.0.25-cp310-cp310-win_amd64.whl", hash = "sha256:87f6e732bccd7dcf1741c00f1ecf33797383128bd1c90144ac8adc02cbb98643"}, - {file = "SQLAlchemy-2.0.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:342d365988ba88ada8af320d43df4e0b13a694dbd75951f537b2d5e4cb5cd002"}, - {file = "SQLAlchemy-2.0.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f37c0caf14b9e9b9e8f6dbc81bc56db06acb4363eba5a633167781a48ef036ed"}, - {file = "SQLAlchemy-2.0.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa9373708763ef46782d10e950b49d0235bfe58facebd76917d3f5cbf5971aed"}, - {file = "SQLAlchemy-2.0.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d24f571990c05f6b36a396218f251f3e0dda916e0c687ef6fdca5072743208f5"}, - {file = "SQLAlchemy-2.0.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75432b5b14dc2fff43c50435e248b45c7cdadef73388e5610852b95280ffd0e9"}, - {file = "SQLAlchemy-2.0.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:884272dcd3ad97f47702965a0e902b540541890f468d24bd1d98bcfe41c3f018"}, - {file = "SQLAlchemy-2.0.25-cp311-cp311-win32.whl", hash = "sha256:e607cdd99cbf9bb80391f54446b86e16eea6ad309361942bf88318bcd452363c"}, - {file = "SQLAlchemy-2.0.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d505815ac340568fd03f719446a589162d55c52f08abd77ba8964fbb7eb5b5f"}, - {file = "SQLAlchemy-2.0.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0dacf67aee53b16f365c589ce72e766efaabd2b145f9de7c917777b575e3659d"}, - {file = "SQLAlchemy-2.0.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b801154027107461ee992ff4b5c09aa7cc6ec91ddfe50d02bca344918c3265c6"}, - {file = "SQLAlchemy-2.0.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59a21853f5daeb50412d459cfb13cb82c089ad4c04ec208cd14dddd99fc23b39"}, - {file = "SQLAlchemy-2.0.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29049e2c299b5ace92cbed0c1610a7a236f3baf4c6b66eb9547c01179f638ec5"}, - {file = "SQLAlchemy-2.0.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b64b183d610b424a160b0d4d880995e935208fc043d0302dd29fee32d1ee3f95"}, - {file = "SQLAlchemy-2.0.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4f7a7d7fcc675d3d85fbf3b3828ecd5990b8d61bd6de3f1b260080b3beccf215"}, - {file = "SQLAlchemy-2.0.25-cp312-cp312-win32.whl", hash = "sha256:cf18ff7fc9941b8fc23437cc3e68ed4ebeff3599eec6ef5eebf305f3d2e9a7c2"}, - {file = "SQLAlchemy-2.0.25-cp312-cp312-win_amd64.whl", hash = "sha256:91f7d9d1c4dd1f4f6e092874c128c11165eafcf7c963128f79e28f8445de82d5"}, - {file = "SQLAlchemy-2.0.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bb209a73b8307f8fe4fe46f6ad5979649be01607f11af1eb94aa9e8a3aaf77f0"}, - {file = "SQLAlchemy-2.0.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:798f717ae7c806d67145f6ae94dc7c342d3222d3b9a311a784f371a4333212c7"}, - {file = "SQLAlchemy-2.0.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fdd402169aa00df3142149940b3bf9ce7dde075928c1886d9a1df63d4b8de62"}, - {file = "SQLAlchemy-2.0.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0d3cab3076af2e4aa5693f89622bef7fa770c6fec967143e4da7508b3dceb9b9"}, - {file = "SQLAlchemy-2.0.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:74b080c897563f81062b74e44f5a72fa44c2b373741a9ade701d5f789a10ba23"}, - {file = "SQLAlchemy-2.0.25-cp37-cp37m-win32.whl", hash = "sha256:87d91043ea0dc65ee583026cb18e1b458d8ec5fc0a93637126b5fc0bc3ea68c4"}, - {file = "SQLAlchemy-2.0.25-cp37-cp37m-win_amd64.whl", hash = "sha256:75f99202324383d613ddd1f7455ac908dca9c2dd729ec8584c9541dd41822a2c"}, - {file = "SQLAlchemy-2.0.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:420362338681eec03f53467804541a854617faed7272fe71a1bfdb07336a381e"}, - {file = "SQLAlchemy-2.0.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c88f0c7dcc5f99bdb34b4fd9b69b93c89f893f454f40219fe923a3a2fd11625"}, - {file = "SQLAlchemy-2.0.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3be4987e3ee9d9a380b66393b77a4cd6d742480c951a1c56a23c335caca4ce3"}, - {file = "SQLAlchemy-2.0.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a159111a0f58fb034c93eeba211b4141137ec4b0a6e75789ab7a3ef3c7e7e3"}, - {file = "SQLAlchemy-2.0.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8b8cb63d3ea63b29074dcd29da4dc6a97ad1349151f2d2949495418fd6e48db9"}, - {file = "SQLAlchemy-2.0.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:736ea78cd06de6c21ecba7416499e7236a22374561493b456a1f7ffbe3f6cdb4"}, - {file = "SQLAlchemy-2.0.25-cp38-cp38-win32.whl", hash = "sha256:10331f129982a19df4284ceac6fe87353ca3ca6b4ca77ff7d697209ae0a5915e"}, - {file = "SQLAlchemy-2.0.25-cp38-cp38-win_amd64.whl", hash = "sha256:c55731c116806836a5d678a70c84cb13f2cedba920212ba7dcad53260997666d"}, - {file = "SQLAlchemy-2.0.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:605b6b059f4b57b277f75ace81cc5bc6335efcbcc4ccb9066695e515dbdb3900"}, - {file = "SQLAlchemy-2.0.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:665f0a3954635b5b777a55111ababf44b4fc12b1f3ba0a435b602b6387ffd7cf"}, - {file = "SQLAlchemy-2.0.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecf6d4cda1f9f6cb0b45803a01ea7f034e2f1aed9475e883410812d9f9e3cfcf"}, - {file = "SQLAlchemy-2.0.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c51db269513917394faec5e5c00d6f83829742ba62e2ac4fa5c98d58be91662f"}, - {file = "SQLAlchemy-2.0.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:790f533fa5c8901a62b6fef5811d48980adeb2f51f1290ade8b5e7ba990ba3de"}, - {file = "SQLAlchemy-2.0.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1b1180cda6df7af84fe72e4530f192231b1f29a7496951db4ff38dac1687202d"}, - {file = "SQLAlchemy-2.0.25-cp39-cp39-win32.whl", hash = "sha256:555651adbb503ac7f4cb35834c5e4ae0819aab2cd24857a123370764dc7d7e24"}, - {file = "SQLAlchemy-2.0.25-cp39-cp39-win_amd64.whl", hash = "sha256:dc55990143cbd853a5d038c05e79284baedf3e299661389654551bd02a6a68d7"}, - {file = "SQLAlchemy-2.0.25-py3-none-any.whl", hash = "sha256:a86b4240e67d4753dc3092d9511886795b3c2852abe599cffe108952f7af7ac3"}, - {file = "SQLAlchemy-2.0.25.tar.gz", hash = "sha256:a2c69a7664fb2d54b8682dd774c3b54f67f84fa123cf84dda2a5f40dcaa04e08"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3b48154678e76445c7ded1896715ce05319f74b1e73cf82d4f8b59b46e9c0ddc"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2753743c2afd061bb95a61a51bbb6a1a11ac1c44292fad898f10c9839a7f75b2"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7bfc726d167f425d4c16269a9a10fe8630ff6d14b683d588044dcef2d0f6be7"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4f61ada6979223013d9ab83a3ed003ded6959eae37d0d685db2c147e9143797"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a365eda439b7a00732638f11072907c1bc8e351c7665e7e5da91b169af794af"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bba002a9447b291548e8d66fd8c96a6a7ed4f2def0bb155f4f0a1309fd2735d5"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-win32.whl", hash = "sha256:0138c5c16be3600923fa2169532205d18891b28afa817cb49b50e08f62198bb8"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-win_amd64.whl", hash = "sha256:99650e9f4cf3ad0d409fed3eec4f071fadd032e9a5edc7270cd646a26446feeb"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:955991a09f0992c68a499791a753523f50f71a6885531568404fa0f231832aa0"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f69e4c756ee2686767eb80f94c0125c8b0a0b87ede03eacc5c8ae3b54b99dc46"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69c9db1ce00e59e8dd09d7bae852a9add716efdc070a3e2068377e6ff0d6fdaa"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1429a4b0f709f19ff3b0cf13675b2b9bfa8a7e79990003207a011c0db880a13"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:efedba7e13aa9a6c8407c48facfdfa108a5a4128e35f4c68f20c3407e4376aa9"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:16863e2b132b761891d6c49f0a0f70030e0bcac4fd208117f6b7e053e68668d0"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-win32.whl", hash = "sha256:2ecabd9ccaa6e914e3dbb2aa46b76dede7eadc8cbf1b8083c94d936bcd5ffb49"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-win_amd64.whl", hash = "sha256:0b3f4c438e37d22b83e640f825ef0f37b95db9aa2d68203f2c9549375d0b2260"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5a79d65395ac5e6b0c2890935bad892eabb911c4aa8e8015067ddb37eea3d56c"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9a5baf9267b752390252889f0c802ea13b52dfee5e369527da229189b8bd592e"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cb5a646930c5123f8461f6468901573f334c2c63c795b9af350063a736d0134"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:296230899df0b77dec4eb799bcea6fbe39a43707ce7bb166519c97b583cfcab3"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c62d401223f468eb4da32627bffc0c78ed516b03bb8a34a58be54d618b74d472"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3b69e934f0f2b677ec111b4d83f92dc1a3210a779f69bf905273192cf4ed433e"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-win32.whl", hash = "sha256:77d2edb1f54aff37e3318f611637171e8ec71472f1fdc7348b41dcb226f93d90"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-win_amd64.whl", hash = "sha256:b6c7ec2b1f4969fc19b65b7059ed00497e25f54069407a8701091beb69e591a5"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5a8e3b0a7e09e94be7510d1661339d6b52daf202ed2f5b1f9f48ea34ee6f2d57"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b60203c63e8f984df92035610c5fb76d941254cf5d19751faab7d33b21e5ddc0"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1dc3eabd8c0232ee8387fbe03e0a62220a6f089e278b1f0aaf5e2d6210741ad"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:40ad017c672c00b9b663fcfcd5f0864a0a97828e2ee7ab0c140dc84058d194cf"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e42203d8d20dc704604862977b1470a122e4892791fe3ed165f041e4bf447a1b"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-win32.whl", hash = "sha256:2a4f4da89c74435f2bc61878cd08f3646b699e7d2eba97144030d1be44e27584"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-win_amd64.whl", hash = "sha256:b6bf767d14b77f6a18b6982cbbf29d71bede087edae495d11ab358280f304d8e"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc0c53579650a891f9b83fa3cecd4e00218e071d0ba00c4890f5be0c34887ed3"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:311710f9a2ee235f1403537b10c7687214bb1f2b9ebb52702c5aa4a77f0b3af7"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:408f8b0e2c04677e9c93f40eef3ab22f550fecb3011b187f66a096395ff3d9fd"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37a4b4fb0dd4d2669070fb05b8b8824afd0af57587393015baee1cf9890242d9"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a943d297126c9230719c27fcbbeab57ecd5d15b0bd6bfd26e91bfcfe64220621"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0a089e218654e740a41388893e090d2e2c22c29028c9d1353feb38638820bbeb"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-win32.whl", hash = "sha256:fa561138a64f949f3e889eb9ab8c58e1504ab351d6cf55259dc4c248eaa19da6"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-win_amd64.whl", hash = "sha256:7d74336c65705b986d12a7e337ba27ab2b9d819993851b140efdf029248e818e"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae8c62fe2480dd61c532ccafdbce9b29dacc126fe8be0d9a927ca3e699b9491a"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2383146973a15435e4717f94c7509982770e3e54974c71f76500a0136f22810b"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8409de825f2c3b62ab15788635ccaec0c881c3f12a8af2b12ae4910a0a9aeef6"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0094c5dc698a5f78d3d1539853e8ecec02516b62b8223c970c86d44e7a80f6c7"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:edc16a50f5e1b7a06a2dcc1f2205b0b961074c123ed17ebda726f376a5ab0953"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f7703c2010355dd28f53deb644a05fc30f796bd8598b43f0ba678878780b6e4c"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-win32.whl", hash = "sha256:1f9a727312ff6ad5248a4367358e2cf7e625e98b1028b1d7ab7b806b7d757513"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-win_amd64.whl", hash = "sha256:a0ef36b28534f2a5771191be6edb44cc2673c7b2edf6deac6562400288664221"}, + {file = "SQLAlchemy-2.0.30-py3-none-any.whl", hash = "sha256:7108d569d3990c71e26a42f60474b4c02c8586c4681af5fd67e51a044fdea86a"}, + {file = "SQLAlchemy-2.0.30.tar.gz", hash = "sha256:2b1708916730f4830bc69d6f49d37f7698b5bd7530aca7f04f785f8849e95255"}, ] [package.dependencies] @@ -1922,174 +3025,235 @@ postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] pymysql = ["pymysql"] sqlcipher = ["sqlcipher3_binary"] +[[package]] +name = "stack-data" +version = "0.6.3" +description = "Extract data from python stack frames and tracebacks for informative displays" +optional = false +python-versions = "*" +files = [ + {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, + {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, +] + +[package.dependencies] +asttokens = ">=2.1.0" +executing = ">=1.2.0" +pure-eval = "*" + +[package.extras] +tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] + [[package]] name = "starlette" -version = "0.27.0" +version = "0.37.2" description = "The little ASGI library that shines." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"}, - {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"}, + {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"}, + {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"}, ] [package.dependencies] anyio = ">=3.4.0,<5" -typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [package.extras] -full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] +full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"] [[package]] name = "tenacity" -version = "8.2.3" +version = "8.3.0" description = "Retry code until it succeeds" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tenacity-8.2.3-py3-none-any.whl", hash = "sha256:ce510e327a630c9e1beaf17d42e6ffacc88185044ad85cf74c0a8887c6a0f88c"}, - {file = "tenacity-8.2.3.tar.gz", hash = "sha256:5398ef0d78e63f40007c1fb4c0bff96e1911394d2fa8d194f77619c05ff6cc8a"}, + {file = "tenacity-8.3.0-py3-none-any.whl", hash = "sha256:3649f6443dbc0d9b01b9d8020a9c4ec7a1ff5f6f3c6c8a036ef371f573fe9185"}, + {file = "tenacity-8.3.0.tar.gz", hash = "sha256:953d4e6ad24357bceffbc9707bc74349aca9d245f68eb65419cf0c249a1949a2"}, ] [package.extras] -doc = ["reno", "sphinx", "tornado (>=4.5)"] +doc = ["reno", "sphinx"] +test = ["pytest", "tornado (>=4.5)", "typeguard"] + +[[package]] +name = "tiktoken" +version = "0.7.0" +description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tiktoken-0.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485f3cc6aba7c6b6ce388ba634fbba656d9ee27f766216f45146beb4ac18b25f"}, + {file = "tiktoken-0.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e54be9a2cd2f6d6ffa3517b064983fb695c9a9d8aa7d574d1ef3c3f931a99225"}, + {file = "tiktoken-0.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79383a6e2c654c6040e5f8506f3750db9ddd71b550c724e673203b4f6b4b4590"}, + {file = "tiktoken-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d4511c52caacf3c4981d1ae2df85908bd31853f33d30b345c8b6830763f769c"}, + {file = "tiktoken-0.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13c94efacdd3de9aff824a788353aa5749c0faee1fbe3816df365ea450b82311"}, + {file = "tiktoken-0.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8e58c7eb29d2ab35a7a8929cbeea60216a4ccdf42efa8974d8e176d50c9a3df5"}, + {file = "tiktoken-0.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:21a20c3bd1dd3e55b91c1331bf25f4af522c525e771691adbc9a69336fa7f702"}, + {file = "tiktoken-0.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:10c7674f81e6e350fcbed7c09a65bca9356eaab27fb2dac65a1e440f2bcfe30f"}, + {file = "tiktoken-0.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:084cec29713bc9d4189a937f8a35dbdfa785bd1235a34c1124fe2323821ee93f"}, + {file = "tiktoken-0.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:811229fde1652fedcca7c6dfe76724d0908775b353556d8a71ed74d866f73f7b"}, + {file = "tiktoken-0.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86b6e7dc2e7ad1b3757e8a24597415bafcfb454cebf9a33a01f2e6ba2e663992"}, + {file = "tiktoken-0.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1063c5748be36344c7e18c7913c53e2cca116764c2080177e57d62c7ad4576d1"}, + {file = "tiktoken-0.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:20295d21419bfcca092644f7e2f2138ff947a6eb8cfc732c09cc7d76988d4a89"}, + {file = "tiktoken-0.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:959d993749b083acc57a317cbc643fb85c014d055b2119b739487288f4e5d1cb"}, + {file = "tiktoken-0.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:71c55d066388c55a9c00f61d2c456a6086673ab7dec22dd739c23f77195b1908"}, + {file = "tiktoken-0.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:09ed925bccaa8043e34c519fbb2f99110bd07c6fd67714793c21ac298e449410"}, + {file = "tiktoken-0.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03c6c40ff1db0f48a7b4d2dafeae73a5607aacb472fa11f125e7baf9dce73704"}, + {file = "tiktoken-0.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d20b5c6af30e621b4aca094ee61777a44118f52d886dbe4f02b70dfe05c15350"}, + {file = "tiktoken-0.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d427614c3e074004efa2f2411e16c826f9df427d3c70a54725cae860f09e4bf4"}, + {file = "tiktoken-0.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8c46d7af7b8c6987fac9b9f61041b452afe92eb087d29c9ce54951280f899a97"}, + {file = "tiktoken-0.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:0bc603c30b9e371e7c4c7935aba02af5994a909fc3c0fe66e7004070858d3f8f"}, + {file = "tiktoken-0.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2398fecd38c921bcd68418675a6d155fad5f5e14c2e92fcf5fe566fa5485a858"}, + {file = "tiktoken-0.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f5f6afb52fb8a7ea1c811e435e4188f2bef81b5e0f7a8635cc79b0eef0193d6"}, + {file = "tiktoken-0.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:861f9ee616766d736be4147abac500732b505bf7013cfaf019b85892637f235e"}, + {file = "tiktoken-0.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54031f95c6939f6b78122c0aa03a93273a96365103793a22e1793ee86da31685"}, + {file = "tiktoken-0.7.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fffdcb319b614cf14f04d02a52e26b1d1ae14a570f90e9b55461a72672f7b13d"}, + {file = "tiktoken-0.7.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c72baaeaefa03ff9ba9688624143c858d1f6b755bb85d456d59e529e17234769"}, + {file = "tiktoken-0.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:131b8aeb043a8f112aad9f46011dced25d62629091e51d9dc1adbf4a1cc6aa98"}, + {file = "tiktoken-0.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cabc6dc77460df44ec5b879e68692c63551ae4fae7460dd4ff17181df75f1db7"}, + {file = "tiktoken-0.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8d57f29171255f74c0aeacd0651e29aa47dff6f070cb9f35ebc14c82278f3b25"}, + {file = "tiktoken-0.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ee92776fdbb3efa02a83f968c19d4997a55c8e9ce7be821ceee04a1d1ee149c"}, + {file = "tiktoken-0.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e215292e99cb41fbc96988ef62ea63bb0ce1e15f2c147a61acc319f8b4cbe5bf"}, + {file = "tiktoken-0.7.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8a81bac94769cab437dd3ab0b8a4bc4e0f9cf6835bcaa88de71f39af1791727a"}, + {file = "tiktoken-0.7.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d6d73ea93e91d5ca771256dfc9d1d29f5a554b83821a1dc0891987636e0ae226"}, + {file = "tiktoken-0.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:2bcb28ddf79ffa424f171dfeef9a4daff61a94c631ca6813f43967cb263b83b9"}, + {file = "tiktoken-0.7.0.tar.gz", hash = "sha256:1077266e949c24e0291f6c350433c6f0971365ece2b173a23bc3b9f9defef6b6"}, +] + +[package.dependencies] +regex = ">=2022.1.18" +requests = ">=2.26.0" + +[package.extras] +blobfile = ["blobfile (>=2)"] [[package]] name = "tokenizers" -version = "0.15.1" +version = "0.19.1" description = "" optional = false python-versions = ">=3.7" files = [ - {file = "tokenizers-0.15.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:32c9491dd1bcb33172c26b454dbd607276af959b9e78fa766e2694cafab3103c"}, - {file = "tokenizers-0.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29a1b784b870a097e7768f8c20c2dd851e2c75dad3efdae69a79d3e7f1d614d5"}, - {file = "tokenizers-0.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0049fbe648af04148b08cb211994ce8365ee628ce49724b56aaefd09a3007a78"}, - {file = "tokenizers-0.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e84b3c235219e75e24de6b71e6073cd2c8d740b14d88e4c6d131b90134e3a338"}, - {file = "tokenizers-0.15.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8cc575769ea11d074308c6d71cb10b036cdaec941562c07fc7431d956c502f0e"}, - {file = "tokenizers-0.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22bf28f299c4158e6d0b5eaebddfd500c4973d947ffeaca8bcbe2e8c137dff0b"}, - {file = "tokenizers-0.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:506555f98361db9c74e1323a862d77dcd7d64c2058829a368bf4159d986e339f"}, - {file = "tokenizers-0.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7061b0a28ade15906f5b2ec8c48d3bdd6e24eca6b427979af34954fbe31d5cef"}, - {file = "tokenizers-0.15.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7ed5e35507b7a0e2aac3285c4f5e37d4ec5cfc0e5825b862b68a0aaf2757af52"}, - {file = "tokenizers-0.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1c9df9247df0de6509dd751b1c086e5f124b220133b5c883bb691cb6fb3d786f"}, - {file = "tokenizers-0.15.1-cp310-none-win32.whl", hash = "sha256:dd999af1b4848bef1b11d289f04edaf189c269d5e6afa7a95fa1058644c3f021"}, - {file = "tokenizers-0.15.1-cp310-none-win_amd64.whl", hash = "sha256:39d06a57f7c06940d602fad98702cf7024c4eee7f6b9fe76b9f2197d5a4cc7e2"}, - {file = "tokenizers-0.15.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8ad034eb48bf728af06915e9294871f72fcc5254911eddec81d6df8dba1ce055"}, - {file = "tokenizers-0.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea9ede7c42f8fa90f31bfc40376fd91a7d83a4aa6ad38e6076de961d48585b26"}, - {file = "tokenizers-0.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b85d6fe1a20d903877aa0ef32ef6b96e81e0e48b71c206d6046ce16094de6970"}, - {file = "tokenizers-0.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a7d44f656320137c7d643b9c7dcc1814763385de737fb98fd2643880910f597"}, - {file = "tokenizers-0.15.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd244bd0793cdacf27ee65ec3db88c21f5815460e8872bbeb32b040469d6774e"}, - {file = "tokenizers-0.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3f4a36e371b3cb1123adac8aeeeeab207ad32f15ed686d9d71686a093bb140"}, - {file = "tokenizers-0.15.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2921a53966afb29444da98d56a6ccbef23feb3b0c0f294b4e502370a0a64f25"}, - {file = "tokenizers-0.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f49068cf51f49c231067f1a8c9fc075ff960573f6b2a956e8e1b0154fb638ea5"}, - {file = "tokenizers-0.15.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0ab1a22f20eaaab832ab3b00a0709ca44a0eb04721e580277579411b622c741c"}, - {file = "tokenizers-0.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:671268f24b607c4adc6fa2b5b580fd4211b9f84b16bd7f46d62f8e5be0aa7ba4"}, - {file = "tokenizers-0.15.1-cp311-none-win32.whl", hash = "sha256:a4f03e33d2bf7df39c8894032aba599bf90f6f6378e683a19d28871f09bb07fc"}, - {file = "tokenizers-0.15.1-cp311-none-win_amd64.whl", hash = "sha256:30f689537bcc7576d8bd4daeeaa2cb8f36446ba2f13f421b173e88f2d8289c4e"}, - {file = "tokenizers-0.15.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f3a379dd0898a82ea3125e8f9c481373f73bffce6430d4315f0b6cd5547e409"}, - {file = "tokenizers-0.15.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d870ae58bba347d38ac3fc8b1f662f51e9c95272d776dd89f30035c83ee0a4f"}, - {file = "tokenizers-0.15.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d6d28e0143ec2e253a8a39e94bf1d24776dbe73804fa748675dbffff4a5cd6d8"}, - {file = "tokenizers-0.15.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61ae9ac9f44e2da128ee35db69489883b522f7abe033733fa54eb2de30dac23d"}, - {file = "tokenizers-0.15.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d8e322a47e29128300b3f7749a03c0ec2bce0a3dc8539ebff738d3f59e233542"}, - {file = "tokenizers-0.15.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:760334f475443bc13907b1a8e1cb0aeaf88aae489062546f9704dce6c498bfe2"}, - {file = "tokenizers-0.15.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1b173753d4aca1e7d0d4cb52b5e3ffecfb0ca014e070e40391b6bb4c1d6af3f2"}, - {file = "tokenizers-0.15.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82c1f13d457c8f0ab17e32e787d03470067fe8a3b4d012e7cc57cb3264529f4a"}, - {file = "tokenizers-0.15.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:425b46ceff4505f20191df54b50ac818055d9d55023d58ae32a5d895b6f15bb0"}, - {file = "tokenizers-0.15.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:681ac6ba3b4fdaf868ead8971221a061f580961c386e9732ea54d46c7b72f286"}, - {file = "tokenizers-0.15.1-cp312-none-win32.whl", hash = "sha256:f2272656063ccfba2044df2115095223960d80525d208e7a32f6c01c351a6f4a"}, - {file = "tokenizers-0.15.1-cp312-none-win_amd64.whl", hash = "sha256:9abe103203b1c6a2435d248d5ff4cceebcf46771bfbc4957a98a74da6ed37674"}, - {file = "tokenizers-0.15.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:2ce9ed5c8ef26b026a66110e3c7b73d93ec2d26a0b1d0ea55ddce61c0e5f446f"}, - {file = "tokenizers-0.15.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:89b24d366137986c3647baac29ef902d2d5445003d11c30df52f1bd304689aeb"}, - {file = "tokenizers-0.15.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0faebedd01b413ab777ca0ee85914ed8b031ea5762ab0ea60b707ce8b9be6842"}, - {file = "tokenizers-0.15.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdbd9dfcdad4f3b95d801f768e143165165055c18e44ca79a8a26de889cd8e85"}, - {file = "tokenizers-0.15.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:97194324c12565b07e9993ca9aa813b939541185682e859fb45bb8d7d99b3193"}, - {file = "tokenizers-0.15.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:485e43e2cc159580e0d83fc919ec3a45ae279097f634b1ffe371869ffda5802c"}, - {file = "tokenizers-0.15.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:191d084d60e3589d6420caeb3f9966168269315f8ec7fbc3883122dc9d99759d"}, - {file = "tokenizers-0.15.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01c28cc8d7220634a75b14c53f4fc9d1b485f99a5a29306a999c115921de2897"}, - {file = "tokenizers-0.15.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:325212027745d3f8d5d5006bb9e5409d674eb80a184f19873f4f83494e1fdd26"}, - {file = "tokenizers-0.15.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:3c5573603c36ce12dbe318bcfb490a94cad2d250f34deb2f06cb6937957bbb71"}, - {file = "tokenizers-0.15.1-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:1441161adb6d71a15a630d5c1d8659d5ebe41b6b209586fbeea64738e58fcbb2"}, - {file = "tokenizers-0.15.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:382a8d0c31afcfb86571afbfefa37186df90865ce3f5b731842dab4460e53a38"}, - {file = "tokenizers-0.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e76959783e3f4ec73b3f3d24d4eec5aa9225f0bee565c48e77f806ed1e048f12"}, - {file = "tokenizers-0.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:401df223e5eb927c5961a0fc6b171818a2bba01fb36ef18c3e1b69b8cd80e591"}, - {file = "tokenizers-0.15.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c52606c233c759561a16e81b2290a7738c3affac7a0b1f0a16fe58dc22e04c7d"}, - {file = "tokenizers-0.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b72c658bbe5a05ed8bc2ac5ad782385bfd743ffa4bc87d9b5026341e709c6f44"}, - {file = "tokenizers-0.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:25f5643a2f005c42f0737a326c6c6bdfedfdc9a994b10a1923d9c3e792e4d6a6"}, - {file = "tokenizers-0.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c5b6f633999d6b42466bbfe21be2e26ad1760b6f106967a591a41d8cbca980e"}, - {file = "tokenizers-0.15.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ceb5c9ad11a015150b545c1a11210966a45b8c3d68a942e57cf8938c578a77ca"}, - {file = "tokenizers-0.15.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bedd4ce0c4872db193444c395b11c7697260ce86a635ab6d48102d76be07d324"}, - {file = "tokenizers-0.15.1-cp37-none-win32.whl", hash = "sha256:cd6caef6c14f5ed6d35f0ddb78eab8ca6306d0cd9870330bccff72ad014a6f42"}, - {file = "tokenizers-0.15.1-cp37-none-win_amd64.whl", hash = "sha256:d2bd7af78f58d75a55e5df61efae164ab9200c04b76025f9cc6eeb7aff3219c2"}, - {file = "tokenizers-0.15.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:59b3ca6c02e0bd5704caee274978bd055de2dff2e2f39dadf536c21032dfd432"}, - {file = "tokenizers-0.15.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:48fe21b67c22583bed71933a025fd66b1f5cfae1baefa423c3d40379b5a6e74e"}, - {file = "tokenizers-0.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3d190254c66a20fb1efbdf035e6333c5e1f1c73b1f7bfad88f9c31908ac2c2c4"}, - {file = "tokenizers-0.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fef90c8f5abf17d48d6635f5fd92ad258acd1d0c2d920935c8bf261782cfe7c8"}, - {file = "tokenizers-0.15.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fac011ef7da3357aa7eb19efeecf3d201ede9618f37ddedddc5eb809ea0963ca"}, - {file = "tokenizers-0.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:574ec5b3e71d1feda6b0ecac0e0445875729b4899806efbe2b329909ec75cb50"}, - {file = "tokenizers-0.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aca16c3c0637c051a59ea99c4253f16fbb43034fac849076a7e7913b2b9afd2d"}, - {file = "tokenizers-0.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a6f238fc2bbfd3e12e8529980ec1624c7e5b69d4e959edb3d902f36974f725a"}, - {file = "tokenizers-0.15.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:587e11a26835b73c31867a728f32ca8a93c9ded4a6cd746516e68b9d51418431"}, - {file = "tokenizers-0.15.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6456e7ad397352775e2efdf68a9ec5d6524bbc4543e926eef428d36de627aed4"}, - {file = "tokenizers-0.15.1-cp38-none-win32.whl", hash = "sha256:614f0da7dd73293214bd143e6221cafd3f7790d06b799f33a987e29d057ca658"}, - {file = "tokenizers-0.15.1-cp38-none-win_amd64.whl", hash = "sha256:a4fa0a20d9f69cc2bf1cfce41aa40588598e77ec1d6f56bf0eb99769969d1ede"}, - {file = "tokenizers-0.15.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:8d3f18a45e0cf03ce193d5900460dc2430eec4e14c786e5d79bddba7ea19034f"}, - {file = "tokenizers-0.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:38dbd6c38f88ad7d5dc5d70c764415d38fe3bcd99dc81638b572d093abc54170"}, - {file = "tokenizers-0.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:777286b1f7e52de92aa4af49fe31046cfd32885d1bbaae918fab3bba52794c33"}, - {file = "tokenizers-0.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58d4d550a3862a47dd249892d03a025e32286eb73cbd6bc887fb8fb64bc97165"}, - {file = "tokenizers-0.15.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4eda68ce0344f35042ae89220b40a0007f721776b727806b5c95497b35714bb7"}, - {file = "tokenizers-0.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cd33d15f7a3a784c3b665cfe807b8de3c6779e060349bd5005bb4ae5bdcb437"}, - {file = "tokenizers-0.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a1aa370f978ac0bfb50374c3a40daa93fd56d47c0c70f0c79607fdac2ccbb42"}, - {file = "tokenizers-0.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:241482b940340fff26a2708cb9ba383a5bb8a2996d67a0ff2c4367bf4b86cc3a"}, - {file = "tokenizers-0.15.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:68f30b05f46a4d9aba88489eadd021904afe90e10a7950e28370d6e71b9db021"}, - {file = "tokenizers-0.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5a3c5d8025529670462b881b7b2527aacb6257398c9ec8e170070432c3ae3a82"}, - {file = "tokenizers-0.15.1-cp39-none-win32.whl", hash = "sha256:74d1827830f60a9d78da8f6d49a1fbea5422ce0eea42e2617877d23380a7efbc"}, - {file = "tokenizers-0.15.1-cp39-none-win_amd64.whl", hash = "sha256:9ff499923e4d6876d6b6a63ea84a56805eb35e91dd89b933a7aee0c56a3838c6"}, - {file = "tokenizers-0.15.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b3aa007a0f4408f62a8471bdaa3faccad644cbf2622639f2906b4f9b5339e8b8"}, - {file = "tokenizers-0.15.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f3d4176fa93d8b2070db8f3c70dc21106ae6624fcaaa334be6bdd3a0251e729e"}, - {file = "tokenizers-0.15.1-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1d0e463655ef8b2064df07bd4a445ed7f76f6da3b286b4590812587d42f80e89"}, - {file = "tokenizers-0.15.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:089138fd0351b62215c462a501bd68b8df0e213edcf99ab9efd5dba7b4cb733e"}, - {file = "tokenizers-0.15.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e563ac628f5175ed08e950430e2580e544b3e4b606a0995bb6b52b3a3165728"}, - {file = "tokenizers-0.15.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:244dcc28c5fde221cb4373961b20da30097669005b122384d7f9f22752487a46"}, - {file = "tokenizers-0.15.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d82951d46052dddae1369e68ff799a0e6e29befa9a0b46e387ae710fd4daefb0"}, - {file = "tokenizers-0.15.1-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7b14296bc9059849246ceb256ffbe97f8806a9b5d707e0095c22db312f4fc014"}, - {file = "tokenizers-0.15.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0309357bb9b6c8d86cdf456053479d7112074b470651a997a058cd7ad1c4ea57"}, - {file = "tokenizers-0.15.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:083f06e9d8d01b70b67bcbcb7751b38b6005512cce95808be6bf34803534a7e7"}, - {file = "tokenizers-0.15.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85288aea86ada579789447f0dcec108ebef8da4b450037eb4813d83e4da9371e"}, - {file = "tokenizers-0.15.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:385e6fcb01e8de90c1d157ae2a5338b23368d0b1c4cc25088cdca90147e35d17"}, - {file = "tokenizers-0.15.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:60067edfcbf7d6cd448ac47af41ec6e84377efbef7be0c06f15a7c1dd069e044"}, - {file = "tokenizers-0.15.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5f7e37f89acfe237d4eaf93c3b69b0f01f407a7a5d0b5a8f06ba91943ea3cf10"}, - {file = "tokenizers-0.15.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:6a63a15b523d42ebc1f4028e5a568013388c2aefa4053a263e511cb10aaa02f1"}, - {file = "tokenizers-0.15.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2417d9e4958a6c2fbecc34c27269e74561c55d8823bf914b422e261a11fdd5fd"}, - {file = "tokenizers-0.15.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8550974bace6210e41ab04231e06408cf99ea4279e0862c02b8d47e7c2b2828"}, - {file = "tokenizers-0.15.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:194ba82129b171bcd29235a969e5859a93e491e9b0f8b2581f500f200c85cfdd"}, - {file = "tokenizers-0.15.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:1bfd95eef8b01e6c0805dbccc8eaf41d8c5a84f0cce72c0ab149fe76aae0bce6"}, - {file = "tokenizers-0.15.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b87a15dd72f8216b03c151e3dace00c75c3fe7b0ee9643c25943f31e582f1a34"}, - {file = "tokenizers-0.15.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6ac22f358a0c2a6c685be49136ce7ea7054108986ad444f567712cf274b34cd8"}, - {file = "tokenizers-0.15.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1e9d1f046a9b9d9a95faa103f07db5921d2c1c50f0329ebba4359350ee02b18b"}, - {file = "tokenizers-0.15.1-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a0fd30a4b74485f6a7af89fffb5fb84d6d5f649b3e74f8d37f624cc9e9e97cf"}, - {file = "tokenizers-0.15.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80e45dc206b9447fa48795a1247c69a1732d890b53e2cc51ba42bc2fefa22407"}, - {file = "tokenizers-0.15.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4eaff56ef3e218017fa1d72007184401f04cb3a289990d2b6a0a76ce71c95f96"}, - {file = "tokenizers-0.15.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:b41dc107e4a4e9c95934e79b025228bbdda37d9b153d8b084160e88d5e48ad6f"}, - {file = "tokenizers-0.15.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:1922b8582d0c33488764bcf32e80ef6054f515369e70092729c928aae2284bc2"}, - {file = "tokenizers-0.15.1.tar.gz", hash = "sha256:c0a331d6d5a3d6e97b7f99f562cee8d56797180797bc55f12070e495e717c980"}, -] - -[package.dependencies] -huggingface_hub = ">=0.16.4,<1.0" + {file = "tokenizers-0.19.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:952078130b3d101e05ecfc7fc3640282d74ed26bcf691400f872563fca15ac97"}, + {file = "tokenizers-0.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82c8b8063de6c0468f08e82c4e198763e7b97aabfe573fd4cf7b33930ca4df77"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f03727225feaf340ceeb7e00604825addef622d551cbd46b7b775ac834c1e1c4"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:453e4422efdfc9c6b6bf2eae00d5e323f263fff62b29a8c9cd526c5003f3f642"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:02e81bf089ebf0e7f4df34fa0207519f07e66d8491d963618252f2e0729e0b46"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b07c538ba956843833fee1190cf769c60dc62e1cf934ed50d77d5502194d63b1"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e28cab1582e0eec38b1f38c1c1fb2e56bce5dc180acb1724574fc5f47da2a4fe"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b01afb7193d47439f091cd8f070a1ced347ad0f9144952a30a41836902fe09e"}, + {file = "tokenizers-0.19.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7fb297edec6c6841ab2e4e8f357209519188e4a59b557ea4fafcf4691d1b4c98"}, + {file = "tokenizers-0.19.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2e8a3dd055e515df7054378dc9d6fa8c8c34e1f32777fb9a01fea81496b3f9d3"}, + {file = "tokenizers-0.19.1-cp310-none-win32.whl", hash = "sha256:7ff898780a155ea053f5d934925f3902be2ed1f4d916461e1a93019cc7250837"}, + {file = "tokenizers-0.19.1-cp310-none-win_amd64.whl", hash = "sha256:bea6f9947e9419c2fda21ae6c32871e3d398cba549b93f4a65a2d369662d9403"}, + {file = "tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5c88d1481f1882c2e53e6bb06491e474e420d9ac7bdff172610c4f9ad3898059"}, + {file = "tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ddf672ed719b4ed82b51499100f5417d7d9f6fb05a65e232249268f35de5ed14"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:dadc509cc8a9fe460bd274c0e16ac4184d0958117cf026e0ea8b32b438171594"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfedf31824ca4915b511b03441784ff640378191918264268e6923da48104acc"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac11016d0a04aa6487b1513a3a36e7bee7eec0e5d30057c9c0408067345c48d2"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76951121890fea8330d3a0df9a954b3f2a37e3ec20e5b0530e9a0044ca2e11fe"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b342d2ce8fc8d00f376af068e3274e2e8649562e3bc6ae4a67784ded6b99428d"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d16ff18907f4909dca9b076b9c2d899114dd6abceeb074eca0c93e2353f943aa"}, + {file = "tokenizers-0.19.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:706a37cc5332f85f26efbe2bdc9ef8a9b372b77e4645331a405073e4b3a8c1c6"}, + {file = "tokenizers-0.19.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:16baac68651701364b0289979ecec728546133e8e8fe38f66fe48ad07996b88b"}, + {file = "tokenizers-0.19.1-cp311-none-win32.whl", hash = "sha256:9ed240c56b4403e22b9584ee37d87b8bfa14865134e3e1c3fb4b2c42fafd3256"}, + {file = "tokenizers-0.19.1-cp311-none-win_amd64.whl", hash = "sha256:ad57d59341710b94a7d9dbea13f5c1e7d76fd8d9bcd944a7a6ab0b0da6e0cc66"}, + {file = "tokenizers-0.19.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:621d670e1b1c281a1c9698ed89451395d318802ff88d1fc1accff0867a06f153"}, + {file = "tokenizers-0.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d924204a3dbe50b75630bd16f821ebda6a5f729928df30f582fb5aade90c818a"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4f3fefdc0446b1a1e6d81cd4c07088ac015665d2e812f6dbba4a06267d1a2c95"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9620b78e0b2d52ef07b0d428323fb34e8ea1219c5eac98c2596311f20f1f9266"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04ce49e82d100594715ac1b2ce87d1a36e61891a91de774755f743babcd0dd52"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5c2ff13d157afe413bf7e25789879dd463e5a4abfb529a2d8f8473d8042e28f"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3174c76efd9d08f836bfccaca7cfec3f4d1c0a4cf3acbc7236ad577cc423c840"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c9d5b6c0e7a1e979bec10ff960fae925e947aab95619a6fdb4c1d8ff3708ce3"}, + {file = "tokenizers-0.19.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a179856d1caee06577220ebcfa332af046d576fb73454b8f4d4b0ba8324423ea"}, + {file = "tokenizers-0.19.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:952b80dac1a6492170f8c2429bd11fcaa14377e097d12a1dbe0ef2fb2241e16c"}, + {file = "tokenizers-0.19.1-cp312-none-win32.whl", hash = "sha256:01d62812454c188306755c94755465505836fd616f75067abcae529c35edeb57"}, + {file = "tokenizers-0.19.1-cp312-none-win_amd64.whl", hash = "sha256:b70bfbe3a82d3e3fb2a5e9b22a39f8d1740c96c68b6ace0086b39074f08ab89a"}, + {file = "tokenizers-0.19.1-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:bb9dfe7dae85bc6119d705a76dc068c062b8b575abe3595e3c6276480e67e3f1"}, + {file = "tokenizers-0.19.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:1f0360cbea28ea99944ac089c00de7b2e3e1c58f479fb8613b6d8d511ce98267"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:71e3ec71f0e78780851fef28c2a9babe20270404c921b756d7c532d280349214"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b82931fa619dbad979c0ee8e54dd5278acc418209cc897e42fac041f5366d626"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e8ff5b90eabdcdaa19af697885f70fe0b714ce16709cf43d4952f1f85299e73a"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e742d76ad84acbdb1a8e4694f915fe59ff6edc381c97d6dfdd054954e3478ad4"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d8c5d59d7b59885eab559d5bc082b2985555a54cda04dda4c65528d90ad252ad"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b2da5c32ed869bebd990c9420df49813709e953674c0722ff471a116d97b22d"}, + {file = "tokenizers-0.19.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:638e43936cc8b2cbb9f9d8dde0fe5e7e30766a3318d2342999ae27f68fdc9bd6"}, + {file = "tokenizers-0.19.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:78e769eb3b2c79687d9cb0f89ef77223e8e279b75c0a968e637ca7043a84463f"}, + {file = "tokenizers-0.19.1-cp37-none-win32.whl", hash = "sha256:72791f9bb1ca78e3ae525d4782e85272c63faaef9940d92142aa3eb79f3407a3"}, + {file = "tokenizers-0.19.1-cp37-none-win_amd64.whl", hash = "sha256:f3bbb7a0c5fcb692950b041ae11067ac54826204318922da754f908d95619fbc"}, + {file = "tokenizers-0.19.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:07f9295349bbbcedae8cefdbcfa7f686aa420be8aca5d4f7d1ae6016c128c0c5"}, + {file = "tokenizers-0.19.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:10a707cc6c4b6b183ec5dbfc5c34f3064e18cf62b4a938cb41699e33a99e03c1"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6309271f57b397aa0aff0cbbe632ca9d70430839ca3178bf0f06f825924eca22"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ad23d37d68cf00d54af184586d79b84075ada495e7c5c0f601f051b162112dc"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:427c4f0f3df9109314d4f75b8d1f65d9477033e67ffaec4bca53293d3aca286d"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e83a31c9cf181a0a3ef0abad2b5f6b43399faf5da7e696196ddd110d332519ee"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c27b99889bd58b7e301468c0838c5ed75e60c66df0d4db80c08f43462f82e0d3"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bac0b0eb952412b0b196ca7a40e7dce4ed6f6926489313414010f2e6b9ec2adf"}, + {file = "tokenizers-0.19.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8a6298bde623725ca31c9035a04bf2ef63208d266acd2bed8c2cb7d2b7d53ce6"}, + {file = "tokenizers-0.19.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:08a44864e42fa6d7d76d7be4bec62c9982f6f6248b4aa42f7302aa01e0abfd26"}, + {file = "tokenizers-0.19.1-cp38-none-win32.whl", hash = "sha256:1de5bc8652252d9357a666e609cb1453d4f8e160eb1fb2830ee369dd658e8975"}, + {file = "tokenizers-0.19.1-cp38-none-win_amd64.whl", hash = "sha256:0bcce02bf1ad9882345b34d5bd25ed4949a480cf0e656bbd468f4d8986f7a3f1"}, + {file = "tokenizers-0.19.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:0b9394bd204842a2a1fd37fe29935353742be4a3460b6ccbaefa93f58a8df43d"}, + {file = "tokenizers-0.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4692ab92f91b87769d950ca14dbb61f8a9ef36a62f94bad6c82cc84a51f76f6a"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6258c2ef6f06259f70a682491c78561d492e885adeaf9f64f5389f78aa49a051"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c85cf76561fbd01e0d9ea2d1cbe711a65400092bc52b5242b16cfd22e51f0c58"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:670b802d4d82bbbb832ddb0d41df7015b3e549714c0e77f9bed3e74d42400fbe"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:85aa3ab4b03d5e99fdd31660872249df5e855334b6c333e0bc13032ff4469c4a"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cbf001afbbed111a79ca47d75941e9e5361297a87d186cbfc11ed45e30b5daba"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4c89aa46c269e4e70c4d4f9d6bc644fcc39bb409cb2a81227923404dd6f5227"}, + {file = "tokenizers-0.19.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:39c1ec76ea1027438fafe16ecb0fb84795e62e9d643444c1090179e63808c69d"}, + {file = "tokenizers-0.19.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c2a0d47a89b48d7daa241e004e71fb5a50533718897a4cd6235cb846d511a478"}, + {file = "tokenizers-0.19.1-cp39-none-win32.whl", hash = "sha256:61b7fe8886f2e104d4caf9218b157b106207e0f2a4905c9c7ac98890688aabeb"}, + {file = "tokenizers-0.19.1-cp39-none-win_amd64.whl", hash = "sha256:f97660f6c43efd3e0bfd3f2e3e5615bf215680bad6ee3d469df6454b8c6e8256"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3b11853f17b54c2fe47742c56d8a33bf49ce31caf531e87ac0d7d13d327c9334"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d26194ef6c13302f446d39972aaa36a1dda6450bc8949f5eb4c27f51191375bd"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e8d1ed93beda54bbd6131a2cb363a576eac746d5c26ba5b7556bc6f964425594"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca407133536f19bdec44b3da117ef0d12e43f6d4b56ac4c765f37eca501c7bda"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce05fde79d2bc2e46ac08aacbc142bead21614d937aac950be88dc79f9db9022"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:35583cd46d16f07c054efd18b5d46af4a2f070a2dd0a47914e66f3ff5efb2b1e"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:43350270bfc16b06ad3f6f07eab21f089adb835544417afda0f83256a8bf8b75"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b4399b59d1af5645bcee2072a463318114c39b8547437a7c2d6a186a1b5a0e2d"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6852c5b2a853b8b0ddc5993cd4f33bfffdca4fcc5d52f89dd4b8eada99379285"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcd266ae85c3d39df2f7e7d0e07f6c41a55e9a3123bb11f854412952deacd828"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecb2651956eea2aa0a2d099434134b1b68f1c31f9a5084d6d53f08ed43d45ff2"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:b279ab506ec4445166ac476fb4d3cc383accde1ea152998509a94d82547c8e2a"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:89183e55fb86e61d848ff83753f64cded119f5d6e1f553d14ffee3700d0a4a49"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2edbc75744235eea94d595a8b70fe279dd42f3296f76d5a86dde1d46e35f574"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:0e64bfde9a723274e9a71630c3e9494ed7b4c0f76a1faacf7fe294cd26f7ae7c"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0b5ca92bfa717759c052e345770792d02d1f43b06f9e790ca0a1db62838816f3"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f8a20266e695ec9d7a946a019c1d5ca4eddb6613d4f466888eee04f16eedb85"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63c38f45d8f2a2ec0f3a20073cccb335b9f99f73b3c69483cd52ebc75369d8a1"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:dd26e3afe8a7b61422df3176e06664503d3f5973b94f45d5c45987e1cb711876"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:eddd5783a4a6309ce23432353cdb36220e25cbb779bfa9122320666508b44b88"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:56ae39d4036b753994476a1b935584071093b55c7a72e3b8288e68c313ca26e7"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f9939ca7e58c2758c01b40324a59c034ce0cebad18e0d4563a9b1beab3018243"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6c330c0eb815d212893c67a032e9dc1b38a803eccb32f3e8172c19cc69fbb439"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec11802450a2487cdf0e634b750a04cbdc1c4d066b97d94ce7dd2cb51ebb325b"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2b718f316b596f36e1dae097a7d5b91fc5b85e90bf08b01ff139bd8953b25af"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:ed69af290c2b65169f0ba9034d1dc39a5db9459b32f1dd8b5f3f32a3fcf06eab"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f8a9c828277133af13f3859d1b6bf1c3cb6e9e1637df0e45312e6b7c2e622b1f"}, + {file = "tokenizers-0.19.1.tar.gz", hash = "sha256:ee59e6680ed0fdbe6b724cf38bd70400a0c1dd623b07ac729087270caeac88e3"}, +] + +[package.dependencies] +huggingface-hub = ">=0.16.4,<1.0" [package.extras] dev = ["tokenizers[testing]"] -docs = ["setuptools_rust", "sphinx", "sphinx_rtd_theme"] -testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests"] +docs = ["setuptools-rust", "sphinx", "sphinx-rtd-theme"] +testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests", "ruff"] [[package]] name = "tqdm" -version = "4.66.1" +version = "4.66.4" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.7" files = [ - {file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"}, - {file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"}, + {file = "tqdm-4.66.4-py3-none-any.whl", hash = "sha256:b75ca56b413b030bc3f00af51fd2c1a1a5eac6a0c1cca83cbb37a5c52abce644"}, + {file = "tqdm-4.66.4.tar.gz", hash = "sha256:e4d936c9de8727928f3be6079590e97d9abfe8d39a590be678eb5919ffc186bb"}, ] [package.dependencies] @@ -2101,15 +3265,30 @@ notebook = ["ipywidgets (>=6)"] slack = ["slack-sdk"] telegram = ["requests"] +[[package]] +name = "traitlets" +version = "5.14.3" +description = "Traitlets Python configuration system" +optional = false +python-versions = ">=3.8" +files = [ + {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}, + {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"}, +] + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"] + [[package]] name = "twilio" -version = "8.12.0" +version = "9.1.0" description = "Twilio API client and TwiML generator" optional = false python-versions = ">=3.7.0" files = [ - {file = "twilio-8.12.0-py2.py3-none-any.whl", hash = "sha256:ccdf78b634dff13fd50b33bafd254a9dc2fb492c6b06839683e73f09ec110ec6"}, - {file = "twilio-8.12.0.tar.gz", hash = "sha256:28e3a743da18d5b298c9b9fb9e922404a60f8091441c5e0aa35bfefc46411370"}, + {file = "twilio-9.1.0-py2.py3-none-any.whl", hash = "sha256:eb4687a9f81dc3118e8981c5a46d9f8184baee135c79afed47c714c759c31bbc"}, + {file = "twilio-9.1.0.tar.gz", hash = "sha256:ab2eb19c779855bf02cdca8a7e02ebaa64feee47da7b591ac9088ec07a6962e2"}, ] [package.dependencies] @@ -2118,15 +3297,32 @@ aiohttp-retry = ">=2.8.3" PyJWT = ">=2.0.0,<3.0.0" requests = ">=2.0.0" +[[package]] +name = "typer" +version = "0.12.3" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +optional = false +python-versions = ">=3.7" +files = [ + {file = "typer-0.12.3-py3-none-any.whl", hash = "sha256:070d7ca53f785acbccba8e7d28b08dcd88f79f1fbda035ade0aecec71ca5c914"}, + {file = "typer-0.12.3.tar.gz", hash = "sha256:49e73131481d804288ef62598d97a1ceef3058905aa536a1134f90891ba35482"}, +] + +[package.dependencies] +click = ">=8.0.0" +rich = ">=10.11.0" +shellingham = ">=1.3.0" +typing-extensions = ">=3.7.4.3" + [[package]] name = "typing-extensions" -version = "4.9.0" +version = "4.12.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, - {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, + {file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"}, + {file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"}, ] [[package]] @@ -2144,192 +3340,474 @@ files = [ mypy-extensions = ">=0.3.0" typing-extensions = ">=3.7.4" +[[package]] +name = "ujson" +version = "5.10.0" +description = "Ultra fast JSON encoder and decoder for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "ujson-5.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2601aa9ecdbee1118a1c2065323bda35e2c5a2cf0797ef4522d485f9d3ef65bd"}, + {file = "ujson-5.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:348898dd702fc1c4f1051bc3aacbf894caa0927fe2c53e68679c073375f732cf"}, + {file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22cffecf73391e8abd65ef5f4e4dd523162a3399d5e84faa6aebbf9583df86d6"}, + {file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26b0e2d2366543c1bb4fbd457446f00b0187a2bddf93148ac2da07a53fe51569"}, + {file = "ujson-5.10.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:caf270c6dba1be7a41125cd1e4fc7ba384bf564650beef0df2dd21a00b7f5770"}, + {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a245d59f2ffe750446292b0094244df163c3dc96b3ce152a2c837a44e7cda9d1"}, + {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:94a87f6e151c5f483d7d54ceef83b45d3a9cca7a9cb453dbdbb3f5a6f64033f5"}, + {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:29b443c4c0a113bcbb792c88bea67b675c7ca3ca80c3474784e08bba01c18d51"}, + {file = "ujson-5.10.0-cp310-cp310-win32.whl", hash = "sha256:c18610b9ccd2874950faf474692deee4223a994251bc0a083c114671b64e6518"}, + {file = "ujson-5.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:924f7318c31874d6bb44d9ee1900167ca32aa9b69389b98ecbde34c1698a250f"}, + {file = "ujson-5.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00"}, + {file = "ujson-5.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126"}, + {file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8"}, + {file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b"}, + {file = "ujson-5.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9"}, + {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f"}, + {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4"}, + {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1"}, + {file = "ujson-5.10.0-cp311-cp311-win32.whl", hash = "sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f"}, + {file = "ujson-5.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720"}, + {file = "ujson-5.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5"}, + {file = "ujson-5.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e"}, + {file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043"}, + {file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1"}, + {file = "ujson-5.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3"}, + {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21"}, + {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2"}, + {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e"}, + {file = "ujson-5.10.0-cp312-cp312-win32.whl", hash = "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e"}, + {file = "ujson-5.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc"}, + {file = "ujson-5.10.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287"}, + {file = "ujson-5.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e"}, + {file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557"}, + {file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988"}, + {file = "ujson-5.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816"}, + {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20"}, + {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0"}, + {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f"}, + {file = "ujson-5.10.0-cp313-cp313-win32.whl", hash = "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165"}, + {file = "ujson-5.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539"}, + {file = "ujson-5.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a984a3131da7f07563057db1c3020b1350a3e27a8ec46ccbfbf21e5928a43050"}, + {file = "ujson-5.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73814cd1b9db6fc3270e9d8fe3b19f9f89e78ee9d71e8bd6c9a626aeaeaf16bd"}, + {file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61e1591ed9376e5eddda202ec229eddc56c612b61ac6ad07f96b91460bb6c2fb"}, + {file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2c75269f8205b2690db4572a4a36fe47cd1338e4368bc73a7a0e48789e2e35a"}, + {file = "ujson-5.10.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7223f41e5bf1f919cd8d073e35b229295aa8e0f7b5de07ed1c8fddac63a6bc5d"}, + {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d4dc2fd6b3067c0782e7002ac3b38cf48608ee6366ff176bbd02cf969c9c20fe"}, + {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:232cc85f8ee3c454c115455195a205074a56ff42608fd6b942aa4c378ac14dd7"}, + {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cc6139531f13148055d691e442e4bc6601f6dba1e6d521b1585d4788ab0bfad4"}, + {file = "ujson-5.10.0-cp38-cp38-win32.whl", hash = "sha256:e7ce306a42b6b93ca47ac4a3b96683ca554f6d35dd8adc5acfcd55096c8dfcb8"}, + {file = "ujson-5.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:e82d4bb2138ab05e18f089a83b6564fee28048771eb63cdecf4b9b549de8a2cc"}, + {file = "ujson-5.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dfef2814c6b3291c3c5f10065f745a1307d86019dbd7ea50e83504950136ed5b"}, + {file = "ujson-5.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4734ee0745d5928d0ba3a213647f1c4a74a2a28edc6d27b2d6d5bd9fa4319e27"}, + {file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d47ebb01bd865fdea43da56254a3930a413f0c5590372a1241514abae8aa7c76"}, + {file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dee5e97c2496874acbf1d3e37b521dd1f307349ed955e62d1d2f05382bc36dd5"}, + {file = "ujson-5.10.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7490655a2272a2d0b072ef16b0b58ee462f4973a8f6bbe64917ce5e0a256f9c0"}, + {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba17799fcddaddf5c1f75a4ba3fd6441f6a4f1e9173f8a786b42450851bd74f1"}, + {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2aff2985cef314f21d0fecc56027505804bc78802c0121343874741650a4d3d1"}, + {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ad88ac75c432674d05b61184178635d44901eb749786c8eb08c102330e6e8996"}, + {file = "ujson-5.10.0-cp39-cp39-win32.whl", hash = "sha256:2544912a71da4ff8c4f7ab5606f947d7299971bdd25a45e008e467ca638d13c9"}, + {file = "ujson-5.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:3ff201d62b1b177a46f113bb43ad300b424b7847f9c5d38b1b4ad8f75d4a282a"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5b6fee72fa77dc172a28f21693f64d93166534c263adb3f96c413ccc85ef6e64"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:61d0af13a9af01d9f26d2331ce49bb5ac1fb9c814964018ac8df605b5422dcb3"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecb24f0bdd899d368b715c9e6664166cf694d1e57be73f17759573a6986dd95a"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbd8fd427f57a03cff3ad6574b5e299131585d9727c8c366da4624a9069ed746"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beeaf1c48e32f07d8820c705ff8e645f8afa690cca1544adba4ebfa067efdc88"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:baed37ea46d756aca2955e99525cc02d9181de67f25515c468856c38d52b5f3b"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7663960f08cd5a2bb152f5ee3992e1af7690a64c0e26d31ba7b3ff5b2ee66337"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:d8640fb4072d36b08e95a3a380ba65779d356b2fee8696afeb7794cf0902d0a1"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78778a3aa7aafb11e7ddca4e29f46bc5139131037ad628cc10936764282d6753"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0111b27f2d5c820e7f2dbad7d48e3338c824e7ac4d2a12da3dc6061cc39c8e6"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:c66962ca7565605b355a9ed478292da628b8f18c0f2793021ca4425abf8b01e5"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ba43cc34cce49cf2d4bc76401a754a81202d8aa926d0e2b79f0ee258cb15d3a4"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ac56eb983edce27e7f51d05bc8dd820586c6e6be1c5216a6809b0c668bb312b8"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44bd4b23a0e723bf8b10628288c2c7c335161d6840013d4d5de20e48551773b"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c10f4654e5326ec14a46bcdeb2b685d4ada6911050aa8baaf3501e57024b804"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0de4971a89a762398006e844ae394bd46991f7c385d7a6a3b93ba229e6dac17e"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e1402f0564a97d2a52310ae10a64d25bcef94f8dd643fcf5d310219d915484f7"}, + {file = "ujson-5.10.0.tar.gz", hash = "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1"}, +] + [[package]] name = "urllib3" -version = "2.1.0" +version = "2.2.1" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"}, - {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"}, + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, ] [package.extras] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] [[package]] name = "uvicorn" -version = "0.21.1" +version = "0.30.0" description = "The lightning-fast ASGI server." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "uvicorn-0.21.1-py3-none-any.whl", hash = "sha256:e47cac98a6da10cd41e6fd036d472c6f58ede6c5dbee3dbee3ef7a100ed97742"}, - {file = "uvicorn-0.21.1.tar.gz", hash = "sha256:0fac9cb342ba099e0d582966005f3fdba5b0290579fed4a6266dc702ca7bb032"}, + {file = "uvicorn-0.30.0-py3-none-any.whl", hash = "sha256:78fa0b5f56abb8562024a59041caeb555c86e48d0efdd23c3fe7de7a4075bdab"}, + {file = "uvicorn-0.30.0.tar.gz", hash = "sha256:f678dec4fa3a39706bbf49b9ec5fc40049d42418716cea52b53f07828a60aa37"}, ] [package.dependencies] click = ">=7.0" +colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""} h11 = ">=0.8" +httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""} +python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} +pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} +uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\" and extra == \"standard\""} +watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} +websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""} [package.extras] standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] +[[package]] +name = "uvloop" +version = "0.19.0" +description = "Fast implementation of asyncio event loop on top of libuv" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e"}, + {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428"}, + {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8"}, + {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849"}, + {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957"}, + {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd"}, + {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef"}, + {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2"}, + {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1"}, + {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24"}, + {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533"}, + {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12"}, + {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650"}, + {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec"}, + {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc"}, + {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6"}, + {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593"}, + {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3"}, + {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:78ab247f0b5671cc887c31d33f9b3abfb88d2614b84e4303f1a63b46c046c8bd"}, + {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:472d61143059c84947aa8bb74eabbace30d577a03a1805b77933d6bd13ddebbd"}, + {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45bf4c24c19fb8a50902ae37c5de50da81de4922af65baf760f7c0c42e1088be"}, + {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271718e26b3e17906b28b67314c45d19106112067205119dddbd834c2b7ce797"}, + {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:34175c9fd2a4bc3adc1380e1261f60306344e3407c20a4d684fd5f3be010fa3d"}, + {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e27f100e1ff17f6feeb1f33968bc185bf8ce41ca557deee9d9bbbffeb72030b7"}, + {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13dfdf492af0aa0a0edf66807d2b465607d11c4fa48f4a1fd41cbea5b18e8e8b"}, + {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e3d4e85ac060e2342ff85e90d0c04157acb210b9ce508e784a944f852a40e67"}, + {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ca4956c9ab567d87d59d49fa3704cf29e37109ad348f2d5223c9bf761a332e7"}, + {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f467a5fd23b4fc43ed86342641f3936a68ded707f4627622fa3f82a120e18256"}, + {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:492e2c32c2af3f971473bc22f086513cedfc66a130756145a931a90c3958cb17"}, + {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2df95fca285a9f5bfe730e51945ffe2fa71ccbfdde3b0da5772b4ee4f2e770d5"}, + {file = "uvloop-0.19.0.tar.gz", hash = "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd"}, +] + +[package.extras] +docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] +test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"] + [[package]] name = "vocode" version = "0.1.111" description = "The all-in-one voice SDK" optional = false -python-versions = ">=3.8.1,<3.12" -files = [ - {file = "vocode-0.1.111-py3-none-any.whl", hash = "sha256:52b1c22188dbb1526eea490ad86fc11cc50df6442f4dd908939948b13fa66953"}, - {file = "vocode-0.1.111.tar.gz", hash = "sha256:9eb1e6d25c55f2fd7b0e1ee712de61a5f2c2cb8b70b058ce5d0eb7eb86bf8367"}, -] +python-versions = ">=3.9,<3.12" +files = [] +develop = true [package.dependencies] -aiohttp = ">=3.8.4,<4.0.0" -anthropic = ">=0.2.9,<0.3.0" -azure-cognitiveservices-speech = ">=1.27.0,<2.0.0" -fastapi = ">=0.100.1,<0.101.0" -janus = ">=1.0.0,<2.0.0" -jinja2 = ">=3.1.2,<4.0.0" -langchain = ">=0.0.198,<0.0.199" -miniaudio = ">=1.59,<2.0" -nltk = ">=3.8.1,<4.0.0" -openai = ">=0.27.8,<0.28.0" -opentelemetry-sdk = ">=1.17.0,<2.0.0" -pydub = ">=0.25.1,<0.26.0" -python-multipart = ">=0.0.6,<0.0.7" -requests = ">=2.28.2,<3.0.0" -scipy = ">=1.10.1,<2.0.0" -six = ">=1.16.0,<2.0.0" -sounddevice = ">=0.4.6,<0.5.0" -speechrecognition = ">=3.10.0,<4.0.0" -uvicorn = ">=0.21.1,<0.22.0" -websockets = ">=11.0.2,<12.0.0" +aiohttp = "^3.9.5" +anthropic = {version = "^0.28.0", optional = true} +azure-cognitiveservices-speech = {version = "^1.37.0", optional = true} +elevenlabs = {version = "^1.2.2", optional = true} +fastapi = "^0.111.0" +google-cloud-speech = {version = "^2.26.0", optional = true} +google-cloud-texttospeech = {version = "^2.16.3", optional = true} +janus = "^1.0.0" +jinja2 = "^3.1.4" +jsonschema = "^4.22.0" +langchain = {version = "^0.2.1", optional = true} +langchain-community = {version = "^0.2.1", optional = true} +loguru = "^0.7.2" +miniaudio = {version = "^1.59", optional = true} +nltk = {version = "^3.8.1", optional = true} +openai = {version = "^1.30.5", optional = true} +opentelemetry-sdk = "^1.24.0" +phonenumbers = "^8.13.37" +pvkoala = {version = "^2.0.1", optional = true} +pydantic = "^2.7.2" +pydub = {version = "^0.25.1", optional = true} +pyht = {version = "^0.0.28", optional = true} +redis = {version = "^5.0.4", optional = true} +requests = "^2.32.3" +sentry-sdk = {version = "^2.3.1", extras = ["fastapi"], optional = true} +sounddevice = "^0.4.7" +tiktoken = {version = "0.7.0", optional = true} +twilio = {version = "^9.1.0", optional = true} +uvicorn = "^0.30.0" +vonage = {version = "^3.14.0", optional = true} +websockets = "^12.0" [package.extras] -actions = ["nylas (>=5.14.0,<6.0.0)"] -agents = ["google-cloud-aiplatform (>=1.26.0,<2.0.0)"] -all = ["elevenlabs (>=0.2.6,<0.3.0)", "google-cloud-aiplatform (>=1.26.0,<2.0.0)", "google-cloud-speech (>=2.19.0,<3.0.0)", "google-cloud-texttospeech (>=2.14.1,<3.0.0)", "gtts (>=2.3.1,<3.0.0)", "nylas (>=5.14.0,<6.0.0)", "redis (>=4.5.4,<5.0.0)", "twilio (>=8.1.0,<9.0.0)", "vonage (>=3.5.1,<4.0.0)"] -synthesizers = ["elevenlabs (>=0.2.6,<0.3.0)", "google-cloud-texttospeech (>=2.14.1,<3.0.0)", "gtts (>=2.3.1,<3.0.0)"] -telephony = ["redis (>=4.5.4,<5.0.0)", "twilio (>=8.1.0,<9.0.0)", "vonage (>=3.5.1,<4.0.0)"] -transcribers = ["google-cloud-speech (>=2.19.0,<3.0.0)"] +agents = ["anthropic (>=0.28.0,<0.29.0)", "openai (>=1.30.5,<2.0.0)", "tiktoken (==0.7.0)"] +all = ["anthropic (>=0.28.0,<0.29.0)", "azure-cognitiveservices-speech (>=1.37.0,<2.0.0)", "elevenlabs (>=1.2.2,<2.0.0)", "google-cloud-speech (>=2.26.0,<3.0.0)", "google-cloud-texttospeech (>=2.16.3,<3.0.0)", "langchain (>=0.2.1,<0.3.0)", "langchain-community (>=0.2.1,<0.3.0)", "miniaudio (>=1.59,<2.0)", "nltk (>=3.8.1,<4.0.0)", "openai (>=1.30.5,<2.0.0)", "pvkoala (>=2.0.1,<3.0.0)", "pydub (>=0.25.1,<0.26.0)", "pyht (>=0.0.28,<0.0.29)", "redis (>=5.0.4,<6.0.0)", "sentry-sdk[fastapi] (>=2.3.1,<3.0.0)", "tiktoken (==0.7.0)", "twilio (>=9.1.0,<10.0.0)", "vonage (>=3.14.0,<4.0.0)"] +misc = ["langchain (>=0.2.1,<0.3.0)", "langchain-community (>=0.2.1,<0.3.0)", "sentry-sdk[fastapi] (>=2.3.1,<3.0.0)"] +synthesizers = ["azure-cognitiveservices-speech (>=1.37.0,<2.0.0)", "elevenlabs (>=1.2.2,<2.0.0)", "google-cloud-texttospeech (>=2.16.3,<3.0.0)", "miniaudio (>=1.59,<2.0)", "nltk (>=3.8.1,<4.0.0)", "pvkoala (>=2.0.1,<3.0.0)", "pydub (>=0.25.1,<0.26.0)", "pyht (>=0.0.28,<0.0.29)"] +telephony = ["redis (>=5.0.4,<6.0.0)", "twilio (>=9.1.0,<10.0.0)", "vonage (>=3.14.0,<4.0.0)"] +transcribers = ["google-cloud-speech (>=2.26.0,<3.0.0)"] + +[package.source] +type = "directory" +url = "../.." [[package]] name = "vonage" -version = "3.12.0" +version = "3.14.0" description = "Vonage Server SDK for Python" optional = false python-versions = ">=3.8" files = [ - {file = "vonage-3.12.0-py2.py3-none-any.whl", hash = "sha256:5816909ae6ad76b18e4b33addcff6e8156bab0b8c6a6caf4803c60e7585cadf6"}, - {file = "vonage-3.12.0.tar.gz", hash = "sha256:3034df64e482927be4c9c289dee890b4e578b0057a0055af05a8ca471d143e9c"}, + {file = "vonage-3.14.0-py2.py3-none-any.whl", hash = "sha256:f8d28b8fcd157c0610d84b880779aadd3ab3768abfb18ef863e08669de163ccf"}, + {file = "vonage-3.14.0.tar.gz", hash = "sha256:ea001e9616abb19670c4250a1ac46288207030ebc9d9ecbcf5fcffef61fa5850"}, ] [package.dependencies] Deprecated = "*" -pydantic = ">=1.10,<2.dev0" +pydantic = ">=2.5.2" pytz = ">=2018.5" requests = ">=2.4.2" vonage-jwt = ">=1.1.0" [[package]] name = "vonage-jwt" -version = "1.1.0" -description = "A JWT Generator for Python. Creates JWTs for use with Vonage APIs." +version = "1.1.1" +description = "Tooling for working with JWTs for Vonage APIs in Python." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "vonage_jwt-1.1.0-py3-none-any.whl", hash = "sha256:f41d2fc51f80cebddff1d65ec2146527ee83ca95f3e8a8fe9cda2263a435e2ed"}, - {file = "vonage_jwt-1.1.0.tar.gz", hash = "sha256:ed6af2bf82dc7cffe42ad453295472b86e02852baaaa3f2b97cd49fcb4e9019d"}, + {file = "vonage_jwt-1.1.1-py3-none-any.whl", hash = "sha256:4b751571e013deeab9f13b68f9e1478d8aa7f0a91f0cb7f6d793fa7b859859df"}, + {file = "vonage_jwt-1.1.1.tar.gz", hash = "sha256:15f4b1cd8fa5909390a4074a909053ae823df0557b1edb9b675d0a013295dc10"}, ] [package.dependencies] pyjwt = {version = ">=1.6.4", extras = ["crypto"]} +vonage-utils = ">=1.1.2" + +[[package]] +name = "vonage-utils" +version = "1.1.2" +description = "Utils package containing objects for use with Vonage APIs" +optional = false +python-versions = ">=3.8" +files = [ + {file = "vonage_utils-1.1.2-py3-none-any.whl", hash = "sha256:a815a8be8f5fdba558d090d0f81b469a2eb0ded4cccbfe4e27dc9276e84c4b7e"}, + {file = "vonage_utils-1.1.2.tar.gz", hash = "sha256:a86c1eafe62e6f82d18dda6fd4dc78c898dea81888b83f18ea75105365307daf"}, +] + +[package.dependencies] +pydantic = ">=2.7.1" +typing-extensions = ">=4.9.0" + +[[package]] +name = "watchfiles" +version = "0.22.0" +description = "Simple, modern and high performance file watching and code reload in python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "watchfiles-0.22.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:da1e0a8caebf17976e2ffd00fa15f258e14749db5e014660f53114b676e68538"}, + {file = "watchfiles-0.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61af9efa0733dc4ca462347becb82e8ef4945aba5135b1638bfc20fad64d4f0e"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d9188979a58a096b6f8090e816ccc3f255f137a009dd4bbec628e27696d67c1"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2bdadf6b90c099ca079d468f976fd50062905d61fae183f769637cb0f68ba59a"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:067dea90c43bf837d41e72e546196e674f68c23702d3ef80e4e816937b0a3ffd"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbf8a20266136507abf88b0df2328e6a9a7c7309e8daff124dda3803306a9fdb"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1235c11510ea557fe21be5d0e354bae2c655a8ee6519c94617fe63e05bca4171"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2444dc7cb9d8cc5ab88ebe792a8d75709d96eeef47f4c8fccb6df7c7bc5be71"}, + {file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c5af2347d17ab0bd59366db8752d9e037982e259cacb2ba06f2c41c08af02c39"}, + {file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9624a68b96c878c10437199d9a8b7d7e542feddda8d5ecff58fdc8e67b460848"}, + {file = "watchfiles-0.22.0-cp310-none-win32.whl", hash = "sha256:4b9f2a128a32a2c273d63eb1fdbf49ad64852fc38d15b34eaa3f7ca2f0d2b797"}, + {file = "watchfiles-0.22.0-cp310-none-win_amd64.whl", hash = "sha256:2627a91e8110b8de2406d8b2474427c86f5a62bf7d9ab3654f541f319ef22bcb"}, + {file = "watchfiles-0.22.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8c39987a1397a877217be1ac0fb1d8b9f662c6077b90ff3de2c05f235e6a8f96"}, + {file = "watchfiles-0.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a927b3034d0672f62fb2ef7ea3c9fc76d063c4b15ea852d1db2dc75fe2c09696"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052d668a167e9fc345c24203b104c313c86654dd6c0feb4b8a6dfc2462239249"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e45fb0d70dda1623a7045bd00c9e036e6f1f6a85e4ef2c8ae602b1dfadf7550"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c49b76a78c156979759d759339fb62eb0549515acfe4fd18bb151cc07366629c"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4a65474fd2b4c63e2c18ac67a0c6c66b82f4e73e2e4d940f837ed3d2fd9d4da"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc0cba54f47c660d9fa3218158b8963c517ed23bd9f45fe463f08262a4adae1"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ebe84a035993bb7668f58a0ebf998174fb723a39e4ef9fce95baabb42b787f"}, + {file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e0f0a874231e2839abbf473256efffe577d6ee2e3bfa5b540479e892e47c172d"}, + {file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:213792c2cd3150b903e6e7884d40660e0bcec4465e00563a5fc03f30ea9c166c"}, + {file = "watchfiles-0.22.0-cp311-none-win32.whl", hash = "sha256:b44b70850f0073b5fcc0b31ede8b4e736860d70e2dbf55701e05d3227a154a67"}, + {file = "watchfiles-0.22.0-cp311-none-win_amd64.whl", hash = "sha256:00f39592cdd124b4ec5ed0b1edfae091567c72c7da1487ae645426d1b0ffcad1"}, + {file = "watchfiles-0.22.0-cp311-none-win_arm64.whl", hash = "sha256:3218a6f908f6a276941422b035b511b6d0d8328edd89a53ae8c65be139073f84"}, + {file = "watchfiles-0.22.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:c7b978c384e29d6c7372209cbf421d82286a807bbcdeb315427687f8371c340a"}, + {file = "watchfiles-0.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd4c06100bce70a20c4b81e599e5886cf504c9532951df65ad1133e508bf20be"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:425440e55cd735386ec7925f64d5dde392e69979d4c8459f6bb4e920210407f2"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68fe0c4d22332d7ce53ad094622b27e67440dacefbaedd29e0794d26e247280c"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a8a31bfd98f846c3c284ba694c6365620b637debdd36e46e1859c897123aa232"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc2e8fe41f3cac0660197d95216c42910c2b7e9c70d48e6d84e22f577d106fc1"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b7cc10261c2786c41d9207193a85c1db1b725cf87936df40972aab466179b6"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28585744c931576e535860eaf3f2c0ec7deb68e3b9c5a85ca566d69d36d8dd27"}, + {file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:00095dd368f73f8f1c3a7982a9801190cc88a2f3582dd395b289294f8975172b"}, + {file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:52fc9b0dbf54d43301a19b236b4a4614e610605f95e8c3f0f65c3a456ffd7d35"}, + {file = "watchfiles-0.22.0-cp312-none-win32.whl", hash = "sha256:581f0a051ba7bafd03e17127735d92f4d286af941dacf94bcf823b101366249e"}, + {file = "watchfiles-0.22.0-cp312-none-win_amd64.whl", hash = "sha256:aec83c3ba24c723eac14225194b862af176d52292d271c98820199110e31141e"}, + {file = "watchfiles-0.22.0-cp312-none-win_arm64.whl", hash = "sha256:c668228833c5619f6618699a2c12be057711b0ea6396aeaece4ded94184304ea"}, + {file = "watchfiles-0.22.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d47e9ef1a94cc7a536039e46738e17cce058ac1593b2eccdede8bf72e45f372a"}, + {file = "watchfiles-0.22.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28f393c1194b6eaadcdd8f941307fc9bbd7eb567995232c830f6aef38e8a6e88"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd64f3a4db121bc161644c9e10a9acdb836853155a108c2446db2f5ae1778c3d"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2abeb79209630da981f8ebca30a2c84b4c3516a214451bfc5f106723c5f45843"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cc382083afba7918e32d5ef12321421ef43d685b9a67cc452a6e6e18920890e"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d048ad5d25b363ba1d19f92dcf29023988524bee6f9d952130b316c5802069cb"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:103622865599f8082f03af4214eaff90e2426edff5e8522c8f9e93dc17caee13"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3e1f3cf81f1f823e7874ae563457828e940d75573c8fbf0ee66818c8b6a9099"}, + {file = "watchfiles-0.22.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8597b6f9dc410bdafc8bb362dac1cbc9b4684a8310e16b1ff5eee8725d13dcd6"}, + {file = "watchfiles-0.22.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0b04a2cbc30e110303baa6d3ddce8ca3664bc3403be0f0ad513d1843a41c97d1"}, + {file = "watchfiles-0.22.0-cp38-none-win32.whl", hash = "sha256:b610fb5e27825b570554d01cec427b6620ce9bd21ff8ab775fc3a32f28bba63e"}, + {file = "watchfiles-0.22.0-cp38-none-win_amd64.whl", hash = "sha256:fe82d13461418ca5e5a808a9e40f79c1879351fcaeddbede094028e74d836e86"}, + {file = "watchfiles-0.22.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3973145235a38f73c61474d56ad6199124e7488822f3a4fc97c72009751ae3b0"}, + {file = "watchfiles-0.22.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:280a4afbc607cdfc9571b9904b03a478fc9f08bbeec382d648181c695648202f"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a0d883351a34c01bd53cfa75cd0292e3f7e268bacf2f9e33af4ecede7e21d1d"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9165bcab15f2b6d90eedc5c20a7f8a03156b3773e5fb06a790b54ccecdb73385"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc1b9b56f051209be458b87edb6856a449ad3f803315d87b2da4c93b43a6fe72"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dc1fc25a1dedf2dd952909c8e5cb210791e5f2d9bc5e0e8ebc28dd42fed7562"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc92d2d2706d2b862ce0568b24987eba51e17e14b79a1abcd2edc39e48e743c8"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97b94e14b88409c58cdf4a8eaf0e67dfd3ece7e9ce7140ea6ff48b0407a593ec"}, + {file = "watchfiles-0.22.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96eec15e5ea7c0b6eb5bfffe990fc7c6bd833acf7e26704eb18387fb2f5fd087"}, + {file = "watchfiles-0.22.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:28324d6b28bcb8d7c1041648d7b63be07a16db5510bea923fc80b91a2a6cbed6"}, + {file = "watchfiles-0.22.0-cp39-none-win32.whl", hash = "sha256:8c3e3675e6e39dc59b8fe5c914a19d30029e36e9f99468dddffd432d8a7b1c93"}, + {file = "watchfiles-0.22.0-cp39-none-win_amd64.whl", hash = "sha256:25c817ff2a86bc3de3ed2df1703e3d24ce03479b27bb4527c57e722f8554d971"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b810a2c7878cbdecca12feae2c2ae8af59bea016a78bc353c184fa1e09f76b68"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7e1f9c5d1160d03b93fc4b68a0aeb82fe25563e12fbcdc8507f8434ab6f823c"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:030bc4e68d14bcad2294ff68c1ed87215fbd9a10d9dea74e7cfe8a17869785ab"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ace7d060432acde5532e26863e897ee684780337afb775107c0a90ae8dbccfd2"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5834e1f8b71476a26df97d121c0c0ed3549d869124ed2433e02491553cb468c2"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:0bc3b2f93a140df6806c8467c7f51ed5e55a931b031b5c2d7ff6132292e803d6"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fdebb655bb1ba0122402352b0a4254812717a017d2dc49372a1d47e24073795"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c8e0aa0e8cc2a43561e0184c0513e291ca891db13a269d8d47cb9841ced7c71"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2f350cbaa4bb812314af5dab0eb8d538481e2e2279472890864547f3fe2281ed"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7a74436c415843af2a769b36bf043b6ccbc0f8d784814ba3d42fc961cdb0a9dc"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00ad0bcd399503a84cc688590cdffbe7a991691314dde5b57b3ed50a41319a31"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72a44e9481afc7a5ee3291b09c419abab93b7e9c306c9ef9108cb76728ca58d2"}, + {file = "watchfiles-0.22.0.tar.gz", hash = "sha256:988e981aaab4f3955209e7e28c7794acdb690be1efa7f16f8ea5aba7ffdadacb"}, +] + +[package.dependencies] +anyio = ">=3.0.0" + +[[package]] +name = "wcwidth" +version = "0.2.13" +description = "Measures the displayed width of unicode strings in a terminal" +optional = false +python-versions = "*" +files = [ + {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, + {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, +] [[package]] name = "websockets" -version = "11.0.3" +version = "12.0" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"}, + {file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"}, + {file = "websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603"}, + {file = "websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f"}, + {file = "websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf"}, + {file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"}, + {file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"}, + {file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"}, + {file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"}, + {file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"}, + {file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"}, + {file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"}, + {file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113"}, + {file = "websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d"}, + {file = "websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f"}, + {file = "websockets-12.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438"}, + {file = "websockets-12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2"}, + {file = "websockets-12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7"}, + {file = "websockets-12.0-cp38-cp38-win32.whl", hash = "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62"}, + {file = "websockets-12.0-cp38-cp38-win_amd64.whl", hash = "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892"}, + {file = "websockets-12.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d"}, + {file = "websockets-12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28"}, + {file = "websockets-12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9"}, + {file = "websockets-12.0-cp39-cp39-win32.whl", hash = "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6"}, + {file = "websockets-12.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8"}, + {file = "websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b"}, + {file = "websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30"}, + {file = "websockets-12.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2"}, + {file = "websockets-12.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468"}, + {file = "websockets-12.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611"}, + {file = "websockets-12.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370"}, + {file = "websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e"}, + {file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"}, +] + +[[package]] +name = "win32-setctime" +version = "1.1.0" +description = "A small Python utility to set file creation time on Windows" +optional = false +python-versions = ">=3.5" files = [ - {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3ccc8a0c387629aec40f2fc9fdcb4b9d5431954f934da3eaf16cdc94f67dbfac"}, - {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d67ac60a307f760c6e65dad586f556dde58e683fab03323221a4e530ead6f74d"}, - {file = "websockets-11.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84d27a4832cc1a0ee07cdcf2b0629a8a72db73f4cf6de6f0904f6661227f256f"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffd7dcaf744f25f82190856bc26ed81721508fc5cbf2a330751e135ff1283564"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7622a89d696fc87af8e8d280d9b421db5133ef5b29d3f7a1ce9f1a7bf7fcfa11"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bceab846bac555aff6427d060f2fcfff71042dba6f5fca7dc4f75cac815e57ca"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:54c6e5b3d3a8936a4ab6870d46bdd6ec500ad62bde9e44462c32d18f1e9a8e54"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:41f696ba95cd92dc047e46b41b26dd24518384749ed0d99bea0a941ca87404c4"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:86d2a77fd490ae3ff6fae1c6ceaecad063d3cc2320b44377efdde79880e11526"}, - {file = "websockets-11.0.3-cp310-cp310-win32.whl", hash = "sha256:2d903ad4419f5b472de90cd2d40384573b25da71e33519a67797de17ef849b69"}, - {file = "websockets-11.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:1d2256283fa4b7f4c7d7d3e84dc2ece74d341bce57d5b9bf385df109c2a1a82f"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e848f46a58b9fcf3d06061d17be388caf70ea5b8cc3466251963c8345e13f7eb"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa5003845cdd21ac0dc6c9bf661c5beddd01116f6eb9eb3c8e272353d45b3288"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b58cbf0697721120866820b89f93659abc31c1e876bf20d0b3d03cef14faf84d"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:660e2d9068d2bedc0912af508f30bbeb505bbbf9774d98def45f68278cea20d3"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1f0524f203e3bd35149f12157438f406eff2e4fb30f71221c8a5eceb3617b6b"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:def07915168ac8f7853812cc593c71185a16216e9e4fa886358a17ed0fd9fcf6"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b30c6590146e53149f04e85a6e4fcae068df4289e31e4aee1fdf56a0dead8f97"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:619d9f06372b3a42bc29d0cd0354c9bb9fb39c2cbc1a9c5025b4538738dbffaf"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:01f5567d9cf6f502d655151645d4e8b72b453413d3819d2b6f1185abc23e82dd"}, - {file = "websockets-11.0.3-cp311-cp311-win32.whl", hash = "sha256:e1459677e5d12be8bbc7584c35b992eea142911a6236a3278b9b5ce3326f282c"}, - {file = "websockets-11.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:e7837cb169eca3b3ae94cc5787c4fed99eef74c0ab9506756eea335e0d6f3ed8"}, - {file = "websockets-11.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9f59a3c656fef341a99e3d63189852be7084c0e54b75734cde571182c087b152"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2529338a6ff0eb0b50c7be33dc3d0e456381157a31eefc561771ee431134a97f"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34fd59a4ac42dff6d4681d8843217137f6bc85ed29722f2f7222bd619d15e95b"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:332d126167ddddec94597c2365537baf9ff62dfcc9db4266f263d455f2f031cb"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6505c1b31274723ccaf5f515c1824a4ad2f0d191cec942666b3d0f3aa4cb4007"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f467ba0050b7de85016b43f5a22b46383ef004c4f672148a8abf32bc999a87f0"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9d9acd80072abcc98bd2c86c3c9cd4ac2347b5a5a0cae7ed5c0ee5675f86d9af"}, - {file = "websockets-11.0.3-cp37-cp37m-win32.whl", hash = "sha256:e590228200fcfc7e9109509e4d9125eace2042fd52b595dd22bbc34bb282307f"}, - {file = "websockets-11.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:b16fff62b45eccb9c7abb18e60e7e446998093cdcb50fed33134b9b6878836de"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fb06eea71a00a7af0ae6aefbb932fb8a7df3cb390cc217d51a9ad7343de1b8d0"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8a34e13a62a59c871064dfd8ffb150867e54291e46d4a7cf11d02c94a5275bae"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4841ed00f1026dfbced6fca7d963c4e7043aa832648671b5138008dc5a8f6d99"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a073fc9ab1c8aff37c99f11f1641e16da517770e31a37265d2755282a5d28aa"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68b977f21ce443d6d378dbd5ca38621755f2063d6fdb3335bda981d552cfff86"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a99a7a71631f0efe727c10edfba09ea6bee4166a6f9c19aafb6c0b5917d09c"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bee9fcb41db2a23bed96c6b6ead6489702c12334ea20a297aa095ce6d31370d0"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4b253869ea05a5a073ebfdcb5cb3b0266a57c3764cf6fe114e4cd90f4bfa5f5e"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1553cb82942b2a74dd9b15a018dce645d4e68674de2ca31ff13ebc2d9f283788"}, - {file = "websockets-11.0.3-cp38-cp38-win32.whl", hash = "sha256:f61bdb1df43dc9c131791fbc2355535f9024b9a04398d3bd0684fc16ab07df74"}, - {file = "websockets-11.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:03aae4edc0b1c68498f41a6772d80ac7c1e33c06c6ffa2ac1c27a07653e79d6f"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:777354ee16f02f643a4c7f2b3eff8027a33c9861edc691a2003531f5da4f6bc8"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8c82f11964f010053e13daafdc7154ce7385ecc538989a354ccc7067fd7028fd"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3580dd9c1ad0701169e4d6fc41e878ffe05e6bdcaf3c412f9d559389d0c9e016"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f1a3f10f836fab6ca6efa97bb952300b20ae56b409414ca85bff2ad241d2a61"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df41b9bc27c2c25b486bae7cf42fccdc52ff181c8c387bfd026624a491c2671b"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279e5de4671e79a9ac877427f4ac4ce93751b8823f276b681d04b2156713b9dd"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1fdf26fa8a6a592f8f9235285b8affa72748dc12e964a5518c6c5e8f916716f7"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:69269f3a0b472e91125b503d3c0b3566bda26da0a3261c49f0027eb6075086d1"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:97b52894d948d2f6ea480171a27122d77af14ced35f62e5c892ca2fae9344311"}, - {file = "websockets-11.0.3-cp39-cp39-win32.whl", hash = "sha256:c7f3cb904cce8e1be667c7e6fef4516b98d1a6a0635a58a57528d577ac18a128"}, - {file = "websockets-11.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c792ea4eabc0159535608fc5658a74d1a81020eb35195dd63214dcf07556f67e"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f2e58f2c36cc52d41f2659e4c0cbf7353e28c8c9e63e30d8c6d3494dc9fdedcf"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de36fe9c02995c7e6ae6efe2e205816f5f00c22fd1fbf343d4d18c3d5ceac2f5"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ac56b661e60edd453585f4bd68eb6a29ae25b5184fd5ba51e97652580458998"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e052b8467dd07d4943936009f46ae5ce7b908ddcac3fda581656b1b19c083d9b"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:42cc5452a54a8e46a032521d7365da775823e21bfba2895fb7b77633cce031bb"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e6316827e3e79b7b8e7d8e3b08f4e331af91a48e794d5d8b099928b6f0b85f20"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8531fdcad636d82c517b26a448dcfe62f720e1922b33c81ce695d0edb91eb931"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c114e8da9b475739dde229fd3bc6b05a6537a88a578358bc8eb29b4030fac9c9"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e063b1865974611313a3849d43f2c3f5368093691349cf3c7c8f8f75ad7cb280"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:92b2065d642bf8c0a82d59e59053dd2fdde64d4ed44efe4870fa816c1232647b"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0ee68fe502f9031f19d495dae2c268830df2760c0524cbac5d759921ba8c8e82"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcacf2c7a6c3a84e720d1bb2b543c675bf6c40e460300b628bab1b1efc7c034c"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b67c6f5e5a401fc56394f191f00f9b3811fe843ee93f4a70df3c389d1adf857d"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d5023a4b6a5b183dc838808087033ec5df77580485fc533e7dab2567851b0a4"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ed058398f55163a79bb9f06a90ef9ccc063b204bb346c4de78efc5d15abfe602"}, - {file = "websockets-11.0.3-py3-none-any.whl", hash = "sha256:6681ba9e7f8f3b19440921e99efbb40fc89f26cd71bf539e45d8c8a25c976dc6"}, - {file = "websockets-11.0.3.tar.gz", hash = "sha256:88fc51d9a26b10fc331be344f1781224a375b78488fc343620184e95a4b27016"}, + {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"}, + {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"}, ] +[package.extras] +dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] + [[package]] name = "wrapt" version = "1.16.0" @@ -2514,20 +3992,20 @@ multidict = ">=4.0" [[package]] name = "zipp" -version = "3.17.0" +version = "3.19.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, - {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, + {file = "zipp-3.19.0-py3-none-any.whl", hash = "sha256:96dc6ad62f1441bcaccef23b274ec471518daf4fbbc580341204936a5a3dddec"}, + {file = "zipp-3.19.0.tar.gz", hash = "sha256:952df858fb3164426c976d9338d3961e8e8b3758e2e059e0f754b8c4262625ee"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.12" -content-hash = "1bed2edebca6168ceb42e5c8bdcb8196d30e29498ca7ea4515f7bcf53ceb926a" +content-hash = "34b3cef8d3c84f54cf50b30e588a545a89fffe91d46a33cb269f48c222176f4e" diff --git a/apps/telephony_app/pyproject.toml b/apps/telephony_app/pyproject.toml index df7b2c7ab..01f6fc1b6 100644 --- a/apps/telephony_app/pyproject.toml +++ b/apps/telephony_app/pyproject.toml @@ -7,12 +7,11 @@ readme = "README.md" [tool.poetry.dependencies] python = ">=3.9,<3.12" -redis = "^4.5.4" -twilio = "^8.1.0" -vonage = "^3.5.1" -pyngrok = "^6.0.0" -python-dotenv = "^1.0.0" -vocode = "0.1.111" +pyngrok = "^7.1.6" +python-dotenv = "^1.0.1" +vocode = { path = "../..", extras = [ + "all", +], develop = true, python = ">=3.11,<3.12" } [build-system] diff --git a/apps/telephony_app/speller_agent.py b/apps/telephony_app/speller_agent.py index 19f755a94..43ed0ce73 100644 --- a/apps/telephony_app/speller_agent.py +++ b/apps/telephony_app/speller_agent.py @@ -1,16 +1,18 @@ -import logging -from typing import Optional, Tuple import typing +from typing import Optional, Tuple + +from vocode.streaming.agent.abstract_factory import AbstractAgentFactory +from vocode.streaming.agent.base_agent import BaseAgent, RespondAgent from vocode.streaming.agent.chat_gpt_agent import ChatGPTAgent from vocode.streaming.models.agent import AgentConfig, AgentType, ChatGPTAgentConfig -from vocode.streaming.agent.base_agent import BaseAgent, RespondAgent -from vocode.streaming.agent.factory import AgentFactory class SpellerAgentConfig(AgentConfig, type="agent_speller"): """Configuration for SpellerAgent. Inherits from AgentConfig.""" + pass + class SpellerAgent(RespondAgent[SpellerAgentConfig]): """SpellerAgent class. Inherits from RespondAgent. @@ -47,18 +49,14 @@ async def respond( return "".join(c + " " for c in human_input), False - -class SpellerAgentFactory(AgentFactory): +class SpellerAgentFactory(AbstractAgentFactory): """Factory class for creating agents based on the provided agent configuration.""" - def create_agent( - self, agent_config: AgentConfig, logger: Optional[logging.Logger] = None - ) -> BaseAgent: + def create_agent(self, agent_config: AgentConfig) -> BaseAgent: """Creates an agent based on the provided agent configuration. Args: agent_config (AgentConfig): The configuration for the agent to be created. - logger (Optional[logging.Logger]): The logger to be used by the agent. Returns: BaseAgent: The created agent. diff --git a/playground/streaming/agent/chat.py b/playground/streaming/agent/chat.py index bba34122f..659443c9a 100644 --- a/playground/streaming/agent/chat.py +++ b/playground/streaming/agent/chat.py @@ -1,85 +1,109 @@ import asyncio +import random import typing + from dotenv import load_dotenv -from playground.streaming.tracing_utils import make_parser_and_maybe_trace from pydantic.v1 import BaseModel + +from vocode.streaming.action.abstract_factory import AbstractActionFactory from vocode.streaming.action.base_action import BaseAction -from vocode.streaming.action.factory import ActionFactory from vocode.streaming.action.worker import ActionsWorker from vocode.streaming.models.actions import ( ActionConfig, ActionInput, ActionOutput, - ActionType, + EndOfTurn, + PhraseBasedActionTrigger, + PhraseBasedActionTriggerConfig, + PhraseTrigger, ) from vocode.streaming.models.agent import ChatGPTAgentConfig +from vocode.streaming.models.message import BaseMessage from vocode.streaming.models.transcript import Transcript -from vocode.streaming.utils.state_manager import ConversationStateManager +from vocode.streaming.utils.state_manager import AbstractConversationStateManager from vocode.streaming.utils.worker import InterruptibleAgentResponseEvent load_dotenv() from vocode.streaming.agent import ChatGPTAgent from vocode.streaming.agent.base_agent import ( - BaseAgent, AgentResponseMessage, AgentResponseType, + BaseAgent, TranscriptionAgentInput, ) - -from vocode.streaming.transcriber.base_transcriber import Transcription +from vocode.streaming.models.transcriber import Transcription from vocode.streaming.utils import create_conversation_id +BACKCHANNELS = ["Got it", "Sure", "Okay", "I understand"] + class ShoutActionConfig(ActionConfig, type="shout"): # type: ignore num_exclamation_marks: int class ShoutActionParameters(BaseModel): - name: str + pass class ShoutActionResponse(BaseModel): success: bool -class ShoutAction( - BaseAction[ShoutActionConfig, ShoutActionParameters, ShoutActionResponse] -): +class ShoutAction(BaseAction[ShoutActionConfig, ShoutActionParameters, ShoutActionResponse]): description: str = "Shouts someone's name" parameters_type: typing.Type[ShoutActionParameters] = ShoutActionParameters response_type: typing.Type[ShoutActionResponse] = ShoutActionResponse async def run( - self, action_input: ActionInput[ShoutActionParameters] + self, + action_input: ActionInput[ShoutActionParameters], ) -> ActionOutput[ShoutActionResponse]: - print( - f"HI THERE {action_input.params.name}{self.action_config.num_exclamation_marks * '!'}" - ) + print(f"HI THERE {self.action_config.num_exclamation_marks * '!'}") return ActionOutput( action_type=self.action_config.type, response=ShoutActionResponse(success=True), ) -class ShoutActionFactory(ActionFactory): +class ShoutActionFactory(AbstractActionFactory): def create_action(self, action_config: ActionConfig) -> BaseAction: if isinstance(action_config, ShoutActionConfig): - return ShoutAction(action_config, should_respond=True) + return ShoutAction(action_config, should_respond="always") else: raise Exception("Invalid action type") -class DummyConversationManager(ConversationStateManager): - pass +class DummyConversationManager(AbstractConversationStateManager): + """For use with Agents operating in a non-call context.""" + + def __init__( + self, + using_input_streaming_synthesizer: bool = False, + ): + self._using_input_streaming_synthesizer = using_input_streaming_synthesizer + self._conversation_id = create_conversation_id() + + def using_input_streaming_synthesizer(self): + return self._using_input_streaming_synthesizer + def get_conversation_id(self): + return self._conversation_id -async def run_agent(agent: BaseAgent): + +async def run_agent( + agent: BaseAgent, interruption_probability: float, backchannel_probability: float +): ended = False conversation_id = create_conversation_id() async def receiver(): nonlocal ended + + assert agent.transcript is not None + + ignore_until_end_of_turn = False + while not ended: try: event = await agent.get_output_queue().get() @@ -93,13 +117,37 @@ async def receiver(): elif response.type == AgentResponseType.MESSAGE: agent_response = typing.cast(AgentResponseMessage, response) - agent.transcript.add_bot_message( - agent_response.message.text, conversation_id - ) - print( - "AI: " - + typing.cast(AgentResponseMessage, response).message.text - ) + if isinstance(agent_response.message, EndOfTurn): + ignore_until_end_of_turn = False + if random.random() < backchannel_probability: + backchannel = random.choice(BACKCHANNELS) + print("Human: " + f"[{backchannel}]") + agent.transcript.add_human_message( + backchannel, + conversation_id, + is_backchannel=True, + ) + elif isinstance(agent_response.message, BaseMessage): + if ignore_until_end_of_turn: + continue + + message_sent: str + is_final: bool + # TODO: consider allowing the user to interrupt the agent manually by responding fast + if random.random() < interruption_probability: + stop_idx = random.randint(0, len(agent_response.message.text)) + message_sent = agent_response.message.text[:stop_idx] + ignore_until_end_of_turn = True + is_final = False + else: + message_sent = agent_response.message.text + is_final = True + + agent.transcript.add_bot_message( + message_sent, conversation_id, is_final=is_final + ) + + print("AI: " + message_sent + ("-" if not is_final else "")) except asyncio.CancelledError: break @@ -116,6 +164,8 @@ async def sender(): message=message, confidence=1.0, is_final=True ), conversation_id=conversation_id, + twilio_sid="0", + vonage_uuid=None, ) ) ) @@ -129,9 +179,7 @@ async def sender(): output_queue=agent.get_input_queue(), action_factory=agent.action_factory, ) - actions_worker.attach_conversation_state_manager( - agent.conversation_state_manager - ) + actions_worker.attach_conversation_state_manager(agent.conversation_state_manager) actions_worker.start() await asyncio.gather(receiver(), sender()) @@ -144,32 +192,43 @@ async def agent_main(): # Replace with your agent! agent = ChatGPTAgent( ChatGPTAgentConfig( - prompt_preamble="have a conversation", + prompt_preamble="Have a conversation", + initial_message=BaseMessage(text="Is this Ajay?"), actions=[ - ShoutActionConfig(num_exclamation_marks=3), + ShoutActionConfig( + num_exclamation_marks=3, + action_trigger=PhraseBasedActionTrigger( + type="action_trigger_phrase_based", + config=PhraseBasedActionTriggerConfig( + phrase_triggers=[ + PhraseTrigger( + phrase="shout", + conditions=["phrase_condition_type_contains"], + ), + ], + ), + ), + ), ], ), action_factory=ShoutActionFactory(), ) - agent.attach_conversation_state_manager(DummyConversationManager(conversation=None)) + agent.attach_conversation_state_manager(DummyConversationManager()) agent.attach_transcript(transcript) if agent.agent_config.initial_message is not None: agent.output_queue.put_nowait( InterruptibleAgentResponseEvent( - payload=AgentResponseMessage( - message=agent.agent_config.initial_message - ), + payload=AgentResponseMessage(message=agent.agent_config.initial_message), agent_response_tracker=asyncio.Event(), ) ) agent.start() try: - await run_agent(agent) + await run_agent(agent, interruption_probability=0, backchannel_probability=0) except KeyboardInterrupt: agent.terminate() if __name__ == "__main__": - make_parser_and_maybe_trace() asyncio.run(agent_main()) diff --git a/playground/streaming/agent/restful_user_implemented_agent.py b/playground/streaming/agent/restful_user_implemented_agent.py index d5d36402a..d8af0c976 100644 --- a/playground/streaming/agent/restful_user_implemented_agent.py +++ b/playground/streaming/agent/restful_user_implemented_agent.py @@ -1,6 +1,7 @@ # type: ignore from typing import Generator, Optional, Tuple + from vocode.streaming.models.agent import RESTfulAgentOutput, RESTfulAgentText from vocode.streaming.user_implemented_agent.restful_agent import RESTfulAgent diff --git a/playground/streaming/agent/websocket_user_implemented_agent.py b/playground/streaming/agent/websocket_user_implemented_agent.py index 157a5aa0c..56698bc44 100644 --- a/playground/streaming/agent/websocket_user_implemented_agent.py +++ b/playground/streaming/agent/websocket_user_implemented_agent.py @@ -1,4 +1,5 @@ import asyncio + from websockets.server import serve from vocode.streaming.models.websocket_agent import ( diff --git a/playground/streaming/benchmark.py b/playground/streaming/benchmark.py index 2717a2af3..26b2dbf97 100644 --- a/playground/streaming/benchmark.py +++ b/playground/streaming/benchmark.py @@ -1,74 +1,53 @@ -from collections import defaultdict -import os -import re -import json +raise DeprecationWarning("This playground script is deprecated and will be removed in the future.") + import argparse import asyncio -import logging -from tqdm import tqdm +import json +import os +from collections import defaultdict + import sounddevice as sd -from opentelemetry import trace, metrics +from loguru import logger +from opentelemetry import metrics, trace from opentelemetry.sdk.metrics import MeterProvider +from opentelemetry.sdk.metrics.export import InMemoryMetricReader +from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import SimpleSpanProcessor -from opentelemetry.sdk.metrics.export import ( - InMemoryMetricReader, -) from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter -from opentelemetry.sdk.resources import Resource +from playground.streaming.tracing_utils import get_final_metrics +from tqdm import tqdm + +from vocode.streaming.agent import ChatGPTAgent from vocode.streaming.agent.base_agent import TranscriptionAgentInput -from vocode.streaming.agent.vertex_ai_agent import ChatVertexAIAgent from vocode.streaming.input_device.file_input_device import FileInputDevice -from vocode.streaming.agent import ChatGPTAgent, ChatAnthropicAgent from vocode.streaming.input_device.microphone_input import MicrophoneInput +from vocode.streaming.models.agent import AzureOpenAIConfig, ChatGPTAgentConfig from vocode.streaming.models.message import BaseMessage -from vocode.streaming.models.agent import ( - AzureOpenAIConfig, - ChatGPTAgentConfig, - ChatAnthropicAgentConfig, - ChatVertexAIAgentConfig, -) -from vocode.streaming.models.synthesizer import ( +from vocode.streaming.models.synthesizer import ( # BarkSynthesizerConfig,; CoquiSynthesizerConfig,; CoquiTTSSynthesizerConfig, AzureSynthesizerConfig, - BarkSynthesizerConfig, - CoquiSynthesizerConfig, - CoquiTTSSynthesizerConfig, ElevenLabsSynthesizerConfig, - GTTSSynthesizerConfig, - GoogleSynthesizerConfig, PlayHtSynthesizerConfig, RimeSynthesizerConfig, - StreamElementsSynthesizerConfig, ) from vocode.streaming.models.transcriber import ( - DeepgramTranscriberConfig, AssemblyAITranscriberConfig, + DeepgramTranscriberConfig, PunctuationEndpointingConfig, + Transcription, ) from vocode.streaming.models.transcript import Transcript from vocode.streaming.output_device.file_output_device import FileOutputDevice -from vocode.streaming.synthesizer import ( - AzureSynthesizer, - BarkSynthesizer, - CoquiSynthesizer, - CoquiTTSSynthesizer, - ElevenLabsSynthesizer, - GTTSSynthesizer, - GoogleSynthesizer, - PlayHtSynthesizer, - RimeSynthesizer, - StreamElementsSynthesizer, -) -from vocode.streaming.transcriber import DeepgramTranscriber, AssemblyAITranscriber -from vocode.streaming.transcriber.base_transcriber import Transcription +from vocode.streaming.synthesizer.azure_synthesizer import AzureSynthesizer +from vocode.streaming.synthesizer.eleven_labs_websocket_synthesizer import ElevenLabsWSSynthesizer +from vocode.streaming.synthesizer.elevenlabs_synthesizer import ElevenLabsSynthesizer +from vocode.streaming.synthesizer.play_ht_synthesizer import PlayHtSynthesizer +from vocode.streaming.synthesizer.play_ht_synthesizer_v2 import PlayHtSynthesizerV2 +from vocode.streaming.synthesizer.rime_synthesizer import RimeSynthesizer +from vocode.streaming.transcriber.assembly_ai_transcriber import AssemblyAITranscriber +from vocode.streaming.transcriber.deepgram_transcriber import DeepgramTranscriber from vocode.streaming.utils import get_chunk_size_per_second, remove_non_letters_digits -from vocode.streaming.utils.worker import InterruptibleEvent -from playground.streaming.tracing_utils import get_final_metrics - -logger = logging.getLogger(__name__) -logging.basicConfig() -logger.setLevel(logging.DEBUG) tracer = trace.get_tracer(__name__) meter = metrics.get_meter(__name__) @@ -76,25 +55,27 @@ # Create the parser parser = argparse.ArgumentParser( description="Benchmark Vocode's transcribers, agents, and synthesizers.\n" - + "Example usage: python playground/streaming/benchmark.py --all --all_num_cycles 3 --create_graphs" + + "Example usage: python playground/streaming/benchmark.py --all --all_num_cycles 3 --create_graphs", ) synthesizer_classes = { "elevenlabs": (ElevenLabsSynthesizer, ElevenLabsSynthesizerConfig), + "elevenlabsws": (ElevenLabsWSSynthesizer, ElevenLabsSynthesizerConfig), "azure": (AzureSynthesizer, AzureSynthesizerConfig), - "bark": (BarkSynthesizer, BarkSynthesizerConfig), + # "bark": (BarkSynthesizer, BarkSynthesizerConfig), # "coqui": (CoquiSynthesizer, CoquiSynthesizerConfig), # "coquitts": (CoquiTTSSynthesizer, CoquiTTSSynthesizerConfig), - "google": (GoogleSynthesizer, GoogleSynthesizerConfig), - "gtts": (GTTSSynthesizer, GTTSSynthesizerConfig), + # "google": (GoogleSynthesizer, GoogleSynthesizerConfig), + # "gtts": (GTTSSynthesizer, GTTSSynthesizerConfig), "playht": (PlayHtSynthesizer, PlayHtSynthesizerConfig), + "playht2": (PlayHtSynthesizerV2, PlayHtSynthesizerConfig), "rime": (RimeSynthesizer, RimeSynthesizerConfig), - "streamelements": (StreamElementsSynthesizer, StreamElementsSynthesizerConfig), + # "streamelements": (StreamElementsSynthesizer, StreamElementsSynthesizerConfig), } # These synthesizers stream output so they need to be traced within this file. -STREAMING_SYNTHESIZERS = ["azure", "elevenlabs"] +STREAMING_SYNTHESIZERS = ["azure", "elevenlabs", "playht2", "elevenlabsws"] TRANSCRIBER_CHOICES = ["deepgram", "assemblyai"] @@ -102,9 +83,6 @@ "gpt_gpt-3.5-turbo", "gpt_gpt-4", "azuregpt_gpt-35-turbo", - "anthropic_claude-v1", - "anthropic_claude-instant-v1", - "vertex_ai_chat-bison@001", ] SYNTHESIZER_CHOICES = list(synthesizer_classes) @@ -135,7 +113,7 @@ parser.add_argument( "--transcriber_audio", type=str, - default="playground/streaming/test.wav", + default=f"{os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test.wav')}", help="Path to the audio file to transcribe", ) parser.add_argument( @@ -244,14 +222,14 @@ except ImportError: print( "ERROR: The --create_graphs flag requires matplotlib. Please " - + "install matplotlib and try again." + + "install matplotlib and try again.", ) exit(1) if args.just_graphs: print( "--just_graphs is set! Skipping computing statistics and instead " - + "generating graphs from the last saved benchmark result JSON file." + + "generating graphs from the last saved benchmark result JSON file.", ) should_generate_responses = not args.no_generate_responses @@ -265,13 +243,13 @@ def get_transcriber(transcriber_name, file_input): DeepgramTranscriberConfig.from_input_device( file_input, endpointing_config=PunctuationEndpointingConfig(), - ) + ), ) elif transcriber_name == "assemblyai": transcriber = AssemblyAITranscriber( AssemblyAITranscriberConfig.from_input_device( file_input, - ) + ), ) return transcriber @@ -289,9 +267,7 @@ async def run_agents(): for agent_name in tqdm(args.agents, desc="Agents"): company, model_name = agent_name.rsplit("_", 1) length_meter = meter.create_counter( - remove_non_letters_digits( - f"agent.agent_chat_{company}-{model_name}.total_characters" - ), + remove_non_letters_digits(f"agent.agent_chat_{company}-{model_name}.total_characters"), ) for _ in tqdm(range(args.agent_num_cycles), desc="Agent Cycles"): if company == "gpt": @@ -302,7 +278,7 @@ async def run_agents(): allow_agent_to_be_cut_off=False, model_name=model_name, generate_responses=should_generate_responses, - ) + ), ) elif company == "azuregpt": agent = ChatGPTAgent( @@ -310,54 +286,34 @@ async def run_agents(): initial_message=None, prompt_preamble=args.agent_prompt_preamble, allow_agent_to_be_cut_off=False, - azure_params=AzureOpenAIConfig(engine=model_name), + azure_params=AzureOpenAIConfig(deployment_name=model_name), generate_responses=should_generate_responses, - ) - ) - elif company == "anthropic": - agent = ChatAnthropicAgent( - ChatAnthropicAgentConfig( - initial_message=None, - allow_agent_to_be_cut_off=False, - model_name=model_name, - generate_responses=should_generate_responses, - ) - ) - elif company == "vertex_ai": - agent = ChatVertexAIAgent( - ChatVertexAIAgentConfig( - initial_message=None, - prompt_preamble=args.agent_prompt_preamble, - allow_agent_to_be_cut_off=False, - model_name=model_name, - generate_responses=False, - ) + ), ) agent.attach_transcript(Transcript()) - agent_task = agent.start() + agent_task = agent.start() # noqa: F841 message = TranscriptionAgentInput( transcription=Transcription( - message=args.agent_first_input, confidence=1.0, is_final=True + message=args.agent_first_input, + confidence=1.0, + is_final=True, ), conversation_id=0, ) agent.consume_nonblocking( - agent.interruptible_event_factory.create_interruptible_event(message) + agent.interruptible_event_factory.create_interruptible_event(message), ) while True: try: - message = await asyncio.wait_for( - agent.output_queue.get(), timeout=15 - ) - length_meter.add(len(message.payload.message.text)) - logger.debug( - f"[Agent: {agent_name}] Response from API: {message.payload.message.text}" - ) + message = await asyncio.wait_for(agent.output_queue.get(), timeout=15) + if isinstance(message.payload.message, BaseMessage): + length_meter.add(len(message.payload.message.text)) + logger.debug( + f"[Agent: {agent_name}] Response from API: {message.payload.message.text}", + ) except asyncio.TimeoutError: - logger.debug( - f"[Agent: {agent_name}] Agent queue is empty, stopping..." - ) + logger.debug(f"[Agent: {agent_name}] Agent queue is empty, stopping...") break @@ -367,54 +323,57 @@ def create_file_output_device(synthesizer_name, extra_info=""): os.path.join(args.results_dir, f"{synthesizer_name}{extra_info}.wav"), ) - for synthesizer_cycle_idx in tqdm( - range(args.synthesizer_num_cycles), desc="Synthesizer Cycles" - ): - for synthesizer_name in args.synthesizers: - file_output = create_file_output_device( - synthesizer_name, f"-run={synthesizer_cycle_idx}" - ) - synthesizer_class, synthesizer_config_class = synthesizer_classes[ - synthesizer_name - ] - extra_config = {} - if synthesizer_name == "playht": - extra_config["voice_id"] = "larry" - elif synthesizer_name == "rime": - extra_config["speaker"] = "young_male_unmarked-1" - synthesizer = synthesizer_class( - synthesizer_config_class.from_output_device(file_output, **extra_config) - ) - - chunk_size = get_chunk_size_per_second( - synthesizer.get_synthesizer_config().audio_encoding, - synthesizer.get_synthesizer_config().sampling_rate, + for synthesizer_name in args.synthesizers: + file_output = create_file_output_device(synthesizer_name) + synthesizer_class, synthesizer_config_class = synthesizer_classes[synthesizer_name] + extra_config = {} + if synthesizer_name == "playht": + extra_config["voice_id"] = "larry" + elif synthesizer_name == "rime": + extra_config["speaker"] = "young_male-1" + elif synthesizer_name == "playht2": + extra_config["voice_id"] = ( + "s3://voice-cloning-zero-shot/d9ff78ba-d016-47f6-b0ef-dd630f59414e/female-cs/manifest.json" ) + extra_config["version"] = "2" + elif synthesizer_name == "elevenlabs": + extra_config["experimental_streaming"] = True + elif synthesizer_name == "elevenlabsws": + extra_config["experimental_websocket"] = True + config = synthesizer_config_class.from_output_device(file_output, **extra_config) + synthesizer = synthesizer_class(config) + + chunk_size = 0.1 * get_chunk_size_per_second( + synthesizer.get_synthesizer_config().audio_encoding, + synthesizer.get_synthesizer_config().sampling_rate, + ) - current_synthesizer_is_streaming = ( - synthesizer_name in STREAMING_SYNTHESIZERS - ) + current_synthesizer_is_streaming = synthesizer_name in STREAMING_SYNTHESIZERS + for _ in tqdm( + range(args.synthesizer_num_cycles), + desc=f"Synthesizer Cycles ({synthesizer_name})", + ): if current_synthesizer_is_streaming: total_synthesis_span = tracer.start_span( - f"synthesizer.{synthesizer_name}.create_total" + f"synthesizer.{synthesizer_name}.create_total", ) first_synthesis_span = tracer.start_span( - f"synthesizer.{synthesizer_name}.create_first" + f"synthesizer.{synthesizer_name}.create_first", ) try: - synthesis_result = await synthesizer.create_speech( + synthesis_result = await synthesizer.create_speech_uncached( message=BaseMessage(text=args.synthesizer_text), - chunk_size=chunk_size, + chunk_size=int(chunk_size), ) except asyncio.TimeoutError: logger.error( - f"[Synthesizer: {synthesizer_name}] Timed out while synthesizing. Skipping {synthesizer_name}..." + f"[Synthesizer: {synthesizer_name}] Timed out while synthesizing. Skipping {synthesizer_name}...", ) continue except Exception as e: logger.error( - f"[Synthesizer: {synthesizer_name}] Exception while synthesizing: {e}. Skipping {synthesizer_name}..." + f"[Synthesizer: {synthesizer_name}] Exception while synthesizing: {e}. Skipping {synthesizer_name}...", ) continue chunk_generator = synthesis_result.chunk_generator @@ -423,17 +382,22 @@ def create_file_output_device(synthesizer_name, extra_info=""): first_chunk = True while True: pbar.update(1) - chunk_result = await chunk_generator.__anext__() - if current_synthesizer_is_streaming and first_chunk: - first_chunk = False - first_synthesis_span.end() - file_output.consume_nonblocking(chunk_result.chunk) + try: + chunk_result = await chunk_generator.__anext__() + if current_synthesizer_is_streaming and first_chunk: + first_chunk = False + first_synthesis_span.end() + file_output.consume_nonblocking(chunk_result.chunk) + except StopAsyncIteration: + break if chunk_result.is_last_chunk: break if current_synthesizer_is_streaming: total_synthesis_span.end() + await synthesizer.tear_down() + async def run_transcribers(): sample_rate = 44100 @@ -451,13 +415,14 @@ async def run_transcribers(): ) for transcriber_cycle_idx in tqdm( - range(args.transcriber_num_cycles), desc="Transcriber Cycles" + range(args.transcriber_num_cycles), + desc="Transcriber Cycles", ): for transcriber_name in tqdm(args.transcribers, desc="Transcribers"): transcriber = get_transcriber(transcriber_name, input_device) if not args.transcriber_use_mic: input_device.load() - transcriber_task = transcriber.start() + transcriber_task = transcriber.start() # noqa: F841 if args.transcriber_use_mic: @@ -485,14 +450,15 @@ async def send_audio_task(): ) while True: try: - transcription = await asyncio.wait_for( - transcriber.output_queue.get(), timeout=5 + transcription = await asyncio.wait_for( # noqa: F841 + transcriber.output_queue.get(), + timeout=5, ) # update the progress bar status pbar.update(round(transcriber.audio_cursor - pbar.n, 2)) except asyncio.TimeoutError: logger.debug( - f"[Transcriber: {transcriber_name}] Transcriber queue is empty, stopping transcription..." + f"[Transcriber: {transcriber_name}] Transcriber queue is empty, stopping transcription...", ) send_audio.cancel() break diff --git a/playground/streaming/synthesizer/synthesize.py b/playground/streaming/synthesizer/synthesize.py index 41adfbef8..b27153c4b 100644 --- a/playground/streaming/synthesizer/synthesize.py +++ b/playground/streaming/synthesizer/synthesize.py @@ -1,39 +1,26 @@ import time -import argparse -from typing import Optional -import aiohttp -from vocode.streaming.agent.bot_sentiment_analyser import BotSentiment + from vocode.streaming.models.message import BaseMessage -from vocode.streaming.models.synthesizer import ( - AzureSynthesizerConfig, - GoogleSynthesizerConfig, - PlayHtSynthesizerConfig, - ElevenLabsSynthesizerConfig, - RimeSynthesizerConfig, - PollySynthesizerConfig, -) +from vocode.streaming.models.synthesizer import AzureSynthesizerConfig from vocode.streaming.output_device.base_output_device import BaseOutputDevice from vocode.streaming.output_device.speaker_output import SpeakerOutput -from vocode.streaming.synthesizer import * +from vocode.streaming.synthesizer.azure_synthesizer import AzureSynthesizer +from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer from vocode.streaming.utils import get_chunk_size_per_second -from playground.streaming.tracing_utils import make_parser_and_maybe_trace - if __name__ == "__main__": import asyncio + from dotenv import load_dotenv load_dotenv() - make_parser_and_maybe_trace() - seconds_per_chunk = 1 async def speak( synthesizer: BaseSynthesizer, output_device: BaseOutputDevice, message: BaseMessage, - bot_sentiment: Optional[BotSentiment] = None, ): message_sent = message.text cut_off = False @@ -42,19 +29,15 @@ async def speak( synthesizer.get_synthesizer_config().sampling_rate, ) # ClientSession needs to be created within the async task - synthesizer.aiohttp_session = aiohttp.ClientSession() - synthesis_result = await synthesizer.create_speech( + synthesis_result = await synthesizer.create_speech_uncached( message=message, - chunk_size=chunk_size, - bot_sentiment=bot_sentiment, + chunk_size=int(chunk_size), ) chunk_idx = 0 async for chunk_result in synthesis_result.chunk_generator: try: start_time = time.time() - speech_length_seconds = seconds_per_chunk * ( - len(chunk_result.chunk) / chunk_size - ) + speech_length_seconds = seconds_per_chunk * (len(chunk_result.chunk) / chunk_size) output_device.consume_nonblocking(chunk_result.chunk) end_time = time.time() await asyncio.sleep( @@ -63,19 +46,11 @@ async def speak( 0, ) ) - print( - "Sent chunk {} with size {}".format( - chunk_idx, len(chunk_result.chunk) - ) - ) + print("Sent chunk {} with size {}".format(chunk_idx, len(chunk_result.chunk))) chunk_idx += 1 except asyncio.CancelledError: seconds = chunk_idx * seconds_per_chunk - print( - "Interrupted, stopping text to speech after {} chunks".format( - chunk_idx - ) - ) + print("Interrupted, stopping text to speech after {} chunks".format(chunk_idx)) message_sent = f"{synthesis_result.get_message_up_to(seconds)}-" cut_off = True break @@ -83,6 +58,8 @@ async def speak( return message_sent, cut_off async def main(): + speaker_output = SpeakerOutput.from_default_device() + synthesizer = AzureSynthesizer(AzureSynthesizerConfig.from_output_device(speaker_output)) try: while True: message_sent, _ = await speak( @@ -93,13 +70,7 @@ async def main(): print("Message sent: ", message_sent) except KeyboardInterrupt: print("Interrupted, exiting") - await synthesizer.tear_down() - - speaker_output = SpeakerOutput.from_default_device() # replace with the synthesizer you want to test # Note: --trace will not work with AzureSynthesizer - synthesizer = AzureSynthesizer( - AzureSynthesizerConfig.from_output_device(speaker_output) - ) asyncio.run(main()) diff --git a/playground/streaming/tracing_utils.py b/playground/streaming/tracing_utils.py index a92343784..2dd1c8656 100644 --- a/playground/streaming/tracing_utils.py +++ b/playground/streaming/tracing_utils.py @@ -1,12 +1,21 @@ -import re +raise DeprecationWarning( + "OpenTelemetry support is currently deprecated, but planned to be re-enabled in the future." +) + import argparse +import re from collections import defaultdict from threading import RLock from typing import Any, Dict, List, Optional, Union + +from opentelemetry.sdk.metrics.export import ( + HistogramDataPoint, + Metric, + MetricReader, + MetricsData, + NumberDataPoint, +) from opentelemetry.sdk.trace.export import SpanExporter -from opentelemetry.sdk.metrics.export import MetricReader -from opentelemetry.sdk.metrics.export import Metric, MetricsData -from opentelemetry.sdk.metrics.export import NumberDataPoint, HistogramDataPoint NANOSECONDS_PER_SECOND = 1e9 @@ -43,21 +52,16 @@ def get_final_metrics(scope_metrics, final_spans=None): transcriber_str = metric_name.split(".")[1] final_metrics[metric_name] = ( raw_metric.sum - / formatted_metric_results[ - f"transcriber.{transcriber_str}.duration" - ].sum + / formatted_metric_results[f"transcriber.{transcriber_str}.duration"].sum ) elif re.match(r"agent.*\.total_characters", metric_name) and final_spans: agent_str = metric_name.split(".", 1)[1].rsplit(".", 1)[0] generate_total_key = f"agent.{agent_str}.generate_total" respond_total_key = f"agent.{agent_str}.respond_total" - final_metrics[f"agent.{agent_str}.characters_per_second"] = ( - raw_metric.value - / ( - sum(final_spans[generate_total_key]) - if generate_total_key in final_spans - else sum(final_spans[respond_total_key]) - ) + final_metrics[f"agent.{agent_str}.characters_per_second"] = raw_metric.value / ( + sum(final_spans[generate_total_key]) + if generate_total_key in final_spans + else sum(final_spans[respond_total_key]) ) else: try: @@ -104,15 +108,13 @@ def shutdown(self, timeout_millis: float = 30_000, **kwargs) -> None: def make_parser_and_maybe_trace(): parser = argparse.ArgumentParser() - parser.add_argument( - "--trace", action="store_true", help="Log latencies and other statistics" - ) + parser.add_argument("--trace", action="store_true", help="Log latencies and other statistics") args = parser.parse_args() if args.trace: from opentelemetry import trace + from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import SimpleSpanProcessor - from opentelemetry.sdk.resources import Resource trace.set_tracer_provider(TracerProvider(resource=Resource.create({}))) span_exporter = PrintDurationSpanExporter() diff --git a/playground/streaming/transcriber/transcribe.py b/playground/streaming/transcriber/transcribe.py index 0ce3ea3ce..111c27246 100644 --- a/playground/streaming/transcriber/transcribe.py +++ b/playground/streaming/transcriber/transcribe.py @@ -1,35 +1,18 @@ -import argparse - from vocode.streaming.input_device.microphone_input import MicrophoneInput -from vocode.streaming.models.transcriber import ( - DeepgramTranscriberConfig, - PunctuationEndpointingConfig, +from vocode.streaming.models.transcriber import DeepgramTranscriberConfig, Transcription +from vocode.streaming.transcriber.base_transcriber import BaseTranscriber +from vocode.streaming.transcriber.deepgram_transcriber import ( + DeepgramEndpointingConfig, + DeepgramTranscriber, ) -from vocode.streaming.transcriber.base_transcriber import BaseTranscriber, Transcription -from vocode.streaming.transcriber import * - if __name__ == "__main__": import asyncio + from dotenv import load_dotenv load_dotenv() - parser = argparse.ArgumentParser() - parser.add_argument( - "--trace", action="store_true", help="Log latencies and other statistics" - ) - args = parser.parse_args() - - if args.trace: - from opentelemetry import metrics - from opentelemetry.sdk.metrics import MeterProvider - from playground.streaming.tracing_utils import SpecificStatisticsReader - - reader = SpecificStatisticsReader() - provider = MeterProvider(metric_readers=[reader]) - metrics.set_meter_provider(provider) - async def print_output(transcriber: BaseTranscriber): while True: transcription: Transcription = await transcriber.output_queue.get() @@ -41,7 +24,7 @@ async def listen(): # replace with the transcriber you want to test transcriber = DeepgramTranscriber( DeepgramTranscriberConfig.from_input_device( - microphone_input, endpointing_config=PunctuationEndpointingConfig() + microphone_input, endpointing_config=DeepgramEndpointingConfig() ) ) transcriber.start() diff --git a/poetry.lock b/poetry.lock index 04b2b0796..c349910d4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,112 +1,100 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. [[package]] name = "aiohttp" -version = "3.8.5" +version = "3.9.5" description = "Async http client/server framework (asyncio)" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "aiohttp-3.8.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a94159871304770da4dd371f4291b20cac04e8c94f11bdea1c3478e557fbe0d8"}, - {file = "aiohttp-3.8.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:13bf85afc99ce6f9ee3567b04501f18f9f8dbbb2ea11ed1a2e079670403a7c84"}, - {file = "aiohttp-3.8.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ce2ac5708501afc4847221a521f7e4b245abf5178cf5ddae9d5b3856ddb2f3a"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96943e5dcc37a6529d18766597c491798b7eb7a61d48878611298afc1fca946c"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ad5c3c4590bb3cc28b4382f031f3783f25ec223557124c68754a2231d989e2b"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c413c633d0512df4dc7fd2373ec06cc6a815b7b6d6c2f208ada7e9e93a5061d"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df72ac063b97837a80d80dec8d54c241af059cc9bb42c4de68bd5b61ceb37caa"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c48c5c0271149cfe467c0ff8eb941279fd6e3f65c9a388c984e0e6cf57538e14"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:368a42363c4d70ab52c2c6420a57f190ed3dfaca6a1b19afda8165ee16416a82"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7607ec3ce4993464368505888af5beb446845a014bc676d349efec0e05085905"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0d21c684808288a98914e5aaf2a7c6a3179d4df11d249799c32d1808e79503b5"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:312fcfbacc7880a8da0ae8b6abc6cc7d752e9caa0051a53d217a650b25e9a691"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ad093e823df03bb3fd37e7dec9d4670c34f9e24aeace76808fc20a507cace825"}, - {file = "aiohttp-3.8.5-cp310-cp310-win32.whl", hash = "sha256:33279701c04351a2914e1100b62b2a7fdb9a25995c4a104259f9a5ead7ed4802"}, - {file = "aiohttp-3.8.5-cp310-cp310-win_amd64.whl", hash = "sha256:6e4a280e4b975a2e7745573e3fc9c9ba0d1194a3738ce1cbaa80626cc9b4f4df"}, - {file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae871a964e1987a943d83d6709d20ec6103ca1eaf52f7e0d36ee1b5bebb8b9b9"}, - {file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:461908b2578955045efde733719d62f2b649c404189a09a632d245b445c9c975"}, - {file = "aiohttp-3.8.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:72a860c215e26192379f57cae5ab12b168b75db8271f111019509a1196dfc780"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc14be025665dba6202b6a71cfcdb53210cc498e50068bc088076624471f8bb9"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8af740fc2711ad85f1a5c034a435782fbd5b5f8314c9a3ef071424a8158d7f6b"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:841cd8233cbd2111a0ef0a522ce016357c5e3aff8a8ce92bcfa14cef890d698f"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed1c46fb119f1b59304b5ec89f834f07124cd23ae5b74288e364477641060ff"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84f8ae3e09a34f35c18fa57f015cc394bd1389bce02503fb30c394d04ee6b938"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62360cb771707cb70a6fd114b9871d20d7dd2163a0feafe43fd115cfe4fe845e"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:23fb25a9f0a1ca1f24c0a371523546366bb642397c94ab45ad3aedf2941cec6a"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0ba0d15164eae3d878260d4c4df859bbdc6466e9e6689c344a13334f988bb53"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5d20003b635fc6ae3f96d7260281dfaf1894fc3aa24d1888a9b2628e97c241e5"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0175d745d9e85c40dcc51c8f88c74bfbaef9e7afeeeb9d03c37977270303064c"}, - {file = "aiohttp-3.8.5-cp311-cp311-win32.whl", hash = "sha256:2e1b1e51b0774408f091d268648e3d57f7260c1682e7d3a63cb00d22d71bb945"}, - {file = "aiohttp-3.8.5-cp311-cp311-win_amd64.whl", hash = "sha256:043d2299f6dfdc92f0ac5e995dfc56668e1587cea7f9aa9d8a78a1b6554e5755"}, - {file = "aiohttp-3.8.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cae533195e8122584ec87531d6df000ad07737eaa3c81209e85c928854d2195c"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f21e83f355643c345177a5d1d8079f9f28b5133bcd154193b799d380331d5d3"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a75ef35f2df54ad55dbf4b73fe1da96f370e51b10c91f08b19603c64004acc"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e2e9839e14dd5308ee773c97115f1e0a1cb1d75cbeeee9f33824fa5144c7634"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44e65da1de4403d0576473e2344828ef9c4c6244d65cf4b75549bb46d40b8dd"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d847e4cde6ecc19125ccbc9bfac4a7ab37c234dd88fbb3c5c524e8e14da543"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:c7a815258e5895d8900aec4454f38dca9aed71085f227537208057853f9d13f2"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:8b929b9bd7cd7c3939f8bcfffa92fae7480bd1aa425279d51a89327d600c704d"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:5db3a5b833764280ed7618393832e0853e40f3d3e9aa128ac0ba0f8278d08649"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:a0215ce6041d501f3155dc219712bc41252d0ab76474615b9700d63d4d9292af"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:fd1ed388ea7fbed22c4968dd64bab0198de60750a25fe8c0c9d4bef5abe13824"}, - {file = "aiohttp-3.8.5-cp36-cp36m-win32.whl", hash = "sha256:6e6783bcc45f397fdebc118d772103d751b54cddf5b60fbcc958382d7dd64f3e"}, - {file = "aiohttp-3.8.5-cp36-cp36m-win_amd64.whl", hash = "sha256:b5411d82cddd212644cf9360879eb5080f0d5f7d809d03262c50dad02f01421a"}, - {file = "aiohttp-3.8.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:01d4c0c874aa4ddfb8098e85d10b5e875a70adc63db91f1ae65a4b04d3344cda"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5980a746d547a6ba173fd5ee85ce9077e72d118758db05d229044b469d9029a"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a482e6da906d5e6e653be079b29bc173a48e381600161c9932d89dfae5942ef"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80bd372b8d0715c66c974cf57fe363621a02f359f1ec81cba97366948c7fc873"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1161b345c0a444ebcf46bf0a740ba5dcf50612fd3d0528883fdc0eff578006a"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd56db019015b6acfaaf92e1ac40eb8434847d9bf88b4be4efe5bfd260aee692"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:153c2549f6c004d2754cc60603d4668899c9895b8a89397444a9c4efa282aaf4"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4a01951fabc4ce26ab791da5f3f24dca6d9a6f24121746eb19756416ff2d881b"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bfb9162dcf01f615462b995a516ba03e769de0789de1cadc0f916265c257e5d8"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:7dde0009408969a43b04c16cbbe252c4f5ef4574ac226bc8815cd7342d2028b6"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4149d34c32f9638f38f544b3977a4c24052042affa895352d3636fa8bffd030a"}, - {file = "aiohttp-3.8.5-cp37-cp37m-win32.whl", hash = "sha256:68c5a82c8779bdfc6367c967a4a1b2aa52cd3595388bf5961a62158ee8a59e22"}, - {file = "aiohttp-3.8.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2cf57fb50be5f52bda004b8893e63b48530ed9f0d6c96c84620dc92fe3cd9b9d"}, - {file = "aiohttp-3.8.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:eca4bf3734c541dc4f374ad6010a68ff6c6748f00451707f39857f429ca36ced"}, - {file = "aiohttp-3.8.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1274477e4c71ce8cfe6c1ec2f806d57c015ebf84d83373676036e256bc55d690"}, - {file = "aiohttp-3.8.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28c543e54710d6158fc6f439296c7865b29e0b616629767e685a7185fab4a6b9"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:910bec0c49637d213f5d9877105d26e0c4a4de2f8b1b29405ff37e9fc0ad52b8"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5443910d662db951b2e58eb70b0fbe6b6e2ae613477129a5805d0b66c54b6cb7"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e460be6978fc24e3df83193dc0cc4de46c9909ed92dd47d349a452ef49325b7"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb1558def481d84f03b45888473fc5a1f35747b5f334ef4e7a571bc0dfcb11f8"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34dd0c107799dcbbf7d48b53be761a013c0adf5571bf50c4ecad5643fe9cfcd0"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aa1990247f02a54185dc0dff92a6904521172a22664c863a03ff64c42f9b5410"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0e584a10f204a617d71d359fe383406305a4b595b333721fa50b867b4a0a1548"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:a3cf433f127efa43fee6b90ea4c6edf6c4a17109d1d037d1a52abec84d8f2e42"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c11f5b099adafb18e65c2c997d57108b5bbeaa9eeee64a84302c0978b1ec948b"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:84de26ddf621d7ac4c975dbea4c945860e08cccde492269db4e1538a6a6f3c35"}, - {file = "aiohttp-3.8.5-cp38-cp38-win32.whl", hash = "sha256:ab88bafedc57dd0aab55fa728ea10c1911f7e4d8b43e1d838a1739f33712921c"}, - {file = "aiohttp-3.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:5798a9aad1879f626589f3df0f8b79b3608a92e9beab10e5fda02c8a2c60db2e"}, - {file = "aiohttp-3.8.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a6ce61195c6a19c785df04e71a4537e29eaa2c50fe745b732aa937c0c77169f3"}, - {file = "aiohttp-3.8.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:773dd01706d4db536335fcfae6ea2440a70ceb03dd3e7378f3e815b03c97ab51"}, - {file = "aiohttp-3.8.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f83a552443a526ea38d064588613aca983d0ee0038801bc93c0c916428310c28"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f7372f7341fcc16f57b2caded43e81ddd18df53320b6f9f042acad41f8e049a"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea353162f249c8097ea63c2169dd1aa55de1e8fecbe63412a9bc50816e87b761"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d47ae48db0b2dcf70bc8a3bc72b3de86e2a590fc299fdbbb15af320d2659de"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d827176898a2b0b09694fbd1088c7a31836d1a505c243811c87ae53a3f6273c1"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3562b06567c06439d8b447037bb655ef69786c590b1de86c7ab81efe1c9c15d8"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4e874cbf8caf8959d2adf572a78bba17cb0e9d7e51bb83d86a3697b686a0ab4d"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6809a00deaf3810e38c628e9a33271892f815b853605a936e2e9e5129762356c"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:33776e945d89b29251b33a7e7d006ce86447b2cfd66db5e5ded4e5cd0340585c"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eaeed7abfb5d64c539e2db173f63631455f1196c37d9d8d873fc316470dfbacd"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e91d635961bec2d8f19dfeb41a539eb94bd073f075ca6dae6c8dc0ee89ad6f91"}, - {file = "aiohttp-3.8.5-cp39-cp39-win32.whl", hash = "sha256:00ad4b6f185ec67f3e6562e8a1d2b69660be43070bd0ef6fcec5211154c7df67"}, - {file = "aiohttp-3.8.5-cp39-cp39-win_amd64.whl", hash = "sha256:c0a9034379a37ae42dea7ac1e048352d96286626251862e448933c0f59cbd79c"}, - {file = "aiohttp-3.8.5.tar.gz", hash = "sha256:b9552ec52cc147dbf1944ac7ac98af7602e51ea2dcd076ed194ca3c0d1c7d0bc"}, + {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fcde4c397f673fdec23e6b05ebf8d4751314fa7c24f93334bf1f1364c1c69ac7"}, + {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d6b3f1fabe465e819aed2c421a6743d8debbde79b6a8600739300630a01bf2c"}, + {file = "aiohttp-3.9.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ae79c1bc12c34082d92bf9422764f799aee4746fd7a392db46b7fd357d4a17a"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d3ebb9e1316ec74277d19c5f482f98cc65a73ccd5430540d6d11682cd857430"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84dabd95154f43a2ea80deffec9cb44d2e301e38a0c9d331cc4aa0166fe28ae3"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8a02fbeca6f63cb1f0475c799679057fc9268b77075ab7cf3f1c600e81dd46b"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c26959ca7b75ff768e2776d8055bf9582a6267e24556bb7f7bd29e677932be72"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:714d4e5231fed4ba2762ed489b4aec07b2b9953cf4ee31e9871caac895a839c0"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7a6a8354f1b62e15d48e04350f13e726fa08b62c3d7b8401c0a1314f02e3558"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c413016880e03e69d166efb5a1a95d40f83d5a3a648d16486592c49ffb76d0db"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ff84aeb864e0fac81f676be9f4685f0527b660f1efdc40dcede3c251ef1e867f"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ad7f2919d7dac062f24d6f5fe95d401597fbb015a25771f85e692d043c9d7832"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:702e2c7c187c1a498a4e2b03155d52658fdd6fda882d3d7fbb891a5cf108bb10"}, + {file = "aiohttp-3.9.5-cp310-cp310-win32.whl", hash = "sha256:67c3119f5ddc7261d47163ed86d760ddf0e625cd6246b4ed852e82159617b5fb"}, + {file = "aiohttp-3.9.5-cp310-cp310-win_amd64.whl", hash = "sha256:471f0ef53ccedec9995287f02caf0c068732f026455f07db3f01a46e49d76bbb"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ae53e33ee7476dd3d1132f932eeb39bf6125083820049d06edcdca4381f342"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c088c4d70d21f8ca5c0b8b5403fe84a7bc8e024161febdd4ef04575ef35d474d"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:639d0042b7670222f33b0028de6b4e2fad6451462ce7df2af8aee37dcac55424"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f26383adb94da5e7fb388d441bf09c61e5e35f455a3217bfd790c6b6bc64b2ee"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66331d00fb28dc90aa606d9a54304af76b335ae204d1836f65797d6fe27f1ca2"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ff550491f5492ab5ed3533e76b8567f4b37bd2995e780a1f46bca2024223233"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f22eb3a6c1080d862befa0a89c380b4dafce29dc6cd56083f630073d102eb595"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a81b1143d42b66ffc40a441379387076243ef7b51019204fd3ec36b9f69e77d6"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f64fd07515dad67f24b6ea4a66ae2876c01031de91c93075b8093f07c0a2d93d"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:93e22add827447d2e26d67c9ac0161756007f152fdc5210277d00a85f6c92323"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:55b39c8684a46e56ef8c8d24faf02de4a2b2ac60d26cee93bc595651ff545de9"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4715a9b778f4293b9f8ae7a0a7cef9829f02ff8d6277a39d7f40565c737d3771"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:afc52b8d969eff14e069a710057d15ab9ac17cd4b6753042c407dcea0e40bf75"}, + {file = "aiohttp-3.9.5-cp311-cp311-win32.whl", hash = "sha256:b3df71da99c98534be076196791adca8819761f0bf6e08e07fd7da25127150d6"}, + {file = "aiohttp-3.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:88e311d98cc0bf45b62fc46c66753a83445f5ab20038bcc1b8a1cc05666f428a"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c7a4b7a6cf5b6eb11e109a9755fd4fda7d57395f8c575e166d363b9fc3ec4678"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0a158704edf0abcac8ac371fbb54044f3270bdbc93e254a82b6c82be1ef08f3c"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d153f652a687a8e95ad367a86a61e8d53d528b0530ef382ec5aaf533140ed00f"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82a6a97d9771cb48ae16979c3a3a9a18b600a8505b1115cfe354dfb2054468b4"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60cdbd56f4cad9f69c35eaac0fbbdf1f77b0ff9456cebd4902f3dd1cf096464c"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8676e8fd73141ded15ea586de0b7cda1542960a7b9ad89b2b06428e97125d4fa"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da00da442a0e31f1c69d26d224e1efd3a1ca5bcbf210978a2ca7426dfcae9f58"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18f634d540dd099c262e9f887c8bbacc959847cfe5da7a0e2e1cf3f14dbf2daf"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:320e8618eda64e19d11bdb3bd04ccc0a816c17eaecb7e4945d01deee2a22f95f"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:2faa61a904b83142747fc6a6d7ad8fccff898c849123030f8e75d5d967fd4a81"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:8c64a6dc3fe5db7b1b4d2b5cb84c4f677768bdc340611eca673afb7cf416ef5a"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:393c7aba2b55559ef7ab791c94b44f7482a07bf7640d17b341b79081f5e5cd1a"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c671dc117c2c21a1ca10c116cfcd6e3e44da7fcde37bf83b2be485ab377b25da"}, + {file = "aiohttp-3.9.5-cp312-cp312-win32.whl", hash = "sha256:5a7ee16aab26e76add4afc45e8f8206c95d1d75540f1039b84a03c3b3800dd59"}, + {file = "aiohttp-3.9.5-cp312-cp312-win_amd64.whl", hash = "sha256:5ca51eadbd67045396bc92a4345d1790b7301c14d1848feaac1d6a6c9289e888"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:694d828b5c41255e54bc2dddb51a9f5150b4eefa9886e38b52605a05d96566e8"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0605cc2c0088fcaae79f01c913a38611ad09ba68ff482402d3410bf59039bfb8"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4558e5012ee03d2638c681e156461d37b7a113fe13970d438d95d10173d25f78"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dbc053ac75ccc63dc3a3cc547b98c7258ec35a215a92bd9f983e0aac95d3d5b"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4109adee842b90671f1b689901b948f347325045c15f46b39797ae1bf17019de"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6ea1a5b409a85477fd8e5ee6ad8f0e40bf2844c270955e09360418cfd09abac"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3c2890ca8c59ee683fd09adf32321a40fe1cf164e3387799efb2acebf090c11"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3916c8692dbd9d55c523374a3b8213e628424d19116ac4308e434dbf6d95bbdd"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8d1964eb7617907c792ca00b341b5ec3e01ae8c280825deadbbd678447b127e1"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5ab8e1f6bee051a4bf6195e38a5c13e5e161cb7bad83d8854524798bd9fcd6e"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:52c27110f3862a1afbcb2af4281fc9fdc40327fa286c4625dfee247c3ba90156"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:7f64cbd44443e80094309875d4f9c71d0401e966d191c3d469cde4642bc2e031"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8b4f72fbb66279624bfe83fd5eb6aea0022dad8eec62b71e7bf63ee1caadeafe"}, + {file = "aiohttp-3.9.5-cp38-cp38-win32.whl", hash = "sha256:6380c039ec52866c06d69b5c7aad5478b24ed11696f0e72f6b807cfb261453da"}, + {file = "aiohttp-3.9.5-cp38-cp38-win_amd64.whl", hash = "sha256:da22dab31d7180f8c3ac7c7635f3bcd53808f374f6aa333fe0b0b9e14b01f91a"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1732102949ff6087589408d76cd6dea656b93c896b011ecafff418c9661dc4ed"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c6021d296318cb6f9414b48e6a439a7f5d1f665464da507e8ff640848ee2a58a"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:239f975589a944eeb1bad26b8b140a59a3a320067fb3cd10b75c3092405a1372"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b7b30258348082826d274504fbc7c849959f1989d86c29bc355107accec6cfb"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd2adf5c87ff6d8b277814a28a535b59e20bfea40a101db6b3bdca7e9926bc24"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9a3d838441bebcf5cf442700e3963f58b5c33f015341f9ea86dcd7d503c07e2"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e3a1ae66e3d0c17cf65c08968a5ee3180c5a95920ec2731f53343fac9bad106"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c69e77370cce2d6df5d12b4e12bdcca60c47ba13d1cbbc8645dd005a20b738b"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf56238f4bbf49dab8c2dc2e6b1b68502b1e88d335bea59b3f5b9f4c001475"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d1469f228cd9ffddd396d9948b8c9cd8022b6d1bf1e40c6f25b0fb90b4f893ed"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:45731330e754f5811c314901cebdf19dd776a44b31927fa4b4dbecab9e457b0c"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3fcb4046d2904378e3aeea1df51f697b0467f2aac55d232c87ba162709478c46"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8cf142aa6c1a751fcb364158fd710b8a9be874b81889c2bd13aa8893197455e2"}, + {file = "aiohttp-3.9.5-cp39-cp39-win32.whl", hash = "sha256:7b179eea70833c8dee51ec42f3b4097bd6370892fa93f510f76762105568cf09"}, + {file = "aiohttp-3.9.5-cp39-cp39-win_amd64.whl", hash = "sha256:38d80498e2e169bc61418ff36170e0aad0cd268da8b38a17c4cf29d254a8b3f1"}, + {file = "aiohttp-3.9.5.tar.gz", hash = "sha256:edea7d15772ceeb29db4aff55e482d4bcfb6ae160ce144f2682de02f6d693551"}, ] [package.dependencies] aiosignal = ">=1.1.2" -async-timeout = ">=4.0.0a3,<5.0" +async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""} attrs = ">=17.3.0" -charset-normalizer = ">=2.0,<4.0" frozenlist = ">=1.1.1" multidict = ">=4.5,<7.0" yarl = ">=1.0,<2.0" [package.extras] -speedups = ["Brotli", "aiodns", "cchardet"] +speedups = ["Brotli", "aiodns", "brotlicffi"] [[package]] name = "aiohttp-retry" @@ -124,17 +112,17 @@ aiohttp = "*" [[package]] name = "aioresponses" -version = "0.7.4" +version = "0.7.6" description = "Mock out requests made by ClientSession from aiohttp package" optional = false python-versions = "*" files = [ - {file = "aioresponses-0.7.4-py2.py3-none-any.whl", hash = "sha256:1160486b5ea96fcae6170cf2bdef029b9d3a283b7dbeabb3d7f1182769bfb6b7"}, - {file = "aioresponses-0.7.4.tar.gz", hash = "sha256:9b8c108b36354c04633bad0ea752b55d956a7602fe3e3234b939fc44af96f1d8"}, + {file = "aioresponses-0.7.6-py2.py3-none-any.whl", hash = "sha256:d2c26defbb9b440ea2685ec132e90700907fd10bcca3e85ec2f157219f0d26f7"}, + {file = "aioresponses-0.7.6.tar.gz", hash = "sha256:f795d9dbda2d61774840e7e32f5366f45752d1adc1b74c9362afd017296c7ee1"}, ] [package.dependencies] -aiohttp = ">=2.0.0,<4.0.0" +aiohttp = ">=3.3.0,<4.0.0" [[package]] name = "aiosignal" @@ -152,85 +140,78 @@ frozenlist = ">=1.1.0" [[package]] name = "annotated-types" -version = "0.6.0" +version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" files = [ - {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, - {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] -[package.dependencies] -typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} - [[package]] name = "anthropic" -version = "0.7.1" +version = "0.28.0" description = "The official Python library for the anthropic API" -optional = false +optional = true python-versions = ">=3.7" files = [ - {file = "anthropic-0.7.1-py3-none-any.whl", hash = "sha256:116d009f1a01fa46f3213e1f0b57b79a5ce3f3c0b2bf14441f96c8de6399a4b4"}, - {file = "anthropic-0.7.1.tar.gz", hash = "sha256:c5559be61dc74499e713669ee9efc0da6f190870f32c9606d7ad989dea5bde82"}, + {file = "anthropic-0.28.0-py3-none-any.whl", hash = "sha256:2b620b21aee3d20c5d8005483c34df239d53ae895687113b26b8a36892a7e20f"}, ] [package.dependencies] -anyio = ">=3.5.0,<4" +anyio = ">=3.5.0,<5" distro = ">=1.7.0,<2" httpx = ">=0.23.0,<1" +jiter = ">=0.4.0,<1" pydantic = ">=1.9.0,<3" +sniffio = "*" tokenizers = ">=0.13.0" -typing-extensions = ">=4.5,<5" +typing-extensions = ">=4.7,<5" + +[package.extras] +bedrock = ["boto3 (>=1.28.57)", "botocore (>=1.31.57)"] +vertex = ["google-auth (>=2,<3)"] [[package]] name = "anyio" -version = "3.7.1" +version = "4.4.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"}, - {file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"}, + {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, + {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, ] [package.dependencies] -exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" sniffio = ">=1.1" +typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} [package.extras] -doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"] -test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (<0.22)"] - -[[package]] -name = "appnope" -version = "0.1.3" -description = "Disable App Nap on macOS >= 10.9" -optional = true -python-versions = "*" -files = [ - {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"}, - {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, -] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.23)"] [[package]] name = "asttokens" -version = "2.2.1" +version = "2.4.1" description = "Annotate AST trees with source code positions" optional = true python-versions = "*" files = [ - {file = "asttokens-2.2.1-py2.py3-none-any.whl", hash = "sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c"}, - {file = "asttokens-2.2.1.tar.gz", hash = "sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3"}, + {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, + {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, ] [package.dependencies] -six = "*" +six = ">=1.12.0" [package.extras] -test = ["astroid", "pytest"] +astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] +test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] [[package]] name = "async-timeout" @@ -245,46 +226,36 @@ files = [ [[package]] name = "attrs" -version = "23.1.0" +version = "23.2.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.7" files = [ - {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, - {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, ] [package.extras] cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]", "pre-commit"] +dev = ["attrs[tests]", "pre-commit"] docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] [[package]] name = "azure-cognitiveservices-speech" -version = "1.31.0" +version = "1.37.0" description = "Microsoft Cognitive Services Speech SDK for Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "azure_cognitiveservices_speech-1.31.0-py3-none-macosx_10_14_x86_64.whl", hash = "sha256:43818484c5b0e0f2f22bb47fef5fea32cec779c08eefd7a501d5ae240ce0bd3f"}, - {file = "azure_cognitiveservices_speech-1.31.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:4684046eb04f17484db768b1de058b0b5a65f7e40c016c0e187247c8c8c9b029"}, - {file = "azure_cognitiveservices_speech-1.31.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:8d82aa933677b528fbe0605b9a0ab1f7aa5f09d4aadd48fb21473ba2dfeec614"}, - {file = "azure_cognitiveservices_speech-1.31.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:0d4a6952d24a32eecec70dd063ba401a1aa6ee72d70c2cc2343bd60741494b67"}, - {file = "azure_cognitiveservices_speech-1.31.0-py3-none-win32.whl", hash = "sha256:3dfe69185f910208099c9e635e52de7e846928c6d0dda526b26ef3c1ed8ee62e"}, - {file = "azure_cognitiveservices_speech-1.31.0-py3-none-win_amd64.whl", hash = "sha256:39940875d651999e0b60caef20adc9798951a675eece4f5e4fb03bcb77ddef03"}, -] - -[[package]] -name = "backcall" -version = "0.2.0" -description = "Specifications for callback functions passed in to an API" optional = true -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, - {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-macosx_10_14_x86_64.whl", hash = "sha256:906d6bf65176e93464e2d763dd074ca00c48cfe1a896371fcdcb155a500910f7"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:54ec8dd55d4dbd9058c61909e08485d3761d6d30954da189e1b17d84daf5e2e0"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:685424689725d2d4115485998c0888c8b5b502259037ff533e5a834575f80b66"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:384f66786c2335165035270897b34d0b91736a1fdf38f7696e9a227075cb2489"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-win32.whl", hash = "sha256:343d5f449ccd6c9b53cd37dd46a70ece0905243517df7a0c047779e55072254c"}, + {file = "azure_cognitiveservices_speech-1.37.0-py3-none-win_amd64.whl", hash = "sha256:a18fb45490cdcd681407ccaad9560fb14dda1c8276de297e219ea1a880467e28"}, ] [[package]] @@ -333,235 +304,189 @@ d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] -[[package]] -name = "boto3" -version = "1.28.30" -description = "The AWS SDK for Python" -optional = false -python-versions = ">= 3.7" -files = [ - {file = "boto3-1.28.30-py3-none-any.whl", hash = "sha256:e095ede98d3680e65966ab71f273b7d86938f5d853773ef96f4cb646277c2a4b"}, - {file = "boto3-1.28.30.tar.gz", hash = "sha256:2b509a959966a572f15db5768a18066ce1f53022ac53fca9421c620219fa3998"}, -] - -[package.dependencies] -botocore = ">=1.31.30,<1.32.0" -jmespath = ">=0.7.1,<2.0.0" -s3transfer = ">=0.6.0,<0.7.0" - -[package.extras] -crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] - -[[package]] -name = "botocore" -version = "1.31.30" -description = "Low-level, data-driven core of boto 3." -optional = false -python-versions = ">= 3.7" -files = [ - {file = "botocore-1.31.30-py3-none-any.whl", hash = "sha256:269f20dcadd8dfd0c26d0e6fbceb84814ff6638ff3aafcc5324b9fb9949a7051"}, - {file = "botocore-1.31.30.tar.gz", hash = "sha256:3cf6a9d7621b897c9ff23cd02113826141b3dd3d7e90273b661efc4dc05f84e2"}, -] - -[package.dependencies] -jmespath = ">=0.7.1,<2.0.0" -python-dateutil = ">=2.1,<3.0.0" -urllib3 = ">=1.25.4,<1.27" - -[package.extras] -crt = ["awscrt (==0.16.26)"] - [[package]] name = "cachetools" -version = "5.3.1" +version = "5.3.3" description = "Extensible memoizing collections and decorators" optional = true python-versions = ">=3.7" files = [ - {file = "cachetools-5.3.1-py3-none-any.whl", hash = "sha256:95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590"}, - {file = "cachetools-5.3.1.tar.gz", hash = "sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b"}, + {file = "cachetools-5.3.3-py3-none-any.whl", hash = "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945"}, + {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, ] [[package]] name = "certifi" -version = "2023.7.22" +version = "2024.2.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, - {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, ] [[package]] name = "cffi" -version = "1.15.1" +version = "1.16.0" description = "Foreign Function Interface for Python calling C code." optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, - {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, - {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, - {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, - {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, - {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, - {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, - {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, - {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, - {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, - {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, - {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, - {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, - {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, - {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, - {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, - {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, - {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, - {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, + {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, + {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, + {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, + {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, + {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, + {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, ] [package.dependencies] pycparser = "*" -[[package]] -name = "cfgv" -version = "3.4.0" -description = "Validate configuration and produce human readable error messages." -optional = false -python-versions = ">=3.8" -files = [ - {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, - {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, -] - [[package]] name = "charset-normalizer" -version = "3.2.0" +version = "3.3.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"}, - {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"}, + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] [[package]] @@ -589,60 +514,136 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "coverage" +version = "7.5.3" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "coverage-7.5.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a6519d917abb15e12380406d721e37613e2a67d166f9fb7e5a8ce0375744cd45"}, + {file = "coverage-7.5.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:aea7da970f1feccf48be7335f8b2ca64baf9b589d79e05b9397a06696ce1a1ec"}, + {file = "coverage-7.5.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:923b7b1c717bd0f0f92d862d1ff51d9b2b55dbbd133e05680204465f454bb286"}, + {file = "coverage-7.5.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62bda40da1e68898186f274f832ef3e759ce929da9a9fd9fcf265956de269dbc"}, + {file = "coverage-7.5.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8b7339180d00de83e930358223c617cc343dd08e1aa5ec7b06c3a121aec4e1d"}, + {file = "coverage-7.5.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:25a5caf742c6195e08002d3b6c2dd6947e50efc5fc2c2205f61ecb47592d2d83"}, + {file = "coverage-7.5.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:05ac5f60faa0c704c0f7e6a5cbfd6f02101ed05e0aee4d2822637a9e672c998d"}, + {file = "coverage-7.5.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:239a4e75e09c2b12ea478d28815acf83334d32e722e7433471fbf641c606344c"}, + {file = "coverage-7.5.3-cp310-cp310-win32.whl", hash = "sha256:a5812840d1d00eafae6585aba38021f90a705a25b8216ec7f66aebe5b619fb84"}, + {file = "coverage-7.5.3-cp310-cp310-win_amd64.whl", hash = "sha256:33ca90a0eb29225f195e30684ba4a6db05dbef03c2ccd50b9077714c48153cac"}, + {file = "coverage-7.5.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f81bc26d609bf0fbc622c7122ba6307993c83c795d2d6f6f6fd8c000a770d974"}, + {file = "coverage-7.5.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7cec2af81f9e7569280822be68bd57e51b86d42e59ea30d10ebdbb22d2cb7232"}, + {file = "coverage-7.5.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55f689f846661e3f26efa535071775d0483388a1ccfab899df72924805e9e7cd"}, + {file = "coverage-7.5.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50084d3516aa263791198913a17354bd1dc627d3c1639209640b9cac3fef5807"}, + {file = "coverage-7.5.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:341dd8f61c26337c37988345ca5c8ccabeff33093a26953a1ac72e7d0103c4fb"}, + {file = "coverage-7.5.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ab0b028165eea880af12f66086694768f2c3139b2c31ad5e032c8edbafca6ffc"}, + {file = "coverage-7.5.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5bc5a8c87714b0c67cfeb4c7caa82b2d71e8864d1a46aa990b5588fa953673b8"}, + {file = "coverage-7.5.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:38a3b98dae8a7c9057bd91fbf3415c05e700a5114c5f1b5b0ea5f8f429ba6614"}, + {file = "coverage-7.5.3-cp311-cp311-win32.whl", hash = "sha256:fcf7d1d6f5da887ca04302db8e0e0cf56ce9a5e05f202720e49b3e8157ddb9a9"}, + {file = "coverage-7.5.3-cp311-cp311-win_amd64.whl", hash = "sha256:8c836309931839cca658a78a888dab9676b5c988d0dd34ca247f5f3e679f4e7a"}, + {file = "coverage-7.5.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:296a7d9bbc598e8744c00f7a6cecf1da9b30ae9ad51c566291ff1314e6cbbed8"}, + {file = "coverage-7.5.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:34d6d21d8795a97b14d503dcaf74226ae51eb1f2bd41015d3ef332a24d0a17b3"}, + {file = "coverage-7.5.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e317953bb4c074c06c798a11dbdd2cf9979dbcaa8ccc0fa4701d80042d4ebf1"}, + {file = "coverage-7.5.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:705f3d7c2b098c40f5b81790a5fedb274113373d4d1a69e65f8b68b0cc26f6db"}, + {file = "coverage-7.5.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1196e13c45e327d6cd0b6e471530a1882f1017eb83c6229fc613cd1a11b53cd"}, + {file = "coverage-7.5.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:015eddc5ccd5364dcb902eaecf9515636806fa1e0d5bef5769d06d0f31b54523"}, + {file = "coverage-7.5.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:fd27d8b49e574e50caa65196d908f80e4dff64d7e592d0c59788b45aad7e8b35"}, + {file = "coverage-7.5.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:33fc65740267222fc02975c061eb7167185fef4cc8f2770267ee8bf7d6a42f84"}, + {file = "coverage-7.5.3-cp312-cp312-win32.whl", hash = "sha256:7b2a19e13dfb5c8e145c7a6ea959485ee8e2204699903c88c7d25283584bfc08"}, + {file = "coverage-7.5.3-cp312-cp312-win_amd64.whl", hash = "sha256:0bbddc54bbacfc09b3edaec644d4ac90c08ee8ed4844b0f86227dcda2d428fcb"}, + {file = "coverage-7.5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f78300789a708ac1f17e134593f577407d52d0417305435b134805c4fb135adb"}, + {file = "coverage-7.5.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b368e1aee1b9b75757942d44d7598dcd22a9dbb126affcbba82d15917f0cc155"}, + {file = "coverage-7.5.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f836c174c3a7f639bded48ec913f348c4761cbf49de4a20a956d3431a7c9cb24"}, + {file = "coverage-7.5.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:244f509f126dc71369393ce5fea17c0592c40ee44e607b6d855e9c4ac57aac98"}, + {file = "coverage-7.5.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4c2872b3c91f9baa836147ca33650dc5c172e9273c808c3c3199c75490e709d"}, + {file = "coverage-7.5.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dd4b3355b01273a56b20c219e74e7549e14370b31a4ffe42706a8cda91f19f6d"}, + {file = "coverage-7.5.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f542287b1489c7a860d43a7d8883e27ca62ab84ca53c965d11dac1d3a1fab7ce"}, + {file = "coverage-7.5.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:75e3f4e86804023e991096b29e147e635f5e2568f77883a1e6eed74512659ab0"}, + {file = "coverage-7.5.3-cp38-cp38-win32.whl", hash = "sha256:c59d2ad092dc0551d9f79d9d44d005c945ba95832a6798f98f9216ede3d5f485"}, + {file = "coverage-7.5.3-cp38-cp38-win_amd64.whl", hash = "sha256:fa21a04112c59ad54f69d80e376f7f9d0f5f9123ab87ecd18fbb9ec3a2beed56"}, + {file = "coverage-7.5.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f5102a92855d518b0996eb197772f5ac2a527c0ec617124ad5242a3af5e25f85"}, + {file = "coverage-7.5.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d1da0a2e3b37b745a2b2a678a4c796462cf753aebf94edcc87dcc6b8641eae31"}, + {file = "coverage-7.5.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8383a6c8cefba1b7cecc0149415046b6fc38836295bc4c84e820872eb5478b3d"}, + {file = "coverage-7.5.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9aad68c3f2566dfae84bf46295a79e79d904e1c21ccfc66de88cd446f8686341"}, + {file = "coverage-7.5.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e079c9ec772fedbade9d7ebc36202a1d9ef7291bc9b3a024ca395c4d52853d7"}, + {file = "coverage-7.5.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bde997cac85fcac227b27d4fb2c7608a2c5f6558469b0eb704c5726ae49e1c52"}, + {file = "coverage-7.5.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:990fb20b32990b2ce2c5f974c3e738c9358b2735bc05075d50a6f36721b8f303"}, + {file = "coverage-7.5.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3d5a67f0da401e105753d474369ab034c7bae51a4c31c77d94030d59e41df5bd"}, + {file = "coverage-7.5.3-cp39-cp39-win32.whl", hash = "sha256:e08c470c2eb01977d221fd87495b44867a56d4d594f43739a8028f8646a51e0d"}, + {file = "coverage-7.5.3-cp39-cp39-win_amd64.whl", hash = "sha256:1d2a830ade66d3563bb61d1e3c77c8def97b30ed91e166c67d0632c018f380f0"}, + {file = "coverage-7.5.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:3538d8fb1ee9bdd2e2692b3b18c22bb1c19ffbefd06880f5ac496e42d7bb3884"}, + {file = "coverage-7.5.3.tar.gz", hash = "sha256:04aefca5190d1dc7a53a4c1a5a7f8568811306d7a8ee231c42fb69215571944f"}, +] + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli"] + [[package]] name = "cryptography" -version = "41.0.3" +version = "42.0.7" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-41.0.3-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:652627a055cb52a84f8c448185922241dd5217443ca194d5739b44612c5e6507"}, - {file = "cryptography-41.0.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:8f09daa483aedea50d249ef98ed500569841d6498aa9c9f4b0531b9964658922"}, - {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4fd871184321100fb400d759ad0cddddf284c4b696568204d281c902fc7b0d81"}, - {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84537453d57f55a50a5b6835622ee405816999a7113267739a1b4581f83535bd"}, - {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3fb248989b6363906827284cd20cca63bb1a757e0a2864d4c1682a985e3dca47"}, - {file = "cryptography-41.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:42cb413e01a5d36da9929baa9d70ca90d90b969269e5a12d39c1e0d475010116"}, - {file = "cryptography-41.0.3-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:aeb57c421b34af8f9fe830e1955bf493a86a7996cc1338fe41b30047d16e962c"}, - {file = "cryptography-41.0.3-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6af1c6387c531cd364b72c28daa29232162010d952ceb7e5ca8e2827526aceae"}, - {file = "cryptography-41.0.3-cp37-abi3-win32.whl", hash = "sha256:0d09fb5356f975974dbcb595ad2d178305e5050656affb7890a1583f5e02a306"}, - {file = "cryptography-41.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:a983e441a00a9d57a4d7c91b3116a37ae602907a7618b882c8013b5762e80574"}, - {file = "cryptography-41.0.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5259cb659aa43005eb55a0e4ff2c825ca111a0da1814202c64d28a985d33b087"}, - {file = "cryptography-41.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:67e120e9a577c64fe1f611e53b30b3e69744e5910ff3b6e97e935aeb96005858"}, - {file = "cryptography-41.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7efe8041897fe7a50863e51b77789b657a133c75c3b094e51b5e4b5cec7bf906"}, - {file = "cryptography-41.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ce785cf81a7bdade534297ef9e490ddff800d956625020ab2ec2780a556c313e"}, - {file = "cryptography-41.0.3-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:57a51b89f954f216a81c9d057bf1a24e2f36e764a1ca9a501a6964eb4a6800dd"}, - {file = "cryptography-41.0.3-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c2f0d35703d61002a2bbdcf15548ebb701cfdd83cdc12471d2bae80878a4207"}, - {file = "cryptography-41.0.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:23c2d778cf829f7d0ae180600b17e9fceea3c2ef8b31a99e3c694cbbf3a24b84"}, - {file = "cryptography-41.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:95dd7f261bb76948b52a5330ba5202b91a26fbac13ad0e9fc8a3ac04752058c7"}, - {file = "cryptography-41.0.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:41d7aa7cdfded09b3d73a47f429c298e80796c8e825ddfadc84c8a7f12df212d"}, - {file = "cryptography-41.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d0d651aa754ef58d75cec6edfbd21259d93810b73f6ec246436a21b7841908de"}, - {file = "cryptography-41.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ab8de0d091acbf778f74286f4989cf3d1528336af1b59f3e5d2ebca8b5fe49e1"}, - {file = "cryptography-41.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a74fbcdb2a0d46fe00504f571a2a540532f4c188e6ccf26f1f178480117b33c4"}, - {file = "cryptography-41.0.3.tar.gz", hash = "sha256:6d192741113ef5e30d89dcb5b956ef4e1578f304708701b8b73d38e3e1461f34"}, -] - -[package.dependencies] -cffi = ">=1.12" + {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"}, + {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"}, + {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"}, + {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"}, + {file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"}, + {file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"}, + {file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"}, + {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"}, + {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"}, + {file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"}, + {file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"}, + {file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"}, + {file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"}, + {file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"}, +] + +[package.dependencies] +cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} [package.extras] docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] -docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] +docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"] nox = ["nox"] -pep8test = ["black", "check-sdist", "mypy", "ruff"] +pep8test = ["check-sdist", "click", "mypy", "ruff"] sdist = ["build"] ssh = ["bcrypt (>=3.1.5)"] -test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] [[package]] name = "dataclasses-json" -version = "0.5.14" +version = "0.6.6" description = "Easily serialize dataclasses to and from JSON." -optional = false -python-versions = ">=3.7,<3.13" +optional = true +python-versions = "<4.0,>=3.7" files = [ - {file = "dataclasses_json-0.5.14-py3-none-any.whl", hash = "sha256:5ec6fed642adb1dbdb4182badb01e0861badfd8fda82e3b67f44b2d1e9d10d21"}, - {file = "dataclasses_json-0.5.14.tar.gz", hash = "sha256:d82896a94c992ffaf689cd1fafc180164e2abdd415b8f94a7f78586af5886236"}, + {file = "dataclasses_json-0.6.6-py3-none-any.whl", hash = "sha256:e54c5c87497741ad454070ba0ed411523d46beb5da102e221efb873801b0ba85"}, + {file = "dataclasses_json-0.6.6.tar.gz", hash = "sha256:0c09827d26fffda27f1be2fed7a7a01a29c5ddcd2eb6393ad5ebf9d77e9deae8"}, ] [package.dependencies] @@ -678,53 +679,79 @@ wrapt = ">=1.10,<2" dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] [[package]] -name = "distlib" -version = "0.3.7" -description = "Distribution utilities" -optional = false -python-versions = "*" +name = "distro" +version = "1.9.0" +description = "Distro - an OS platform information API" +optional = true +python-versions = ">=3.6" files = [ - {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"}, - {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"}, + {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, + {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, ] [[package]] -name = "distro" -version = "1.8.0" -description = "Distro - an OS platform information API" +name = "dnspython" +version = "2.6.1" +description = "DNS toolkit" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "distro-1.8.0-py3-none-any.whl", hash = "sha256:99522ca3e365cac527b44bde033f64c6945d90eb9f769703caaec52b09bbd3ff"}, - {file = "distro-1.8.0.tar.gz", hash = "sha256:02e111d1dc6a50abb8eed6bf31c3e48ed8b0830d1ea2a1b78c61765c2513fdd8"}, + {file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"}, + {file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"}, ] +[package.extras] +dev = ["black (>=23.1.0)", "coverage (>=7.0)", "flake8 (>=7)", "mypy (>=1.8)", "pylint (>=3)", "pytest (>=7.4)", "pytest-cov (>=4.1.0)", "sphinx (>=7.2.0)", "twine (>=4.0.0)", "wheel (>=0.42.0)"] +dnssec = ["cryptography (>=41)"] +doh = ["h2 (>=4.1.0)", "httpcore (>=1.0.0)", "httpx (>=0.26.0)"] +doq = ["aioquic (>=0.9.25)"] +idna = ["idna (>=3.6)"] +trio = ["trio (>=0.23)"] +wmi = ["wmi (>=1.5.1)"] + [[package]] name = "elevenlabs" -version = "0.2.27" -description = "The official elevenlabs python package." +version = "1.2.2" +description = "" optional = true -python-versions = "*" +python-versions = "<4.0,>=3.8" files = [ - {file = "elevenlabs-0.2.27-py3-none-any.whl", hash = "sha256:c31ea892d5668002bc26d0bb46a6466b0b4e2fe5aaed75cbc1b7011f01d3fa29"}, - {file = "elevenlabs-0.2.27.tar.gz", hash = "sha256:1b17d3c997557e5aa654b296e3960c25ea183525cfdbd0ec53070b038ba5fd95"}, + {file = "elevenlabs-1.2.2-py3-none-any.whl", hash = "sha256:60b92b0e2aabdfba93a43569f207f8a2ad397492519b8e11a2eebb32807ddefa"}, + {file = "elevenlabs-1.2.2.tar.gz", hash = "sha256:ebd02869b95602b8956874dd727981bb49ad16b9a3c2f5901193d838213694aa"}, ] [package.dependencies] +httpx = ">=0.21.2" ipython = ">=7.0" -pydantic = ">=2.0" +pydantic = ">=1.9.2" requests = ">=2.20" +typing_extensions = ">=4.0.0" websockets = ">=11.0" +[[package]] +name = "email-validator" +version = "2.1.1" +description = "A robust email address syntax and deliverability validation library." +optional = false +python-versions = ">=3.8" +files = [ + {file = "email_validator-2.1.1-py3-none-any.whl", hash = "sha256:97d882d174e2a65732fb43bfce81a3a834cbc1bde8bf419e30ef5ea976370a05"}, + {file = "email_validator-2.1.1.tar.gz", hash = "sha256:200a70680ba08904be6d1eef729205cc0d687634399a5924d842533efb824b84"}, +] + +[package.dependencies] +dnspython = ">=2.0.0" +idna = ">=2.0.0" + [[package]] name = "exceptiongroup" -version = "1.1.3" +version = "1.2.1" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, - {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, + {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, + {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, ] [package.extras] @@ -732,131 +759,234 @@ test = ["pytest (>=6)"] [[package]] name = "executing" -version = "1.2.0" +version = "2.0.1" description = "Get the currently executing AST node of a frame, and other information" optional = true -python-versions = "*" +python-versions = ">=3.5" +files = [ + {file = "executing-2.0.1-py2.py3-none-any.whl", hash = "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc"}, + {file = "executing-2.0.1.tar.gz", hash = "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147"}, +] + +[package.extras] +tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] + +[[package]] +name = "fakeredis" +version = "2.23.2" +description = "Python implementation of redis API, can be used for testing purposes." +optional = false +python-versions = "<4.0,>=3.7" files = [ - {file = "executing-1.2.0-py2.py3-none-any.whl", hash = "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc"}, - {file = "executing-1.2.0.tar.gz", hash = "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107"}, + {file = "fakeredis-2.23.2-py3-none-any.whl", hash = "sha256:3721946b955930c065231befd24a9cdc68b339746e93848ef01a010d98e4eb4f"}, + {file = "fakeredis-2.23.2.tar.gz", hash = "sha256:d649c409abe46c63690b6c35d3c460e4ce64c69a52cea3f02daff2649378f878"}, ] +[package.dependencies] +redis = ">=4" +sortedcontainers = ">=2,<3" +typing_extensions = {version = ">=4.7,<5.0", markers = "python_version < \"3.11\""} + [package.extras] -tests = ["asttokens", "littleutils", "pytest", "rich"] +bf = ["pyprobables (>=0.6,<0.7)"] +cf = ["pyprobables (>=0.6,<0.7)"] +json = ["jsonpath-ng (>=1.6,<2.0)"] +lua = ["lupa (>=2.1,<3.0)"] +probabilistic = ["pyprobables (>=0.6,<0.7)"] [[package]] name = "fastapi" -version = "0.100.1" +version = "0.111.0" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "fastapi-0.111.0-py3-none-any.whl", hash = "sha256:97ecbf994be0bcbdadedf88c3150252bed7b2087075ac99735403b1b76cc8fc0"}, + {file = "fastapi-0.111.0.tar.gz", hash = "sha256:b9db9dd147c91cb8b769f7183535773d8741dd46f9dc6676cd82eab510228cd7"}, +] + +[package.dependencies] +email_validator = ">=2.0.0" +fastapi-cli = ">=0.0.2" +httpx = ">=0.23.0" +jinja2 = ">=2.11.2" +orjson = ">=3.2.1" +pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" +python-multipart = ">=0.0.7" +starlette = ">=0.37.2,<0.38.0" +typing-extensions = ">=4.8.0" +ujson = ">=4.0.1,<4.0.2 || >4.0.2,<4.1.0 || >4.1.0,<4.2.0 || >4.2.0,<4.3.0 || >4.3.0,<5.0.0 || >5.0.0,<5.1.0 || >5.1.0" +uvicorn = {version = ">=0.12.0", extras = ["standard"]} + +[package.extras] +all = ["email_validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] + +[[package]] +name = "fastapi-cli" +version = "0.0.4" +description = "Run and manage FastAPI apps from the command line with FastAPI CLI. 🚀" +optional = false +python-versions = ">=3.8" files = [ - {file = "fastapi-0.100.1-py3-none-any.whl", hash = "sha256:ec6dd52bfc4eff3063cfcd0713b43c87640fefb2687bbbe3d8a08d94049cdf32"}, - {file = "fastapi-0.100.1.tar.gz", hash = "sha256:522700d7a469e4a973d92321ab93312448fbe20fca9c8da97effc7e7bc56df23"}, + {file = "fastapi_cli-0.0.4-py3-none-any.whl", hash = "sha256:a2552f3a7ae64058cdbb530be6fa6dbfc975dc165e4fa66d224c3d396e25e809"}, + {file = "fastapi_cli-0.0.4.tar.gz", hash = "sha256:e2e9ffaffc1f7767f488d6da34b6f5a377751c996f397902eb6abb99a67bde32"}, ] [package.dependencies] -pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<3.0.0" -starlette = ">=0.27.0,<0.28.0" -typing-extensions = ">=4.5.0" +typer = ">=0.12.3" [package.extras] -all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +standard = ["fastapi", "uvicorn[standard] (>=0.15.0)"] [[package]] name = "filelock" -version = "3.12.2" +version = "3.14.0" description = "A platform independent file lock." -optional = false -python-versions = ">=3.7" +optional = true +python-versions = ">=3.8" files = [ - {file = "filelock-3.12.2-py3-none-any.whl", hash = "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec"}, - {file = "filelock-3.12.2.tar.gz", hash = "sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81"}, + {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"}, + {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"}, ] [package.extras] -docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +typing = ["typing-extensions (>=4.8)"] [[package]] name = "frozenlist" -version = "1.4.0" +version = "1.4.1" description = "A list-like structure which implements collections.abc.MutableSequence" optional = false python-versions = ">=3.8" files = [ - {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab"}, - {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559"}, - {file = "frozenlist-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62"}, - {file = "frozenlist-1.4.0-cp310-cp310-win32.whl", hash = "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0"}, - {file = "frozenlist-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb"}, - {file = "frozenlist-1.4.0-cp311-cp311-win32.whl", hash = "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431"}, - {file = "frozenlist-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8"}, - {file = "frozenlist-1.4.0-cp38-cp38-win32.whl", hash = "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc"}, - {file = "frozenlist-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3"}, - {file = "frozenlist-1.4.0-cp39-cp39-win32.whl", hash = "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f"}, - {file = "frozenlist-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167"}, - {file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, + {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, + {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, + {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, + {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, + {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, + {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, + {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, + {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, + {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, + {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, + {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, + {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, +] + +[[package]] +name = "fsspec" +version = "2024.5.0" +description = "File-system specification" +optional = true +python-versions = ">=3.8" +files = [ + {file = "fsspec-2024.5.0-py3-none-any.whl", hash = "sha256:e0fdbc446d67e182f49a70b82cf7889028a63588fde6b222521f10937b2b670c"}, + {file = "fsspec-2024.5.0.tar.gz", hash = "sha256:1d021b0b0f933e3b3029ed808eb400c08ba101ca2de4b3483fbc9ca23fcee94a"}, ] +[package.extras] +abfs = ["adlfs"] +adl = ["adlfs"] +arrow = ["pyarrow (>=1)"] +dask = ["dask", "distributed"] +dev = ["pre-commit", "ruff"] +dropbox = ["dropbox", "dropboxdrivefs", "requests"] +full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] +fuse = ["fusepy"] +gcs = ["gcsfs"] +git = ["pygit2"] +github = ["requests"] +gs = ["gcsfs"] +gui = ["panel"] +hdfs = ["pyarrow (>=1)"] +http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)"] +libarchive = ["libarchive-c"] +oci = ["ocifs"] +s3 = ["s3fs"] +sftp = ["paramiko"] +smb = ["smbprotocol"] +ssh = ["paramiko"] +test = ["aiohttp (!=4.0.0a0,!=4.0.0a1)", "numpy", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "requests"] +test-downstream = ["aiobotocore (>=2.5.4,<3.0.0)", "dask-expr", "dask[dataframe,test]", "moto[server] (>4,<5)", "pytest-timeout", "xarray"] +test-full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "cloudpickle", "dask", "distributed", "dropbox", "dropboxdrivefs", "fastparquet", "fusepy", "gcsfs", "jinja2", "kerchunk", "libarchive-c", "lz4", "notebook", "numpy", "ocifs", "pandas", "panel", "paramiko", "pyarrow", "pyarrow (>=1)", "pyftpdlib", "pygit2", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "python-snappy", "requests", "smbprotocol", "tqdm", "urllib3", "zarr", "zstandard"] +tqdm = ["tqdm"] + [[package]] name = "google-api-core" -version = "2.11.1" +version = "2.19.0" description = "Google API client core library" optional = true python-versions = ">=3.7" files = [ - {file = "google-api-core-2.11.1.tar.gz", hash = "sha256:25d29e05a0058ed5f19c61c0a78b1b53adea4d9364b464d014fbda941f6d1c9a"}, - {file = "google_api_core-2.11.1-py3-none-any.whl", hash = "sha256:d92a5a92dc36dd4f4b9ee4e55528a90e432b059f93aee6ad857f9de8cc7ae94a"}, + {file = "google-api-core-2.19.0.tar.gz", hash = "sha256:cf1b7c2694047886d2af1128a03ae99e391108a08804f87cfd35970e49c9cd10"}, + {file = "google_api_core-2.19.0-py3-none-any.whl", hash = "sha256:8661eec4078c35428fd3f69a2c7ee29e342896b70f01d1a1cbcb334372dd6251"}, ] [package.dependencies] @@ -870,6 +1000,7 @@ grpcio-status = [ {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, {version = ">=1.33.2,<2.0.dev0", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, ] +proto-plus = ">=1.22.3,<2.0.0dev" protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" requests = ">=2.18.0,<3.0.0.dev0" @@ -880,21 +1011,19 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] [[package]] name = "google-auth" -version = "2.22.0" +version = "2.29.0" description = "Google Authentication Library" optional = true -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "google-auth-2.22.0.tar.gz", hash = "sha256:164cba9af4e6e4e40c3a4f90a1a6c12ee56f14c0b4868d1ca91b32826ab334ce"}, - {file = "google_auth-2.22.0-py2.py3-none-any.whl", hash = "sha256:d61d1b40897407b574da67da1a833bdc10d5a11642566e506565d1b1a46ba873"}, + {file = "google-auth-2.29.0.tar.gz", hash = "sha256:672dff332d073227550ffc7457868ac4218d6c500b155fe6cc17d2b13602c360"}, + {file = "google_auth-2.29.0-py2.py3-none-any.whl", hash = "sha256:d452ad095688cd52bae0ad6fafe027f6a6d6f560e810fec20914e17a09526415"}, ] [package.dependencies] cachetools = ">=2.0.0,<6.0" pyasn1-modules = ">=0.2.1" rsa = ">=3.1.4,<5" -six = ">=1.9.0" -urllib3 = "<2.0" [package.extras] aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"] @@ -903,284 +1032,52 @@ pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] reauth = ["pyu2f (>=0.1.5)"] requests = ["requests (>=2.20.0,<3.0.0.dev0)"] -[[package]] -name = "google-cloud-aiplatform" -version = "1.30.1" -description = "Vertex AI API client library" -optional = true -python-versions = ">=3.7" -files = [ - {file = "google-cloud-aiplatform-1.30.1.tar.gz", hash = "sha256:7552a6b2e66d7a9ff3c4b2bb95b0e9c182e7475dfb35d6347e9299f78779135a"}, - {file = "google_cloud_aiplatform-1.30.1-py2.py3-none-any.whl", hash = "sha256:ab1bbd4cf83cf583b7dea7e53421ad076f18b63e93cb22fb53c03176d5aa9258"}, -] - -[package.dependencies] -google-api-core = {version = ">=1.32.0,<2.0.dev0 || >=2.8.dev0,<3.0.0dev", extras = ["grpc"]} -google-cloud-bigquery = ">=1.15.0,<4.0.0dev" -google-cloud-resource-manager = ">=1.3.3,<3.0.0dev" -google-cloud-storage = ">=1.32.0,<3.0.0dev" -packaging = ">=14.3" -proto-plus = ">=1.22.0,<2.0.0dev" -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" -shapely = "<2.0.0" - -[package.extras] -autologging = ["mlflow (>=1.27.0,<=2.1.1)"] -cloud-profiler = ["tensorboard-plugin-profile (>=2.4.0,<3.0.0dev)", "tensorflow (>=2.4.0,<3.0.0dev)", "werkzeug (>=2.0.0,<2.1.0dev)"] -datasets = ["pyarrow (>=3.0.0,<8.0dev)"] -endpoint = ["requests (>=2.28.1)"] -full = ["docker (>=5.0.3)", "explainable-ai-sdk (>=1.0.0)", "fastapi (>=0.71.0,<0.76.0)", "google-cloud-bigquery-storage", "google-vizier (==0.0.4)", "lit-nlp (==0.4.0)", "mlflow (>=1.27.0,<=2.1.1)", "numpy (>=1.15.0)", "pandas (>=1.0.0)", "pyarrow (>=3.0.0,<8.0dev)", "pyarrow (>=6.0.1)", "pyyaml (>=5.3,<7)", "requests (>=2.28.1)", "starlette (>=0.17.1)", "tensorflow (>=2.3.0,<3.0.0dev)", "urllib3 (>=1.21.1,<1.27)", "uvicorn[standard] (>=0.16.0)"] -lit = ["explainable-ai-sdk (>=1.0.0)", "lit-nlp (==0.4.0)", "pandas (>=1.0.0)", "tensorflow (>=2.3.0,<3.0.0dev)"] -metadata = ["numpy (>=1.15.0)", "pandas (>=1.0.0)"] -pipelines = ["pyyaml (>=5.3,<7)"] -prediction = ["docker (>=5.0.3)", "fastapi (>=0.71.0,<0.76.0)", "starlette (>=0.17.1)", "uvicorn[standard] (>=0.16.0)"] -private-endpoints = ["requests (>=2.28.1)", "urllib3 (>=1.21.1,<1.27)"] -tensorboard = ["tensorflow (>=2.3.0,<3.0.0dev)"] -testing = ["docker (>=5.0.3)", "explainable-ai-sdk (>=1.0.0)", "fastapi (>=0.71.0,<0.76.0)", "google-cloud-bigquery-storage", "google-vizier (==0.0.4)", "grpcio-testing", "ipython", "kfp", "lit-nlp (==0.4.0)", "mlflow (>=1.27.0,<=2.1.1)", "numpy (>=1.15.0)", "pandas (>=1.0.0)", "pyarrow (>=3.0.0,<8.0dev)", "pyarrow (>=6.0.1)", "pytest-asyncio", "pytest-xdist", "pyyaml (>=5.3,<7)", "requests (>=2.28.1)", "scikit-learn", "starlette (>=0.17.1)", "tensorboard-plugin-profile (>=2.4.0,<3.0.0dev)", "tensorflow (>=2.3.0,<3.0.0dev)", "tensorflow (>=2.4.0,<3.0.0dev)", "urllib3 (>=1.21.1,<1.27)", "uvicorn[standard] (>=0.16.0)", "werkzeug (>=2.0.0,<2.1.0dev)", "xgboost"] -vizier = ["google-vizier (==0.0.4)"] -xai = ["tensorflow (>=2.3.0,<3.0.0dev)"] - -[[package]] -name = "google-cloud-bigquery" -version = "3.11.4" -description = "Google BigQuery API client library" -optional = true -python-versions = ">=3.7" -files = [ - {file = "google-cloud-bigquery-3.11.4.tar.gz", hash = "sha256:697df117241a2283bcbb93b21e10badc14e51c9a90800d2a7e1a3e1c7d842974"}, - {file = "google_cloud_bigquery-3.11.4-py2.py3-none-any.whl", hash = "sha256:5fa7897743a0ed949ade25a0942fc9e7557d8fce307c6f8a76d1b604cf27f1b1"}, -] - -[package.dependencies] -google-api-core = {version = ">=1.31.5,<2.0.dev0 || >2.3.0,<3.0.0dev", extras = ["grpc"]} -google-cloud-core = ">=1.6.0,<3.0.0dev" -google-resumable-media = ">=0.6.0,<3.0dev" -grpcio = [ - {version = ">=1.49.1,<2.0dev", markers = "python_version >= \"3.11\""}, - {version = ">=1.47.0,<2.0dev", markers = "python_version < \"3.11\""}, -] -packaging = ">=20.0.0" -proto-plus = ">=1.15.0,<2.0.0dev" -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" -python-dateutil = ">=2.7.2,<3.0dev" -requests = ">=2.21.0,<3.0.0dev" - -[package.extras] -all = ["Shapely (>=1.8.4,<2.0dev)", "db-dtypes (>=0.3.0,<2.0.0dev)", "geopandas (>=0.9.0,<1.0dev)", "google-cloud-bigquery-storage (>=2.6.0,<3.0.0dev)", "grpcio (>=1.47.0,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "ipykernel (>=6.0.0)", "ipython (>=7.23.1,!=8.1.0)", "ipywidgets (>=7.7.0)", "opentelemetry-api (>=1.1.0)", "opentelemetry-instrumentation (>=0.20b0)", "opentelemetry-sdk (>=1.1.0)", "pandas (>=1.1.0)", "pyarrow (>=3.0.0)", "tqdm (>=4.7.4,<5.0.0dev)"] -bqstorage = ["google-cloud-bigquery-storage (>=2.6.0,<3.0.0dev)", "grpcio (>=1.47.0,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "pyarrow (>=3.0.0)"] -geopandas = ["Shapely (>=1.8.4,<2.0dev)", "geopandas (>=0.9.0,<1.0dev)"] -ipython = ["ipykernel (>=6.0.0)", "ipython (>=7.23.1,!=8.1.0)"] -ipywidgets = ["ipykernel (>=6.0.0)", "ipywidgets (>=7.7.0)"] -opentelemetry = ["opentelemetry-api (>=1.1.0)", "opentelemetry-instrumentation (>=0.20b0)", "opentelemetry-sdk (>=1.1.0)"] -pandas = ["db-dtypes (>=0.3.0,<2.0.0dev)", "pandas (>=1.1.0)", "pyarrow (>=3.0.0)"] -tqdm = ["tqdm (>=4.7.4,<5.0.0dev)"] - -[[package]] -name = "google-cloud-core" -version = "2.3.3" -description = "Google Cloud API client core library" -optional = true -python-versions = ">=3.7" -files = [ - {file = "google-cloud-core-2.3.3.tar.gz", hash = "sha256:37b80273c8d7eee1ae816b3a20ae43585ea50506cb0e60f3cf5be5f87f1373cb"}, - {file = "google_cloud_core-2.3.3-py2.py3-none-any.whl", hash = "sha256:fbd11cad3e98a7e5b0343dc07cb1039a5ffd7a5bb96e1f1e27cee4bda4a90863"}, -] - -[package.dependencies] -google-api-core = ">=1.31.6,<2.0.dev0 || >2.3.0,<3.0.0dev" -google-auth = ">=1.25.0,<3.0dev" - -[package.extras] -grpc = ["grpcio (>=1.38.0,<2.0dev)"] - -[[package]] -name = "google-cloud-resource-manager" -version = "1.10.3" -description = "Google Cloud Resource Manager API client library" -optional = true -python-versions = ">=3.7" -files = [ - {file = "google-cloud-resource-manager-1.10.3.tar.gz", hash = "sha256:f80efcea36f10c5a81889afe93910926e3978b4b1ceeb82f563a2fc863072d14"}, - {file = "google_cloud_resource_manager-1.10.3-py2.py3-none-any.whl", hash = "sha256:1381a4b0f522248ebe0ebd1289d8822b99c54f4e1fe03924a6e723b2ed93dd7f"}, -] - -[package.dependencies] -google-api-core = {version = ">=1.34.0,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} -grpc-google-iam-v1 = ">=0.12.4,<1.0.0dev" -proto-plus = [ - {version = ">=1.22.2,<2.0.0dev", markers = "python_version >= \"3.11\""}, - {version = ">=1.22.0,<2.0.0dev", markers = "python_version < \"3.11\""}, -] -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" - [[package]] name = "google-cloud-speech" -version = "2.21.0" +version = "2.26.0" description = "Google Cloud Speech API client library" optional = true python-versions = ">=3.7" files = [ - {file = "google-cloud-speech-2.21.0.tar.gz", hash = "sha256:661c39bbb6f2b216ba56ace3b087260e9778dd19ade9efa3700adee9258009ad"}, - {file = "google_cloud_speech-2.21.0-py2.py3-none-any.whl", hash = "sha256:88e51aa35d385d7b8325c461327c5f4a19ac8ab38d92ffb0d61c4e91494a0171"}, + {file = "google-cloud-speech-2.26.0.tar.gz", hash = "sha256:d3156a78496aeacff403429408a1b13efe996da6f0544a25567904ad801671d5"}, + {file = "google_cloud_speech-2.26.0-py2.py3-none-any.whl", hash = "sha256:8b61aebcbcc9bd5450933c94c431584a07667e022d12834f9037bb2c0e673c87"}, ] [package.dependencies] -google-api-core = {version = ">=1.34.0,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} -proto-plus = [ - {version = ">=1.22.2,<2.0.0dev", markers = "python_version >= \"3.11\""}, - {version = ">=1.22.0,<2.0.0dev", markers = "python_version < \"3.11\""}, -] +google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} +google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev" +proto-plus = ">=1.22.3,<2.0.0dev" protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" -[[package]] -name = "google-cloud-storage" -version = "2.10.0" -description = "Google Cloud Storage API client library" -optional = true -python-versions = ">=3.7" -files = [ - {file = "google-cloud-storage-2.10.0.tar.gz", hash = "sha256:934b31ead5f3994e5360f9ff5750982c5b6b11604dc072bc452c25965e076dc7"}, - {file = "google_cloud_storage-2.10.0-py2.py3-none-any.whl", hash = "sha256:9433cf28801671de1c80434238fb1e7e4a1ba3087470e90f70c928ea77c2b9d7"}, -] - -[package.dependencies] -google-api-core = ">=1.31.5,<2.0.dev0 || >2.3.0,<3.0.0dev" -google-auth = ">=1.25.0,<3.0dev" -google-cloud-core = ">=2.3.0,<3.0dev" -google-resumable-media = ">=2.3.2" -requests = ">=2.18.0,<3.0.0dev" - -[package.extras] -protobuf = ["protobuf (<5.0.0dev)"] - [[package]] name = "google-cloud-texttospeech" -version = "2.16.1" +version = "2.16.3" description = "Google Cloud Texttospeech API client library" optional = true python-versions = ">=3.7" files = [ - {file = "google-cloud-texttospeech-2.16.1.tar.gz", hash = "sha256:f0c81ff37a5ddc51689299dbd60f030ed85504163e86f04c9a375fd9fa50b304"}, - {file = "google_cloud_texttospeech-2.16.1-py2.py3-none-any.whl", hash = "sha256:58ed78a30ee17cce96ef11f4c793e6bf8f67d029860699b338138bce9502000f"}, + {file = "google-cloud-texttospeech-2.16.3.tar.gz", hash = "sha256:fabc315032d137da0710bb4c268734d336212d8fa8316b23b277dd3a84ce721c"}, + {file = "google_cloud_texttospeech-2.16.3-py2.py3-none-any.whl", hash = "sha256:5d1e23f9270908a5d7ecf2af04105fbd3a7ddde60fe48506e397bd18c1ece499"}, ] [package.dependencies] -google-api-core = {version = ">=1.34.0,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} -google-auth = ">=2.14.1,<3.0.0dev" +google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} +google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev" proto-plus = ">=1.22.3,<2.0.0dev" protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" -[[package]] -name = "google-crc32c" -version = "1.5.0" -description = "A python wrapper of the C library 'Google CRC32C'" -optional = true -python-versions = ">=3.7" -files = [ - {file = "google-crc32c-1.5.0.tar.gz", hash = "sha256:89284716bc6a5a415d4eaa11b1726d2d60a0cd12aadf5439828353662ede9dd7"}, - {file = "google_crc32c-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:596d1f98fc70232fcb6590c439f43b350cb762fb5d61ce7b0e9db4539654cc13"}, - {file = "google_crc32c-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:be82c3c8cfb15b30f36768797a640e800513793d6ae1724aaaafe5bf86f8f346"}, - {file = "google_crc32c-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:461665ff58895f508e2866824a47bdee72497b091c730071f2b7575d5762ab65"}, - {file = "google_crc32c-1.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2096eddb4e7c7bdae4bd69ad364e55e07b8316653234a56552d9c988bd2d61b"}, - {file = "google_crc32c-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:116a7c3c616dd14a3de8c64a965828b197e5f2d121fedd2f8c5585c547e87b02"}, - {file = "google_crc32c-1.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5829b792bf5822fd0a6f6eb34c5f81dd074f01d570ed7f36aa101d6fc7a0a6e4"}, - {file = "google_crc32c-1.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:64e52e2b3970bd891309c113b54cf0e4384762c934d5ae56e283f9a0afcd953e"}, - {file = "google_crc32c-1.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:02ebb8bf46c13e36998aeaad1de9b48f4caf545e91d14041270d9dca767b780c"}, - {file = "google_crc32c-1.5.0-cp310-cp310-win32.whl", hash = "sha256:2e920d506ec85eb4ba50cd4228c2bec05642894d4c73c59b3a2fe20346bd00ee"}, - {file = "google_crc32c-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:07eb3c611ce363c51a933bf6bd7f8e3878a51d124acfc89452a75120bc436289"}, - {file = "google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273"}, - {file = "google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298"}, - {file = "google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57"}, - {file = "google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8485b340a6a9e76c62a7dce3c98e5f102c9219f4cfbf896a00cf48caf078d438"}, - {file = "google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906"}, - {file = "google_crc32c-1.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f583edb943cf2e09c60441b910d6a20b4d9d626c75a36c8fcac01a6c96c01183"}, - {file = "google_crc32c-1.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:a1fd716e7a01f8e717490fbe2e431d2905ab8aa598b9b12f8d10abebb36b04dd"}, - {file = "google_crc32c-1.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:72218785ce41b9cfd2fc1d6a017dc1ff7acfc4c17d01053265c41a2c0cc39b8c"}, - {file = "google_crc32c-1.5.0-cp311-cp311-win32.whl", hash = "sha256:66741ef4ee08ea0b2cc3c86916ab66b6aef03768525627fd6a1b34968b4e3709"}, - {file = "google_crc32c-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:98cb4d057f285bd80d8778ebc4fde6b4d509ac3f331758fb1528b733215443ae"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd8536e902db7e365f49e7d9029283403974ccf29b13fc7028b97e2295b33556"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19e0a019d2c4dcc5e598cd4a4bc7b008546b0358bd322537c74ad47a5386884f"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02c65b9817512edc6a4ae7c7e987fea799d2e0ee40c53ec573a692bee24de876"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6ac08d24c1f16bd2bf5eca8eaf8304812f44af5cfe5062006ec676e7e1d50afc"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3359fc442a743e870f4588fcf5dcbc1bf929df1fad8fb9905cd94e5edb02e84c"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e986b206dae4476f41bcec1faa057851f3889503a70e1bdb2378d406223994a"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:de06adc872bcd8c2a4e0dc51250e9e65ef2ca91be023b9d13ebd67c2ba552e1e"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-win32.whl", hash = "sha256:d3515f198eaa2f0ed49f8819d5732d70698c3fa37384146079b3799b97667a94"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:67b741654b851abafb7bc625b6d1cdd520a379074e64b6a128e3b688c3c04740"}, - {file = "google_crc32c-1.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c02ec1c5856179f171e032a31d6f8bf84e5a75c45c33b2e20a3de353b266ebd8"}, - {file = "google_crc32c-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:edfedb64740750e1a3b16152620220f51d58ff1b4abceb339ca92e934775c27a"}, - {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84e6e8cd997930fc66d5bb4fde61e2b62ba19d62b7abd7a69920406f9ecca946"}, - {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:024894d9d3cfbc5943f8f230e23950cd4906b2fe004c72e29b209420a1e6b05a"}, - {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:998679bf62b7fb599d2878aa3ed06b9ce688b8974893e7223c60db155f26bd8d"}, - {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:83c681c526a3439b5cf94f7420471705bbf96262f49a6fe546a6db5f687a3d4a"}, - {file = "google_crc32c-1.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4c6fdd4fccbec90cc8a01fc00773fcd5fa28db683c116ee3cb35cd5da9ef6c37"}, - {file = "google_crc32c-1.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5ae44e10a8e3407dbe138984f21e536583f2bba1be9491239f942c2464ac0894"}, - {file = "google_crc32c-1.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37933ec6e693e51a5b07505bd05de57eee12f3e8c32b07da7e73669398e6630a"}, - {file = "google_crc32c-1.5.0-cp38-cp38-win32.whl", hash = "sha256:fe70e325aa68fa4b5edf7d1a4b6f691eb04bbccac0ace68e34820d283b5f80d4"}, - {file = "google_crc32c-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:74dea7751d98034887dbd821b7aae3e1d36eda111d6ca36c206c44478035709c"}, - {file = "google_crc32c-1.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c6c777a480337ac14f38564ac88ae82d4cd238bf293f0a22295b66eb89ffced7"}, - {file = "google_crc32c-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:759ce4851a4bb15ecabae28f4d2e18983c244eddd767f560165563bf9aefbc8d"}, - {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f13cae8cc389a440def0c8c52057f37359014ccbc9dc1f0827936bcd367c6100"}, - {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e560628513ed34759456a416bf86b54b2476c59144a9138165c9a1575801d0d9"}, - {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1674e4307fa3024fc897ca774e9c7562c957af85df55efe2988ed9056dc4e57"}, - {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:278d2ed7c16cfc075c91378c4f47924c0625f5fc84b2d50d921b18b7975bd210"}, - {file = "google_crc32c-1.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d5280312b9af0976231f9e317c20e4a61cd2f9629b7bfea6a693d1878a264ebd"}, - {file = "google_crc32c-1.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8b87e1a59c38f275c0e3676fc2ab6d59eccecfd460be267ac360cc31f7bcde96"}, - {file = "google_crc32c-1.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7c074fece789b5034b9b1404a1f8208fc2d4c6ce9decdd16e8220c5a793e6f61"}, - {file = "google_crc32c-1.5.0-cp39-cp39-win32.whl", hash = "sha256:7f57f14606cd1dd0f0de396e1e53824c371e9544a822648cd76c034d209b559c"}, - {file = "google_crc32c-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:a2355cba1f4ad8b6988a4ca3feed5bff33f6af2d7f134852cf279c2aebfde541"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f314013e7dcd5cf45ab1945d92e713eec788166262ae8deb2cfacd53def27325"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b747a674c20a67343cb61d43fdd9207ce5da6a99f629c6e2541aa0e89215bcd"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8f24ed114432de109aa9fd317278518a5af2d31ac2ea6b952b2f7782b43da091"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8667b48e7a7ef66afba2c81e1094ef526388d35b873966d8a9a447974ed9178"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:1c7abdac90433b09bad6c43a43af253e688c9cfc1c86d332aed13f9a7c7f65e2"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6f998db4e71b645350b9ac28a2167e6632c239963ca9da411523bb439c5c514d"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c99616c853bb585301df6de07ca2cadad344fd1ada6d62bb30aec05219c45d2"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ad40e31093a4af319dadf503b2467ccdc8f67c72e4bcba97f8c10cb078207b5"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd67cf24a553339d5062eff51013780a00d6f97a39ca062781d06b3a73b15462"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:398af5e3ba9cf768787eef45c803ff9614cc3e22a5b2f7d7ae116df8b11e3314"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b1f8133c9a275df5613a451e73f36c2aea4fe13c5c8997e22cf355ebd7bd0728"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ba053c5f50430a3fcfd36f75aff9caeba0440b2d076afdb79a318d6ca245f88"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:272d3892a1e1a2dbc39cc5cde96834c236d5327e2122d3aaa19f6614531bb6eb"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:635f5d4dd18758a1fbd1049a8e8d2fee4ffed124462d837d1a02a0e009c3ab31"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c672d99a345849301784604bfeaeba4db0c7aae50b95be04dd651fd2a7310b93"}, -] - -[package.extras] -testing = ["pytest"] - -[[package]] -name = "google-resumable-media" -version = "2.5.0" -description = "Utilities for Google Media Downloads and Resumable Uploads" -optional = true -python-versions = ">= 3.7" -files = [ - {file = "google-resumable-media-2.5.0.tar.gz", hash = "sha256:218931e8e2b2a73a58eb354a288e03a0fd5fb1c4583261ac6e4c078666468c93"}, - {file = "google_resumable_media-2.5.0-py2.py3-none-any.whl", hash = "sha256:da1bd943e2e114a56d85d6848497ebf9be6a14d3db23e9fc57581e7c3e8170ec"}, -] - -[package.dependencies] -google-crc32c = ">=1.0,<2.0dev" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)"] -requests = ["requests (>=2.18.0,<3.0.0dev)"] - [[package]] name = "googleapis-common-protos" -version = "1.60.0" +version = "1.63.0" description = "Common protobufs used in Google APIs" optional = true python-versions = ">=3.7" files = [ - {file = "googleapis-common-protos-1.60.0.tar.gz", hash = "sha256:e73ebb404098db405ba95d1e1ae0aa91c3e15a71da031a2eeb6b2e23e7bc3708"}, - {file = "googleapis_common_protos-1.60.0-py2.py3-none-any.whl", hash = "sha256:69f9bbcc6acde92cab2db95ce30a70bd2b81d20b12eff3f1aabaffcbe8a93918"}, + {file = "googleapis-common-protos-1.63.0.tar.gz", hash = "sha256:17ad01b11d5f1d0171c06d3ba5c04c54474e883b66b949722b4938ee2694ef4e"}, + {file = "googleapis_common_protos-1.63.0-py2.py3-none-any.whl", hash = "sha256:ae45f75702f7c08b541f750854a678bd8f534a1a6bace6afe975f1d0a82d6632"}, ] [package.dependencies] -grpcio = {version = ">=1.44.0,<2.0.0.dev0", optional = true, markers = "extra == \"grpc\""} protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" [package.extras] @@ -1188,185 +1085,149 @@ grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] [[package]] name = "greenlet" -version = "2.0.2" +version = "3.0.3" description = "Lightweight in-process concurrent programming" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" -files = [ - {file = "greenlet-2.0.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:bdfea8c661e80d3c1c99ad7c3ff74e6e87184895bbaca6ee8cc61209f8b9b85d"}, - {file = "greenlet-2.0.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:9d14b83fab60d5e8abe587d51c75b252bcc21683f24699ada8fb275d7712f5a9"}, - {file = "greenlet-2.0.2-cp27-cp27m-win32.whl", hash = "sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74"}, - {file = "greenlet-2.0.2-cp27-cp27m-win_amd64.whl", hash = "sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343"}, - {file = "greenlet-2.0.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae"}, - {file = "greenlet-2.0.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df"}, - {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088"}, - {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb"}, - {file = "greenlet-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d75209eed723105f9596807495d58d10b3470fa6732dd6756595e89925ce2470"}, - {file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a51c9751078733d88e013587b108f1b7a1fb106d402fb390740f002b6f6551a"}, - {file = "greenlet-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91"}, - {file = "greenlet-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645"}, - {file = "greenlet-2.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c"}, - {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca"}, - {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0"}, - {file = "greenlet-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2"}, - {file = "greenlet-2.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:eff4eb9b7eb3e4d0cae3d28c283dc16d9bed6b193c2e1ace3ed86ce48ea8df19"}, - {file = "greenlet-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5454276c07d27a740c5892f4907c86327b632127dd9abec42ee62e12427ff7e3"}, - {file = "greenlet-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:7cafd1208fdbe93b67c7086876f061f660cfddc44f404279c1585bbf3cdc64c5"}, - {file = "greenlet-2.0.2-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:910841381caba4f744a44bf81bfd573c94e10b3045ee00de0cbf436fe50673a6"}, - {file = "greenlet-2.0.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:18a7f18b82b52ee85322d7a7874e676f34ab319b9f8cce5de06067384aa8ff43"}, - {file = "greenlet-2.0.2-cp35-cp35m-win32.whl", hash = "sha256:03a8f4f3430c3b3ff8d10a2a86028c660355ab637cee9333d63d66b56f09d52a"}, - {file = "greenlet-2.0.2-cp35-cp35m-win_amd64.whl", hash = "sha256:4b58adb399c4d61d912c4c331984d60eb66565175cdf4a34792cd9600f21b394"}, - {file = "greenlet-2.0.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:703f18f3fda276b9a916f0934d2fb6d989bf0b4fb5a64825260eb9bfd52d78f0"}, - {file = "greenlet-2.0.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:32e5b64b148966d9cccc2c8d35a671409e45f195864560829f395a54226408d3"}, - {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dd11f291565a81d71dab10b7033395b7a3a5456e637cf997a6f33ebdf06f8db"}, - {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0f72c9ddb8cd28532185f54cc1453f2c16fb417a08b53a855c4e6a418edd099"}, - {file = "greenlet-2.0.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd021c754b162c0fb55ad5d6b9d960db667faad0fa2ff25bb6e1301b0b6e6a75"}, - {file = "greenlet-2.0.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:3c9b12575734155d0c09d6c3e10dbd81665d5c18e1a7c6597df72fd05990c8cf"}, - {file = "greenlet-2.0.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b9ec052b06a0524f0e35bd8790686a1da006bd911dd1ef7d50b77bfbad74e292"}, - {file = "greenlet-2.0.2-cp36-cp36m-win32.whl", hash = "sha256:dbfcfc0218093a19c252ca8eb9aee3d29cfdcb586df21049b9d777fd32c14fd9"}, - {file = "greenlet-2.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:9f35ec95538f50292f6d8f2c9c9f8a3c6540bbfec21c9e5b4b751e0a7c20864f"}, - {file = "greenlet-2.0.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:d5508f0b173e6aa47273bdc0a0b5ba055b59662ba7c7ee5119528f466585526b"}, - {file = "greenlet-2.0.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:f82d4d717d8ef19188687aa32b8363e96062911e63ba22a0cff7802a8e58e5f1"}, - {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9c59a2120b55788e800d82dfa99b9e156ff8f2227f07c5e3012a45a399620b7"}, - {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2780572ec463d44c1d3ae850239508dbeb9fed38e294c68d19a24d925d9223ca"}, - {file = "greenlet-2.0.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:937e9020b514ceedb9c830c55d5c9872abc90f4b5862f89c0887033ae33c6f73"}, - {file = "greenlet-2.0.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:36abbf031e1c0f79dd5d596bfaf8e921c41df2bdf54ee1eed921ce1f52999a86"}, - {file = "greenlet-2.0.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:18e98fb3de7dba1c0a852731c3070cf022d14f0d68b4c87a19cc1016f3bb8b33"}, - {file = "greenlet-2.0.2-cp37-cp37m-win32.whl", hash = "sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7"}, - {file = "greenlet-2.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3"}, - {file = "greenlet-2.0.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30"}, - {file = "greenlet-2.0.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b"}, - {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526"}, - {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b"}, - {file = "greenlet-2.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acd2162a36d3de67ee896c43effcd5ee3de247eb00354db411feb025aa319857"}, - {file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0bf60faf0bc2468089bdc5edd10555bab6e85152191df713e2ab1fcc86382b5a"}, - {file = "greenlet-2.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a"}, - {file = "greenlet-2.0.2-cp38-cp38-win32.whl", hash = "sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249"}, - {file = "greenlet-2.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40"}, - {file = "greenlet-2.0.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8"}, - {file = "greenlet-2.0.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6"}, - {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df"}, - {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be4ed120b52ae4d974aa40215fcdfde9194d63541c7ded40ee12eb4dda57b76b"}, - {file = "greenlet-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94c817e84245513926588caf1152e3b559ff794d505555211ca041f032abbb6b"}, - {file = "greenlet-2.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1a819eef4b0e0b96bb0d98d797bef17dc1b4a10e8d7446be32d1da33e095dbb8"}, - {file = "greenlet-2.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7efde645ca1cc441d6dc4b48c0f7101e8d86b54c8530141b09fd31cef5149ec9"}, - {file = "greenlet-2.0.2-cp39-cp39-win32.whl", hash = "sha256:ea9872c80c132f4663822dd2a08d404073a5a9b5ba6155bea72fb2a79d1093b5"}, - {file = "greenlet-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:db1a39669102a1d8d12b57de2bb7e2ec9066a6f2b3da35ae511ff93b01b5d564"}, - {file = "greenlet-2.0.2.tar.gz", hash = "sha256:e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0"}, -] - -[package.extras] -docs = ["Sphinx", "docutils (<0.18)"] -test = ["objgraph", "psutil"] - -[[package]] -name = "grpc-google-iam-v1" -version = "0.12.6" -description = "IAM API client library" optional = true python-versions = ">=3.7" files = [ - {file = "grpc-google-iam-v1-0.12.6.tar.gz", hash = "sha256:2bc4b8fdf22115a65d751c9317329322602c39b7c86a289c9b72d228d960ef5f"}, - {file = "grpc_google_iam_v1-0.12.6-py2.py3-none-any.whl", hash = "sha256:5c10f3d8dc2d88678ab1a9b0cb5482735c5efee71e6c0cd59f872eef22913f5c"}, + {file = "greenlet-3.0.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dca1e2f3ca00b84a396bc1bce13dd21f680f035314d2379c4160c98153b2059b"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ed7fb269f15dc662787f4119ec300ad0702fa1b19d2135a37c2c4de6fadfd4a"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd4f49ae60e10adbc94b45c0b5e6a179acc1736cf7a90160b404076ee283cf83"}, + {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:73a411ef564e0e097dbe7e866bb2dda0f027e072b04da387282b02c308807405"}, + {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7f362975f2d179f9e26928c5b517524e89dd48530a0202570d55ad6ca5d8a56f"}, + {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:649dde7de1a5eceb258f9cb00bdf50e978c9db1b996964cd80703614c86495eb"}, + {file = "greenlet-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:68834da854554926fbedd38c76e60c4a2e3198c6fbed520b106a8986445caaf9"}, + {file = "greenlet-3.0.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379"}, + {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22"}, + {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3"}, + {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d"}, + {file = "greenlet-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728"}, + {file = "greenlet-3.0.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230"}, + {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf"}, + {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305"}, + {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6"}, + {file = "greenlet-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2"}, + {file = "greenlet-3.0.3-cp37-cp37m-macosx_11_0_universal2.whl", hash = "sha256:5b51e85cb5ceda94e79d019ed36b35386e8c37d22f07d6a751cb659b180d5274"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:daf3cb43b7cf2ba96d614252ce1684c1bccee6b2183a01328c98d36fcd7d5cb0"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99bf650dc5d69546e076f413a87481ee1d2d09aaaaaca058c9251b6d8c14783f"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dd6e660effd852586b6a8478a1d244b8dc90ab5b1321751d2ea15deb49ed414"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3391d1e16e2a5a1507d83e4a8b100f4ee626e8eca43cf2cadb543de69827c4c"}, + {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1f145462f1fa6e4a4ae3c0f782e580ce44d57c8f2c7aae1b6fa88c0b2efdb41"}, + {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1a7191e42732df52cb5f39d3527217e7ab73cae2cb3694d241e18f53d84ea9a7"}, + {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0448abc479fab28b00cb472d278828b3ccca164531daab4e970a0458786055d6"}, + {file = "greenlet-3.0.3-cp37-cp37m-win32.whl", hash = "sha256:b542be2440edc2d48547b5923c408cbe0fc94afb9f18741faa6ae970dbcb9b6d"}, + {file = "greenlet-3.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67"}, + {file = "greenlet-3.0.3-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1996cb9306c8595335bb157d133daf5cf9f693ef413e7673cb07e3e5871379ca"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ddc0f794e6ad661e321caa8d2f0a55ce01213c74722587256fb6566049a8b04"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9db1c18f0eaad2f804728c67d6c610778456e3e1cc4ab4bbd5eeb8e6053c6fc"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7170375bcc99f1a2fbd9c306f5be8764eaf3ac6b5cb968862cad4c7057756506"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b66c9c1e7ccabad3a7d037b2bcb740122a7b17a53734b7d72a344ce39882a1b"}, + {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:098d86f528c855ead3479afe84b49242e174ed262456c342d70fc7f972bc13c4"}, + {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:81bb9c6d52e8321f09c3d165b2a78c680506d9af285bfccbad9fb7ad5a5da3e5"}, + {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da"}, + {file = "greenlet-3.0.3-cp38-cp38-win32.whl", hash = "sha256:d46677c85c5ba00a9cb6f7a00b2bfa6f812192d2c9f7d9c4f6a55b60216712f3"}, + {file = "greenlet-3.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:419b386f84949bf0e7c73e6032e3457b82a787c1ab4a0e43732898a761cc9dbf"}, + {file = "greenlet-3.0.3-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:da70d4d51c8b306bb7a031d5cff6cc25ad253affe89b70352af5f1cb68e74b53"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086152f8fbc5955df88382e8a75984e2bb1c892ad2e3c80a2508954e52295257"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d73a9fe764d77f87f8ec26a0c85144d6a951a6c438dfe50487df5595c6373eac"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7dcbe92cc99f08c8dd11f930de4d99ef756c3591a5377d1d9cd7dd5e896da71"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1551a8195c0d4a68fac7a4325efac0d541b48def35feb49d803674ac32582f61"}, + {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:64d7675ad83578e3fc149b617a444fab8efdafc9385471f868eb5ff83e446b8b"}, + {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b37eef18ea55f2ffd8f00ff8fe7c8d3818abd3e25fb73fae2ca3b672e333a7a6"}, + {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:77457465d89b8263bca14759d7c1684df840b6811b2499838cc5b040a8b5b113"}, + {file = "greenlet-3.0.3-cp39-cp39-win32.whl", hash = "sha256:57e8974f23e47dac22b83436bdcf23080ade568ce77df33159e019d161ce1d1e"}, + {file = "greenlet-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c5ee858cfe08f34712f548c3c363e807e7186f03ad7a5039ebadb29e8c6be067"}, + {file = "greenlet-3.0.3.tar.gz", hash = "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491"}, ] -[package.dependencies] -googleapis-common-protos = {version = ">=1.56.0,<2.0.0dev", extras = ["grpc"]} -grpcio = ">=1.44.0,<2.0.0dev" -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" +[package.extras] +docs = ["Sphinx", "furo"] +test = ["objgraph", "psutil"] [[package]] name = "grpcio" -version = "1.57.0" +version = "1.64.0" description = "HTTP/2-based RPC framework" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "grpcio-1.57.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:092fa155b945015754bdf988be47793c377b52b88d546e45c6a9f9579ac7f7b6"}, - {file = "grpcio-1.57.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:2f7349786da979a94690cc5c2b804cab4e8774a3cf59be40d037c4342c906649"}, - {file = "grpcio-1.57.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:82640e57fb86ea1d71ea9ab54f7e942502cf98a429a200b2e743d8672171734f"}, - {file = "grpcio-1.57.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40b72effd4c789de94ce1be2b5f88d7b9b5f7379fe9645f198854112a6567d9a"}, - {file = "grpcio-1.57.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f708a6a17868ad8bf586598bee69abded4996b18adf26fd2d91191383b79019"}, - {file = "grpcio-1.57.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:60fe15288a0a65d5c1cb5b4a62b1850d07336e3ba728257a810317be14f0c527"}, - {file = "grpcio-1.57.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6907b1cf8bb29b058081d2aad677b15757a44ef2d4d8d9130271d2ad5e33efca"}, - {file = "grpcio-1.57.0-cp310-cp310-win32.whl", hash = "sha256:57b183e8b252825c4dd29114d6c13559be95387aafc10a7be645462a0fc98bbb"}, - {file = "grpcio-1.57.0-cp310-cp310-win_amd64.whl", hash = "sha256:7b400807fa749a9eb286e2cd893e501b110b4d356a218426cb9c825a0474ca56"}, - {file = "grpcio-1.57.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:c6ebecfb7a31385393203eb04ed8b6a08f5002f53df3d59e5e795edb80999652"}, - {file = "grpcio-1.57.0-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:00258cbe3f5188629828363ae8ff78477ce976a6f63fb2bb5e90088396faa82e"}, - {file = "grpcio-1.57.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:23e7d8849a0e58b806253fd206ac105b328171e01b8f18c7d5922274958cc87e"}, - {file = "grpcio-1.57.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5371bcd861e679d63b8274f73ac281751d34bd54eccdbfcd6aa00e692a82cd7b"}, - {file = "grpcio-1.57.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aed90d93b731929e742967e236f842a4a2174dc5db077c8f9ad2c5996f89f63e"}, - {file = "grpcio-1.57.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fe752639919aad9ffb0dee0d87f29a6467d1ef764f13c4644d212a9a853a078d"}, - {file = "grpcio-1.57.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fada6b07ec4f0befe05218181f4b85176f11d531911b64c715d1875c4736d73a"}, - {file = "grpcio-1.57.0-cp311-cp311-win32.whl", hash = "sha256:bb396952cfa7ad2f01061fbc7dc1ad91dd9d69243bcb8110cf4e36924785a0fe"}, - {file = "grpcio-1.57.0-cp311-cp311-win_amd64.whl", hash = "sha256:e503cb45ed12b924b5b988ba9576dc9949b2f5283b8e33b21dcb6be74a7c58d0"}, - {file = "grpcio-1.57.0-cp37-cp37m-linux_armv7l.whl", hash = "sha256:fd173b4cf02b20f60860dc2ffe30115c18972d7d6d2d69df97ac38dee03be5bf"}, - {file = "grpcio-1.57.0-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:d7f8df114d6b4cf5a916b98389aeaf1e3132035420a88beea4e3d977e5f267a5"}, - {file = "grpcio-1.57.0-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:76c44efa4ede1f42a9d5b2fed1fe9377e73a109bef8675fb0728eb80b0b8e8f2"}, - {file = "grpcio-1.57.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4faea2cfdf762a664ab90589b66f416274887641ae17817de510b8178356bf73"}, - {file = "grpcio-1.57.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c60b83c43faeb6d0a9831f0351d7787a0753f5087cc6fa218d78fdf38e5acef0"}, - {file = "grpcio-1.57.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b363bbb5253e5f9c23d8a0a034dfdf1b7c9e7f12e602fc788c435171e96daccc"}, - {file = "grpcio-1.57.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:f1fb0fd4a1e9b11ac21c30c169d169ef434c6e9344ee0ab27cfa6f605f6387b2"}, - {file = "grpcio-1.57.0-cp37-cp37m-win_amd64.whl", hash = "sha256:34950353539e7d93f61c6796a007c705d663f3be41166358e3d88c45760c7d98"}, - {file = "grpcio-1.57.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:871f9999e0211f9551f368612460442a5436d9444606184652117d6a688c9f51"}, - {file = "grpcio-1.57.0-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:a8a8e560e8dbbdf29288872e91efd22af71e88b0e5736b0daf7773c1fecd99f0"}, - {file = "grpcio-1.57.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:2313b124e475aa9017a9844bdc5eafb2d5abdda9d456af16fc4535408c7d6da6"}, - {file = "grpcio-1.57.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b4098b6b638d9e0ca839a81656a2fd4bc26c9486ea707e8b1437d6f9d61c3941"}, - {file = "grpcio-1.57.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e5b58e32ae14658085c16986d11e99abd002ddbf51c8daae8a0671fffb3467f"}, - {file = "grpcio-1.57.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0f80bf37f09e1caba6a8063e56e2b87fa335add314cf2b78ebf7cb45aa7e3d06"}, - {file = "grpcio-1.57.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5b7a4ce8f862fe32b2a10b57752cf3169f5fe2915acfe7e6a1e155db3da99e79"}, - {file = "grpcio-1.57.0-cp38-cp38-win32.whl", hash = "sha256:9338bacf172e942e62e5889b6364e56657fbf8ac68062e8b25c48843e7b202bb"}, - {file = "grpcio-1.57.0-cp38-cp38-win_amd64.whl", hash = "sha256:e1cb52fa2d67d7f7fab310b600f22ce1ff04d562d46e9e0ac3e3403c2bb4cc16"}, - {file = "grpcio-1.57.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:fee387d2fab144e8a34e0e9c5ca0f45c9376b99de45628265cfa9886b1dbe62b"}, - {file = "grpcio-1.57.0-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:b53333627283e7241fcc217323f225c37783b5f0472316edcaa4479a213abfa6"}, - {file = "grpcio-1.57.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:f19ac6ac0a256cf77d3cc926ef0b4e64a9725cc612f97228cd5dc4bd9dbab03b"}, - {file = "grpcio-1.57.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e3fdf04e402f12e1de8074458549337febb3b45f21076cc02ef4ff786aff687e"}, - {file = "grpcio-1.57.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5613a2fecc82f95d6c51d15b9a72705553aa0d7c932fad7aed7afb51dc982ee5"}, - {file = "grpcio-1.57.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b670c2faa92124b7397b42303e4d8eb64a4cd0b7a77e35a9e865a55d61c57ef9"}, - {file = "grpcio-1.57.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7a635589201b18510ff988161b7b573f50c6a48fae9cb567657920ca82022b37"}, - {file = "grpcio-1.57.0-cp39-cp39-win32.whl", hash = "sha256:d78d8b86fcdfa1e4c21f8896614b6cc7ee01a2a758ec0c4382d662f2a62cf766"}, - {file = "grpcio-1.57.0-cp39-cp39-win_amd64.whl", hash = "sha256:20ec6fc4ad47d1b6e12deec5045ec3cd5402d9a1597f738263e98f490fe07056"}, - {file = "grpcio-1.57.0.tar.gz", hash = "sha256:4b089f7ad1eb00a104078bab8015b0ed0ebcb3b589e527ab009c53893fd4e613"}, -] - -[package.extras] -protobuf = ["grpcio-tools (>=1.57.0)"] + {file = "grpcio-1.64.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:3b09c3d9de95461214a11d82cc0e6a46a6f4e1f91834b50782f932895215e5db"}, + {file = "grpcio-1.64.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:7e013428ab472892830287dd082b7d129f4d8afef49227a28223a77337555eaa"}, + {file = "grpcio-1.64.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:02cc9cc3f816d30f7993d0d408043b4a7d6a02346d251694d8ab1f78cc723e7e"}, + {file = "grpcio-1.64.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f5de082d936e0208ce8db9095821361dfa97af8767a6607ae71425ac8ace15c"}, + {file = "grpcio-1.64.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7b7bf346391dffa182fba42506adf3a84f4a718a05e445b37824136047686a1"}, + {file = "grpcio-1.64.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b2cbdfba18408389a1371f8c2af1659119e1831e5ed24c240cae9e27b4abc38d"}, + {file = "grpcio-1.64.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:aca4f15427d2df592e0c8f3d38847e25135e4092d7f70f02452c0e90d6a02d6d"}, + {file = "grpcio-1.64.0-cp310-cp310-win32.whl", hash = "sha256:7c1f5b2298244472bcda49b599be04579f26425af0fd80d3f2eb5fd8bc84d106"}, + {file = "grpcio-1.64.0-cp310-cp310-win_amd64.whl", hash = "sha256:73f84f9e5985a532e47880b3924867de16fa1aa513fff9b26106220c253c70c5"}, + {file = "grpcio-1.64.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:2a18090371d138a57714ee9bffd6c9c9cb2e02ce42c681aac093ae1e7189ed21"}, + {file = "grpcio-1.64.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:59c68df3a934a586c3473d15956d23a618b8f05b5e7a3a904d40300e9c69cbf0"}, + {file = "grpcio-1.64.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:b52e1ec7185512103dd47d41cf34ea78e7a7361ba460187ddd2416b480e0938c"}, + {file = "grpcio-1.64.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d598b5d5e2c9115d7fb7e2cb5508d14286af506a75950762aa1372d60e41851"}, + {file = "grpcio-1.64.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01615bbcae6875eee8091e6b9414072f4e4b00d8b7e141f89635bdae7cf784e5"}, + {file = "grpcio-1.64.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0b2dfe6dcace264807d9123d483d4c43274e3f8c39f90ff51de538245d7a4145"}, + {file = "grpcio-1.64.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7f17572dc9acd5e6dfd3014d10c0b533e9f79cd9517fc10b0225746f4c24b58e"}, + {file = "grpcio-1.64.0-cp311-cp311-win32.whl", hash = "sha256:6ec5ed15b4ffe56e2c6bc76af45e6b591c9be0224b3fb090adfb205c9012367d"}, + {file = "grpcio-1.64.0-cp311-cp311-win_amd64.whl", hash = "sha256:597191370951b477b7a1441e1aaa5cacebeb46a3b0bd240ec3bb2f28298c7553"}, + {file = "grpcio-1.64.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:1ce4cd5a61d4532651079e7aae0fedf9a80e613eed895d5b9743e66b52d15812"}, + {file = "grpcio-1.64.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:650a8150a9b288f40d5b7c1d5400cc11724eae50bd1f501a66e1ea949173649b"}, + {file = "grpcio-1.64.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:8de0399b983f8676a7ccfdd45e5b2caec74a7e3cc576c6b1eecf3b3680deda5e"}, + {file = "grpcio-1.64.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:46b8b43ba6a2a8f3103f103f97996cad507bcfd72359af6516363c48793d5a7b"}, + {file = "grpcio-1.64.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a54362f03d4dcfae63be455d0a7d4c1403673498b92c6bfe22157d935b57c7a9"}, + {file = "grpcio-1.64.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1f8ea18b928e539046bb5f9c124d717fbf00cc4b2d960ae0b8468562846f5aa1"}, + {file = "grpcio-1.64.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c56c91bd2923ddb6e7ed28ebb66d15633b03e0df22206f22dfcdde08047e0a48"}, + {file = "grpcio-1.64.0-cp312-cp312-win32.whl", hash = "sha256:874c741c8a66f0834f653a69e7e64b4e67fcd4a8d40296919b93bab2ccc780ba"}, + {file = "grpcio-1.64.0-cp312-cp312-win_amd64.whl", hash = "sha256:0da1d921f8e4bcee307aeef6c7095eb26e617c471f8cb1c454fd389c5c296d1e"}, + {file = "grpcio-1.64.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:c46fb6bfca17bfc49f011eb53416e61472fa96caa0979b4329176bdd38cbbf2a"}, + {file = "grpcio-1.64.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3d2004e85cf5213995d09408501f82c8534700d2babeb81dfdba2a3bff0bb396"}, + {file = "grpcio-1.64.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:6d5541eb460d73a07418524fb64dcfe0adfbcd32e2dac0f8f90ce5b9dd6c046c"}, + {file = "grpcio-1.64.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f279ad72dd7d64412e10f2443f9f34872a938c67387863c4cd2fb837f53e7d2"}, + {file = "grpcio-1.64.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85fda90b81da25993aa47fae66cae747b921f8f6777550895fb62375b776a231"}, + {file = "grpcio-1.64.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a053584079b793a54bece4a7d1d1b5c0645bdbee729215cd433703dc2532f72b"}, + {file = "grpcio-1.64.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:579dd9fb11bc73f0de061cab5f8b2def21480fd99eb3743ed041ad6a1913ee2f"}, + {file = "grpcio-1.64.0-cp38-cp38-win32.whl", hash = "sha256:23b6887bb21d77649d022fa1859e05853fdc2e60682fd86c3db652a555a282e0"}, + {file = "grpcio-1.64.0-cp38-cp38-win_amd64.whl", hash = "sha256:753cb58683ba0c545306f4e17dabf468d29cb6f6b11832e1e432160bb3f8403c"}, + {file = "grpcio-1.64.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:2186d76a7e383e1466e0ea2b0febc343ffeae13928c63c6ec6826533c2d69590"}, + {file = "grpcio-1.64.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0f30596cdcbed3c98024fb4f1d91745146385b3f9fd10c9f2270cbfe2ed7ed91"}, + {file = "grpcio-1.64.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:d9171f025a196f5bcfec7e8e7ffb7c3535f7d60aecd3503f9e250296c7cfc150"}, + {file = "grpcio-1.64.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf4c8daed18ae2be2f1fc7d613a76ee2a2e28fdf2412d5c128be23144d28283d"}, + {file = "grpcio-1.64.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3550493ac1d23198d46dc9c9b24b411cef613798dc31160c7138568ec26bc9b4"}, + {file = "grpcio-1.64.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3161a8f8bb38077a6470508c1a7301cd54301c53b8a34bb83e3c9764874ecabd"}, + {file = "grpcio-1.64.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e8fabe2cc57a369638ab1ad8e6043721014fdf9a13baa7c0e35995d3a4a7618"}, + {file = "grpcio-1.64.0-cp39-cp39-win32.whl", hash = "sha256:31890b24d47b62cc27da49a462efe3d02f3c120edb0e6c46dcc0025506acf004"}, + {file = "grpcio-1.64.0-cp39-cp39-win_amd64.whl", hash = "sha256:5a56797dea8c02e7d3a85dfea879f286175cf4d14fbd9ab3ef2477277b927baa"}, + {file = "grpcio-1.64.0.tar.gz", hash = "sha256:257baf07f53a571c215eebe9679c3058a313fd1d1f7c4eede5a8660108c52d9c"}, +] + +[package.extras] +protobuf = ["grpcio-tools (>=1.64.0)"] [[package]] name = "grpcio-status" -version = "1.57.0" +version = "1.62.2" description = "Status proto mapping for gRPC" optional = true python-versions = ">=3.6" files = [ - {file = "grpcio-status-1.57.0.tar.gz", hash = "sha256:b098da99df1eebe58337f8f78e50df990273ccacc1226fddeb47c590e3df9e02"}, - {file = "grpcio_status-1.57.0-py3-none-any.whl", hash = "sha256:15d6af055914ebbc4ed17e55ebfb8e6bb17a45a57fea32e6af19978fb7844690"}, + {file = "grpcio-status-1.62.2.tar.gz", hash = "sha256:62e1bfcb02025a1cd73732a2d33672d3e9d0df4d21c12c51e0bbcaf09bab742a"}, + {file = "grpcio_status-1.62.2-py3-none-any.whl", hash = "sha256:206ddf0eb36bc99b033f03b2c8e95d319f0044defae9b41ae21408e7e0cda48f"}, ] [package.dependencies] googleapis-common-protos = ">=1.5.5" -grpcio = ">=1.57.0" +grpcio = ">=1.62.2" protobuf = ">=4.21.6" -[[package]] -name = "gtts" -version = "2.3.2" -description = "gTTS (Google Text-to-Speech), a Python library and CLI tool to interface with Google Translate text-to-speech API" -optional = true -python-versions = ">=3.7" -files = [ - {file = "gTTS-2.3.2-py3-none-any.whl", hash = "sha256:9132e409603f34d5023458e3e10ce2f5df55498d7a2ee781c9adbe616fbd4152"}, - {file = "gTTS-2.3.2.tar.gz", hash = "sha256:5314f7dedb4230889ff4773edd37e101408497e166982027b8d9582a4585eb4f"}, -] - -[package.dependencies] -click = ">=7.1,<8.2" -requests = ">=2.27,<3" - -[package.extras] -docs = ["sphinx", "sphinx-autobuild", "sphinx-click", "sphinx-mdinclude", "sphinx-rtd-theme"] -tests = ["pytest (>=7.1.3,<7.2.0)", "pytest-cov", "testfixtures"] - [[package]] name = "h11" version = "0.14.0" @@ -1380,39 +1241,88 @@ files = [ [[package]] name = "httpcore" -version = "0.17.3" +version = "1.0.5" description = "A minimal low-level HTTP client." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "httpcore-0.17.3-py3-none-any.whl", hash = "sha256:c2789b767ddddfa2a5782e3199b2b7f6894540b17b16ec26b2c4d8e103510b87"}, - {file = "httpcore-0.17.3.tar.gz", hash = "sha256:a6f30213335e34c1ade7be6ec7c47f19f50c56db36abef1a9dfa3815b1cb3888"}, + {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, + {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, ] [package.dependencies] -anyio = ">=3.0,<5.0" certifi = "*" h11 = ">=0.13,<0.15" -sniffio = "==1.*" [package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<0.26.0)"] + +[[package]] +name = "httptools" +version = "0.6.1" +description = "A collection of framework independent HTTP protocol utils." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d2f6c3c4cb1948d912538217838f6e9960bc4a521d7f9b323b3da579cd14532f"}, + {file = "httptools-0.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:00d5d4b68a717765b1fabfd9ca755bd12bf44105eeb806c03d1962acd9b8e563"}, + {file = "httptools-0.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:639dc4f381a870c9ec860ce5c45921db50205a37cc3334e756269736ff0aac58"}, + {file = "httptools-0.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e57997ac7fb7ee43140cc03664de5f268813a481dff6245e0075925adc6aa185"}, + {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0ac5a0ae3d9f4fe004318d64b8a854edd85ab76cffbf7ef5e32920faef62f142"}, + {file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3f30d3ce413088a98b9db71c60a6ada2001a08945cb42dd65a9a9fe228627658"}, + {file = "httptools-0.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:1ed99a373e327f0107cb513b61820102ee4f3675656a37a50083eda05dc9541b"}, + {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7a7ea483c1a4485c71cb5f38be9db078f8b0e8b4c4dc0210f531cdd2ddac1ef1"}, + {file = "httptools-0.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:85ed077c995e942b6f1b07583e4eb0a8d324d418954fc6af913d36db7c05a5a0"}, + {file = "httptools-0.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b0bb634338334385351a1600a73e558ce619af390c2b38386206ac6a27fecfc"}, + {file = "httptools-0.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d9ceb2c957320def533671fc9c715a80c47025139c8d1f3797477decbc6edd2"}, + {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4f0f8271c0a4db459f9dc807acd0eadd4839934a4b9b892f6f160e94da309837"}, + {file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6a4f5ccead6d18ec072ac0b84420e95d27c1cdf5c9f1bc8fbd8daf86bd94f43d"}, + {file = "httptools-0.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:5cceac09f164bcba55c0500a18fe3c47df29b62353198e4f37bbcc5d591172c3"}, + {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:75c8022dca7935cba14741a42744eee13ba05db00b27a4b940f0d646bd4d56d0"}, + {file = "httptools-0.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:48ed8129cd9a0d62cf4d1575fcf90fb37e3ff7d5654d3a5814eb3d55f36478c2"}, + {file = "httptools-0.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f58e335a1402fb5a650e271e8c2d03cfa7cea46ae124649346d17bd30d59c90"}, + {file = "httptools-0.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93ad80d7176aa5788902f207a4e79885f0576134695dfb0fefc15b7a4648d503"}, + {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9bb68d3a085c2174c2477eb3ffe84ae9fb4fde8792edb7bcd09a1d8467e30a84"}, + {file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b512aa728bc02354e5ac086ce76c3ce635b62f5fbc32ab7082b5e582d27867bb"}, + {file = "httptools-0.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:97662ce7fb196c785344d00d638fc9ad69e18ee4bfb4000b35a52efe5adcc949"}, + {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8e216a038d2d52ea13fdd9b9c9c7459fb80d78302b257828285eca1c773b99b3"}, + {file = "httptools-0.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3e802e0b2378ade99cd666b5bffb8b2a7cc8f3d28988685dc300469ea8dd86cb"}, + {file = "httptools-0.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bd3e488b447046e386a30f07af05f9b38d3d368d1f7b4d8f7e10af85393db97"}, + {file = "httptools-0.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe467eb086d80217b7584e61313ebadc8d187a4d95bb62031b7bab4b205c3ba3"}, + {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3c3b214ce057c54675b00108ac42bacf2ab8f85c58e3f324a4e963bbc46424f4"}, + {file = "httptools-0.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8ae5b97f690badd2ca27cbf668494ee1b6d34cf1c464271ef7bfa9ca6b83ffaf"}, + {file = "httptools-0.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:405784577ba6540fa7d6ff49e37daf104e04f4b4ff2d1ac0469eaa6a20fde084"}, + {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:95fb92dd3649f9cb139e9c56604cc2d7c7bf0fc2e7c8d7fbd58f96e35eddd2a3"}, + {file = "httptools-0.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dcbab042cc3ef272adc11220517278519adf8f53fd3056d0e68f0a6f891ba94e"}, + {file = "httptools-0.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf2372e98406efb42e93bfe10f2948e467edfd792b015f1b4ecd897903d3e8d"}, + {file = "httptools-0.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:678fcbae74477a17d103b7cae78b74800d795d702083867ce160fc202104d0da"}, + {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e0b281cf5a125c35f7f6722b65d8542d2e57331be573e9e88bc8b0115c4a7a81"}, + {file = "httptools-0.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:95658c342529bba4e1d3d2b1a874db16c7cca435e8827422154c9da76ac4e13a"}, + {file = "httptools-0.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ebaec1bf683e4bf5e9fbb49b8cc36da482033596a415b3e4ebab5a4c0d7ec5e"}, + {file = "httptools-0.6.1.tar.gz", hash = "sha256:c6e26c30455600b95d94b1b836085138e82f177351454ee841c148f93a9bad5a"}, +] + +[package.extras] +test = ["Cython (>=0.29.24,<0.30.0)"] [[package]] name = "httpx" -version = "0.24.1" +version = "0.27.0" description = "The next generation HTTP client." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "httpx-0.24.1-py3-none-any.whl", hash = "sha256:06781eb9ac53cde990577af654bd990a4949de37a28bdb4a230d434f3a30b9bd"}, - {file = "httpx-0.24.1.tar.gz", hash = "sha256:5853a43053df830c20f8110c5e69fe44d035d850b2dfe795e196f00fdb774bdd"}, + {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, + {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, ] [package.dependencies] +anyio = "*" certifi = "*" -httpcore = ">=0.15.0,<0.18.0" +httpcore = "==1.*" idna = "*" sniffio = "*" @@ -1423,48 +1333,68 @@ http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] [[package]] -name = "identify" -version = "2.5.26" -description = "File identification library for Python" -optional = false -python-versions = ">=3.8" +name = "huggingface-hub" +version = "0.23.2" +description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" +optional = true +python-versions = ">=3.8.0" files = [ - {file = "identify-2.5.26-py2.py3-none-any.whl", hash = "sha256:c22a8ead0d4ca11f1edd6c9418c3220669b3b7533ada0a0ffa6cc0ef85cf9b54"}, - {file = "identify-2.5.26.tar.gz", hash = "sha256:7243800bce2f58404ed41b7c002e53d4d22bcf3ae1b7900c2d7aefd95394bf7f"}, + {file = "huggingface_hub-0.23.2-py3-none-any.whl", hash = "sha256:48727a16e704d409c4bb5913613308499664f22a99743435dc3a13b23c485827"}, + {file = "huggingface_hub-0.23.2.tar.gz", hash = "sha256:f6829b62d5fdecb452a76fdbec620cba4c1573655a8d710c1df71735fd9edbd2"}, ] +[package.dependencies] +filelock = "*" +fsspec = ">=2023.5.0" +packaging = ">=20.9" +pyyaml = ">=5.1" +requests = "*" +tqdm = ">=4.42.1" +typing-extensions = ">=3.7.4.3" + [package.extras] -license = ["ukkonen"] +all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +cli = ["InquirerPy (==0.3.4)"] +dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"] +hf-transfer = ["hf-transfer (>=0.1.4)"] +inference = ["aiohttp", "minijinja (>=1.0)"] +quality = ["mypy (==1.5.1)", "ruff (>=0.3.0)"] +tensorflow = ["graphviz", "pydot", "tensorflow"] +tensorflow-testing = ["keras (<3.0)", "tensorflow"] +testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] +torch = ["safetensors", "torch"] +typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"] [[package]] name = "idna" -version = "3.4" +version = "3.7" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, + {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, + {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, ] [[package]] name = "importlib-metadata" -version = "6.8.0" +version = "7.1.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, - {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, + {file = "importlib_metadata-7.1.0-py3-none-any.whl", hash = "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570"}, + {file = "importlib_metadata-7.1.0.tar.gz", hash = "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2"}, ] [package.dependencies] zipp = ">=0.5" [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] [[package]] name = "iniconfig" @@ -1479,42 +1409,55 @@ files = [ [[package]] name = "ipython" -version = "8.12.2" +version = "8.24.0" description = "IPython: Productive Interactive Computing" optional = true -python-versions = ">=3.8" +python-versions = ">=3.10" files = [ - {file = "ipython-8.12.2-py3-none-any.whl", hash = "sha256:ea8801f15dfe4ffb76dea1b09b847430ffd70d827b41735c64a0638a04103bfc"}, - {file = "ipython-8.12.2.tar.gz", hash = "sha256:c7b80eb7f5a855a88efc971fda506ff7a91c280b42cdae26643e0f601ea281ea"}, + {file = "ipython-8.24.0-py3-none-any.whl", hash = "sha256:d7bf2f6c4314984e3e02393213bab8703cf163ede39672ce5918c51fe253a2a3"}, + {file = "ipython-8.24.0.tar.gz", hash = "sha256:010db3f8a728a578bb641fdd06c063b9fb8e96a9464c63aec6310fbcb5e80501"}, ] [package.dependencies] -appnope = {version = "*", markers = "sys_platform == \"darwin\""} -backcall = "*" colorama = {version = "*", markers = "sys_platform == \"win32\""} decorator = "*" +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} jedi = ">=0.16" matplotlib-inline = "*" -pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} -pickleshare = "*" -prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\""} +prompt-toolkit = ">=3.0.41,<3.1.0" pygments = ">=2.4.0" stack-data = "*" -traitlets = ">=5" -typing-extensions = {version = "*", markers = "python_version < \"3.10\""} +traitlets = ">=5.13.0" +typing-extensions = {version = ">=4.6", markers = "python_version < \"3.12\""} [package.extras] -all = ["black", "curio", "docrepr", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.21)", "pandas", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +all = ["ipython[black,doc,kernel,matplotlib,nbconvert,nbformat,notebook,parallel,qtconsole]", "ipython[test,test-extra]"] black = ["black"] -doc = ["docrepr", "ipykernel", "matplotlib", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "stack-data", "typing-extensions"] kernel = ["ipykernel"] +matplotlib = ["matplotlib"] nbconvert = ["nbconvert"] nbformat = ["nbformat"] notebook = ["ipywidgets", "notebook"] parallel = ["ipyparallel"] qtconsole = ["qtconsole"] -test = ["pytest (<7.1)", "pytest-asyncio", "testpath"] -test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"] +test = ["pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "ipython[test]", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "trio"] + +[[package]] +name = "isort" +version = "5.13.2" +description = "A Python utility / library to sort Python imports." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, + {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, +] + +[package.extras] +colors = ["colorama (>=0.4.6)"] [[package]] name = "janus" @@ -1532,13 +1475,13 @@ typing-extensions = ">=3.7.4.3" [[package]] name = "jedi" -version = "0.19.0" +version = "0.19.1" description = "An autocompletion tool for Python that can be used for text editors." optional = true python-versions = ">=3.6" files = [ - {file = "jedi-0.19.0-py2.py3-none-any.whl", hash = "sha256:cb8ce23fbccff0025e9386b5cf85e892f94c9b822378f8da49970471335ac64e"}, - {file = "jedi-0.19.0.tar.gz", hash = "sha256:bcf9894f1753969cbac8022a8c2eaee06bfa3724e4192470aaffe7eb6272b0c4"}, + {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"}, + {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"}, ] [package.dependencies] @@ -1547,17 +1490,17 @@ parso = ">=0.8.3,<0.9.0" [package.extras] docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] -testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] +testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] [[package]] name = "jinja2" -version = "3.1.2" +version = "3.1.4" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" files = [ - {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, - {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, ] [package.dependencies] @@ -1567,32 +1510,91 @@ MarkupSafe = ">=2.0" i18n = ["Babel (>=2.7)"] [[package]] -name = "jmespath" -version = "1.0.1" -description = "JSON Matching Expressions" -optional = false -python-versions = ">=3.7" +name = "jiter" +version = "0.4.0" +description = "Fast iterable JSON parser." +optional = true +python-versions = ">=3.8" files = [ - {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, - {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, + {file = "jiter-0.4.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:4aa6226d82a4a4505078c0bd5947bad65399635fc5cd4b226512e41753624edf"}, + {file = "jiter-0.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:947111ac906740a948e7b63799481acd3d5ef666ccb178d146e25718640b7408"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69572ffb4e84ae289a7422b9af4ea123cae2ce0772228859b37d4b26b4bc92ea"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ba6046cbb5d1baa5a781b846f7e5438596a332f249a857d63f86ef5d1d9563b0"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4f346e54602782e66d07df0d1c7389384fd93680052ed6170da2c6dc758409e"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:49110ce693f07e97d61089d894cea05a0b9894d5ccc6ac6fc583028726c8c8af"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e358df6fd129f3a4e087539f086355ad0107e5da16dbc8bc857d94222eaeed5"}, + {file = "jiter-0.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7eb852ca39a48f3c049def56f0d1771b32e948e4f429a782d14ef4cc64cfd26e"}, + {file = "jiter-0.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:44dc045decb2545bffe2da04ea4c36d9438d3f3d49fc47ed423ea75c352b712e"}, + {file = "jiter-0.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:413adb15372ac63db04373240f40925788e4282c997eeafc2040530049a0a599"}, + {file = "jiter-0.4.0-cp310-none-win32.whl", hash = "sha256:0b48ea71673a97b897e4b94bbc871e62495a5a85f836c9f90712a4c70aa3ef7e"}, + {file = "jiter-0.4.0-cp310-none-win_amd64.whl", hash = "sha256:6a1c84b44afafaf0ba6223679cf17af664b889da14da31d8af3595fd977d96fa"}, + {file = "jiter-0.4.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b2cc498345fa37ca23fbc20271a553aa46e6eb00924600f49b7dc4b2aa8952ee"}, + {file = "jiter-0.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:69f7221ac09ab421abf04f89942026868297c568133998fb181bcf435760cbf3"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef7d01c52f3e5a56ae73af36bd13797dd1a56711eb522748e5e84d15425b3f10"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:39be97d5ce0c4d0dae28c23c03a0af0501a725589427e99763f99c42e18aa402"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eac2ed1ec1e577b92b7ea2d4e6de8aec0c1164defd8af8affdc8ec0f0ec2904a"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6258837d184c92c9cb91c983c310ad7269d41afb49d34f00ca9246e073943a03"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:123c2a77b066bf17a4d021e238e8351058cfa56b90ac04f2522d120dc64ea055"}, + {file = "jiter-0.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2df939f792c7a40e55f36700417db551b9f6b84d348990fa0f2c608adeb1f11b"}, + {file = "jiter-0.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cb1b09b16d40cf9ba1d11ba11e5b96ad29286a6a1c4ad5e6a2aef5e352a89f5d"}, + {file = "jiter-0.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0efb4208889ebdbf933bf08dbcbc16e64ffd34c8e2b28044ee142789a9dc3a67"}, + {file = "jiter-0.4.0-cp311-none-win32.whl", hash = "sha256:20545ac1b68e7e5b066a1e8347840c9cebdd02ace65faae2e655fc02ec5c915c"}, + {file = "jiter-0.4.0-cp311-none-win_amd64.whl", hash = "sha256:6b300f9887c8e4431cd03a974ea3e4f9958885636003c3864220a9b2d2f8462b"}, + {file = "jiter-0.4.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:923432a0563bbae404ff25bb010e348514a69bfab979f2f8119b23b625dbf6d9"}, + {file = "jiter-0.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab8bb0ec8b97cec4422dc8b37b525442d969244488c805b834609ab0ccd788e2"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b857adb127b9c533907226791eafa79c5038c3eb5a477984994bf7c4715ba518"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2609cc0d1d8d470e921ff9a604afeb4c701bbe13e00bd9834d5aa6e7ea732a9b"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d39e99f8b7df46a119b6f84321f6ba01f16fa46abfa765d44c05c486d8e66829"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:56de8b518ebfe76a70f856741f6de248ce396c50a87acef827b6e8388e3a502d"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:488b7e777be47f67ce1a1f8f8eb907f9bbd81af5c03784a9bab09d025c250233"}, + {file = "jiter-0.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7ea35e0ecbb5dadd457855eb980dcc548c14cf5341bcd22a43814cb56f2bcc79"}, + {file = "jiter-0.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e1a9e9ee69c80b63951c93226b68d0e955953f64fe758bad2afe7ef7f9016af9"}, + {file = "jiter-0.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:78e2f3cc2a32a21d43ccc5afcf66f5d17e827ccc4e6d21c0b353bdad2c7dcc9c"}, + {file = "jiter-0.4.0-cp312-none-win32.whl", hash = "sha256:eeaa7a2b47a99f4ebbb4142bb58b95617e09f24c87570f6a57d2770687c9ddbe"}, + {file = "jiter-0.4.0-cp312-none-win_amd64.whl", hash = "sha256:8d4a78b385b93ff59a67215d26000fcb4789a388fca3730d1b60fab17fc81e3c"}, + {file = "jiter-0.4.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:ebf20a3fac1089ce26963bf04140da0f803d55332ec69d59c5a87cf1a87d29c4"}, + {file = "jiter-0.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d62244ffc6a168187452277adeefb7b2c30170689c6bf543a51e98e8c17ddab7"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40b2cde77446a41cec595739fd168be87edff2428eaf7c3438231224dd0ab7a5"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e51fc0a22021ec8905b9b00a2f7d25756f2ff7a653e35a790a2067ae126b51f6"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a56e6f980b89d7cfe5c43811dcf52d6f37b319428a4540511235dafda9ea7808"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0fec16adab8d3d3d6d74e3711a1f380836ebeab2a20e3f88cfe2ec5094d8b84"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19e3de515801c954e8f1dc1f575282a4a86df9e782d4993ea1ed2be9a8dedaa0"}, + {file = "jiter-0.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17e0ad8abf0bb04d81810eaeaab35d2c99b5da11fcd1058e0a389607ff6503b0"}, + {file = "jiter-0.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8dc0132b728f3b3e90ff0d1874504cd49c78f3553bf3745168a7fc0b4cf674e1"}, + {file = "jiter-0.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:81a883104aa96e494d3d28eaf7070780d03ecee8ccfdfaf7e4899710340c47f1"}, + {file = "jiter-0.4.0-cp38-none-win32.whl", hash = "sha256:a044c53ab1aaa4af624ac9574181b5bad8e260aea7e03104738156511433deba"}, + {file = "jiter-0.4.0-cp38-none-win_amd64.whl", hash = "sha256:d920035c869053e3d9a0b3ff94384d16a8ef5fde3dea55f97bd29916f6e27554"}, + {file = "jiter-0.4.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:091e978f4e586a2f1c69bf940d45f4e6a23455877172a0ab7d6de04a3b119299"}, + {file = "jiter-0.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:79134b2d601309bcbe3304a262d7d228ad61d53c80883231c637773000a6d683"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c471473e0b05058b5d729ff04271b6d45a575ac8bd9948563268c734b380ac7e"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb84b8930da8b32b0b1fdff9817e2c4b47e8981b5647ad11c4975403416e4112"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f2805e28941751ebfe0948596a64cde4cfb9b84bea5282affd020063e659c96"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:42ef59f9e513bf081a8b5c5578933ea9c3a63e559e6e3501a3e72edcd456ff5e"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ae12e3906f9e565120ab569de261b738e3a1ec50c40e30c67499e4f893e9a8c"}, + {file = "jiter-0.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:264dc1324f45a793bc89af4f653225229eb17bca9ec7107dce6c8fb4fe68d20f"}, + {file = "jiter-0.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9a1c172ec47d846e25881dfbd52438ddb690da4ea04d185e477abd3db6c32f8a"}, + {file = "jiter-0.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ccde31d0bc114aedad0dbd71b7f63ba0f0eecd7ec9ae1926a0ca01c1eb2854e7"}, + {file = "jiter-0.4.0-cp39-none-win32.whl", hash = "sha256:13139b05792fbc13a0f9a5b4c89823ea0874141decae1b8f693f12bb1d28e061"}, + {file = "jiter-0.4.0-cp39-none-win_amd64.whl", hash = "sha256:3a729b2631c6d5551a41069697415fee9659c3eadc9ab87369376ba51930cd00"}, + {file = "jiter-0.4.0.tar.gz", hash = "sha256:68203e02e0419bc3eca717c580c2d8f615aeee1150e2a1fb68d6600a7e52a37c"}, ] [[package]] name = "joblib" -version = "1.3.2" +version = "1.4.2" description = "Lightweight pipelining with Python functions" -optional = false -python-versions = ">=3.7" +optional = true +python-versions = ">=3.8" files = [ - {file = "joblib-1.3.2-py3-none-any.whl", hash = "sha256:ef4331c65f239985f3f2220ecc87db222f08fd22097a3dd5698f693875f8cbb9"}, - {file = "joblib-1.3.2.tar.gz", hash = "sha256:92f865e621e17784e7955080b6d042489e3b8e294949cc44c6eac304f59772b1"}, + {file = "joblib-1.4.2-py3-none-any.whl", hash = "sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6"}, + {file = "joblib-1.4.2.tar.gz", hash = "sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e"}, ] [[package]] name = "jsonpatch" version = "1.33" description = "Apply JSON-Patches (RFC 6902)" -optional = false +optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, @@ -1606,32 +1608,65 @@ jsonpointer = ">=1.9" name = "jsonpointer" version = "2.4" description = "Identify specific nodes in a JSON document (RFC 6901)" -optional = false +optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, ] +[[package]] +name = "jsonschema" +version = "4.22.0" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema-4.22.0-py3-none-any.whl", hash = "sha256:ff4cfd6b1367a40e7bc6411caec72effadd3db0bbe5017de188f2d6108335802"}, + {file = "jsonschema-4.22.0.tar.gz", hash = "sha256:5b22d434a45935119af990552c862e5d6d564e8f6601206b305a61fdf661a2b7"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] + +[[package]] +name = "jsonschema-specifications" +version = "2023.12.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, + {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, +] + +[package.dependencies] +referencing = ">=0.31.0" + [[package]] name = "langchain" -version = "0.1.4" +version = "0.2.1" description = "Building applications with LLMs through composability" -optional = false -python-versions = ">=3.8.1,<4.0" +optional = true +python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain-0.1.4-py3-none-any.whl", hash = "sha256:6befdd6221f5f326092e31a3c19efdc7ce3d7d1f2e2cab065141071451730ed7"}, - {file = "langchain-0.1.4.tar.gz", hash = "sha256:8767a9461e2b717ce9a35b1fa20659de89ea86ba9c2a4ff516e05d47ab2d195d"}, + {file = "langchain-0.2.1-py3-none-any.whl", hash = "sha256:3e13bf97c5717bce2c281f5117e8778823e8ccf62d949e73d3869448962b1c97"}, + {file = "langchain-0.2.1.tar.gz", hash = "sha256:5758a315e1ac92eb26dafec5ad0fafa03cafa686aba197d5bb0b1dd28cc03ebe"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""} -dataclasses-json = ">=0.5.7,<0.7" -jsonpatch = ">=1.33,<2.0" -langchain-community = ">=0.0.14,<0.1" -langchain-core = ">=0.1.16,<0.2" -langsmith = ">=0.0.83,<0.1" +langchain-core = ">=0.2.0,<0.3.0" +langchain-text-splitters = ">=0.2.0,<0.3.0" +langsmith = ">=0.1.17,<0.2.0" numpy = ">=1,<2" pydantic = ">=1,<3" PyYAML = ">=5.3" @@ -1640,35 +1675,36 @@ SQLAlchemy = ">=1.4,<3" tenacity = ">=8.1.0,<9.0.0" [package.extras] -azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-textanalytics (>=5.3.0,<6.0.0)", "azure-ai-vision (>=0.11.1b1,<0.12.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b8)", "openai (<2)"] +azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-textanalytics (>=5.3.0,<6.0.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b8)", "openai (<2)"] clarifai = ["clarifai (>=9.1.0)"] cli = ["typer (>=0.9.0,<0.10.0)"] -cohere = ["cohere (>=4,<5)"] +cohere = ["cohere (>=4,<6)"] docarray = ["docarray[hnswlib] (>=0.32.0,<0.33.0)"] embeddings = ["sentence-transformers (>=2,<3)"] -extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<5)", "couchbase (>=4.1.9,<5.0.0)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "langchain-openai (>=0.0.2,<0.1)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] +extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<6)", "couchbase (>=4.1.9,<5.0.0)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "langchain-openai (>=0.1,<0.2)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] javascript = ["esprima (>=4.0.1,<5.0.0)"] -llms = ["clarifai (>=9.1.0)", "cohere (>=4,<5)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (<2)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] -openai = ["openai (<2)", "tiktoken (>=0.3.2,<0.6.0)"] +llms = ["clarifai (>=9.1.0)", "cohere (>=4,<6)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (<2)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] +openai = ["openai (<2)", "tiktoken (>=0.7,<1.0)"] qdrant = ["qdrant-client (>=1.3.1,<2.0.0)"] text-helpers = ["chardet (>=5.1.0,<6.0.0)"] [[package]] name = "langchain-community" -version = "0.0.16" +version = "0.2.1" description = "Community contributed LangChain integrations." -optional = false -python-versions = ">=3.8.1,<4.0" +optional = true +python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_community-0.0.16-py3-none-any.whl", hash = "sha256:0f1dfc1a6205ce8d39931d3515974a208a9f69c16157c649f83490a7cc830b73"}, - {file = "langchain_community-0.0.16.tar.gz", hash = "sha256:c06512a93013a06fba7679cd5a1254ff8b927cddd2d1fbe0cc444bf7bbdf0b8c"}, + {file = "langchain_community-0.2.1-py3-none-any.whl", hash = "sha256:b834e2c5ded6903b839fcaf566eee90a0ffae53405a0f7748202725e701d39cd"}, + {file = "langchain_community-0.2.1.tar.gz", hash = "sha256:079942e8f15da975769ccaae19042b7bba5481c42020bbbd7d8cad73a9393261"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" dataclasses-json = ">=0.5.7,<0.7" -langchain-core = ">=0.1.16,<0.2" -langsmith = ">=0.0.83,<0.1" +langchain = ">=0.2.0,<0.3.0" +langchain-core = ">=0.2.0,<0.3.0" +langsmith = ">=0.1.0,<0.2.0" numpy = ">=1,<2" PyYAML = ">=5.3" requests = ">=2,<3" @@ -1677,145 +1713,223 @@ tenacity = ">=8.1.0,<9.0.0" [package.extras] cli = ["typer (>=0.9.0,<0.10.0)"] -extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<5)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)", "zhipuai (>=1.0.7,<2.0.0)"] +extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "azure-identity (>=1.15.0,<2.0.0)", "azure-search-documents (==11.4.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.6,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cloudpathlib (>=0.18,<0.19)", "cloudpickle (>=2.0.0)", "cohere (>=4,<5)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "friendli-client (>=1.2.4,<2.0.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "httpx (>=0.24.1,<0.25.0)", "httpx-sse (>=0.4.0,<0.5.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "nvidia-riva-client (>=2.14.0,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "oracledb (>=2.2.0,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "premai (>=0.3.25,<0.4.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pyjwt (>=2.8.0,<3.0.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "tidb-vector (>=0.0.3,<1.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "tree-sitter (>=0.20.2,<0.21.0)", "tree-sitter-languages (>=1.8.0,<2.0.0)", "upstash-redis (>=0.15.0,<0.16.0)", "vdms (>=0.0.20,<0.0.21)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] [[package]] name = "langchain-core" -version = "0.1.17" +version = "0.2.3" description = "Building applications with LLMs through composability" -optional = false -python-versions = ">=3.8.1,<4.0" +optional = true +python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_core-0.1.17-py3-none-any.whl", hash = "sha256:026155cf97867bde410ab1834799ab4c5ba64c39380f2a4328bcf9c78623ca64"}, - {file = "langchain_core-0.1.17.tar.gz", hash = "sha256:59016e457cd6a1708d83a3a454acc97cf02c2a2c3af95626d13f83894fd4e777"}, + {file = "langchain_core-0.2.3-py3-none-any.whl", hash = "sha256:22189b5a3a30bfd65eb995f95e627f7c2c3acb322feb89f5f5f2fb7df21833a7"}, + {file = "langchain_core-0.2.3.tar.gz", hash = "sha256:fbc75a64b9c0b7655d96ca57a707df1e6c09efc1539c36adbd73260612549810"}, ] [package.dependencies] -anyio = ">=3,<5" jsonpatch = ">=1.33,<2.0" -langsmith = ">=0.0.83,<0.1" +langsmith = ">=0.1.65,<0.2.0" packaging = ">=23.2,<24.0" pydantic = ">=1,<3" PyYAML = ">=5.3" -requests = ">=2,<3" tenacity = ">=8.1.0,<9.0.0" [package.extras] extended-testing = ["jinja2 (>=3,<4)"] +[[package]] +name = "langchain-text-splitters" +version = "0.2.0" +description = "LangChain text splitting utilities" +optional = true +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_text_splitters-0.2.0-py3-none-any.whl", hash = "sha256:7b4c6a45f8471630a882b321e138329b6897102a5bc62f4c12be1c0b05bb9199"}, + {file = "langchain_text_splitters-0.2.0.tar.gz", hash = "sha256:b32ab4f7397f7d42c1fa3283fefc2547ba356bd63a68ee9092865e5ad83c82f9"}, +] + +[package.dependencies] +langchain-core = ">=0.2.0,<0.3.0" + +[package.extras] +extended-testing = ["beautifulsoup4 (>=4.12.3,<5.0.0)", "lxml (>=4.9.3,<6.0)"] + [[package]] name = "langsmith" -version = "0.0.85" +version = "0.1.65" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." -optional = false -python-versions = ">=3.8.1,<4.0" +optional = true +python-versions = "<4.0,>=3.8.1" files = [ - {file = "langsmith-0.0.85-py3-none-any.whl", hash = "sha256:9d0ccbcda7b69c83828060603a51bb4319e43b8dc807fbd90b6355f8ec709500"}, - {file = "langsmith-0.0.85.tar.gz", hash = "sha256:fefc631fc30d836b54d4e3f99961c41aea497633898b8f09e305b6c7216c2c54"}, + {file = "langsmith-0.1.65-py3-none-any.whl", hash = "sha256:ab4487029240e69cca30da1065f1e9138e5a7ca2bbe8c697f0bd7d5839f71cf7"}, + {file = "langsmith-0.1.65.tar.gz", hash = "sha256:d3c2eb2391478bd79989f02652cf66e29a7959d677614b6993a47cef43f7f43b"}, ] [package.dependencies] +orjson = ">=3.9.14,<4.0.0" pydantic = ">=1,<3" requests = ">=2,<3" +[[package]] +name = "loguru" +version = "0.7.2" +description = "Python logging made (stupidly) simple" +optional = false +python-versions = ">=3.5" +files = [ + {file = "loguru-0.7.2-py3-none-any.whl", hash = "sha256:003d71e3d3ed35f0f8984898359d65b79e5b21943f78af86aa5491210429b8eb"}, + {file = "loguru-0.7.2.tar.gz", hash = "sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"}, +] + +[package.dependencies] +colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} +win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} + +[package.extras] +dev = ["Sphinx (==7.2.5)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.2.2)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.4.1)", "mypy (==v1.5.1)", "pre-commit (==3.4.0)", "pytest (==6.1.2)", "pytest (==7.4.0)", "pytest-cov (==2.12.1)", "pytest-cov (==4.1.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.0.0)", "sphinx-autobuild (==2021.3.14)", "sphinx-rtd-theme (==1.3.0)", "tox (==3.27.1)", "tox (==4.11.0)"] + +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.8" +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + [[package]] name = "markupsafe" -version = "2.1.3" +version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.7" files = [ - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, - {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, ] [[package]] name = "marshmallow" -version = "3.20.1" +version = "3.21.2" description = "A lightweight library for converting complex datatypes to and from native Python datatypes." -optional = false +optional = true python-versions = ">=3.8" files = [ - {file = "marshmallow-3.20.1-py3-none-any.whl", hash = "sha256:684939db93e80ad3561392f47be0230743131560a41c5110684c16e21ade0a5c"}, - {file = "marshmallow-3.20.1.tar.gz", hash = "sha256:5d2371bbe42000f2b3fb5eaa065224df7d8f8597bc19a1bbfa5bfe7fba8da889"}, + {file = "marshmallow-3.21.2-py3-none-any.whl", hash = "sha256:70b54a6282f4704d12c0a41599682c5c5450e843b9ec406308653b47c59648a1"}, + {file = "marshmallow-3.21.2.tar.gz", hash = "sha256:82408deadd8b33d56338d2182d455db632c6313aa2af61916672146bb32edc56"}, ] [package.dependencies] packaging = ">=17.0" [package.extras] -dev = ["flake8 (==6.0.0)", "flake8-bugbear (==23.7.10)", "mypy (==1.4.1)", "pre-commit (>=2.4,<4.0)", "pytest", "pytz", "simplejson", "tox"] -docs = ["alabaster (==0.7.13)", "autodocsumm (==0.2.11)", "sphinx (==7.0.1)", "sphinx-issues (==3.0.1)", "sphinx-version-warning (==1.1.2)"] -lint = ["flake8 (==6.0.0)", "flake8-bugbear (==23.7.10)", "mypy (==1.4.1)", "pre-commit (>=2.4,<4.0)"] +dev = ["marshmallow[tests]", "pre-commit (>=3.5,<4.0)", "tox"] +docs = ["alabaster (==0.7.16)", "autodocsumm (==0.2.12)", "sphinx (==7.3.7)", "sphinx-issues (==4.1.0)", "sphinx-version-warning (==1.1.2)"] tests = ["pytest", "pytz", "simplejson"] [[package]] name = "matplotlib-inline" -version = "0.1.6" +version = "0.1.7" description = "Inline Matplotlib backend for Jupyter" optional = true -python-versions = ">=3.5" +python-versions = ">=3.8" files = [ - {file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"}, - {file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"}, + {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"}, + {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"}, ] [package.dependencies] traitlets = "*" +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + [[package]] name = "miniaudio" version = "1.59" description = "python bindings for the miniaudio library and its decoders (mp3, flac, ogg vorbis, wav)" -optional = false +optional = true python-versions = "*" files = [ {file = "miniaudio-1.59-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:028d7e8e6d99441340c0bfb60660db7bd5789cae7c95fa599d830344901d6d72"}, @@ -1877,121 +1991,137 @@ cffi = ">=1.12.0" [[package]] name = "multidict" -version = "6.0.4" +version = "6.0.5" description = "multidict implementation" optional = false python-versions = ">=3.7" files = [ - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, - {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, - {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, - {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, - {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, - {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, - {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, - {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, - {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, - {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, - {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, - {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, - {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, + {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, + {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, + {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, + {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, + {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, + {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, + {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, + {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, + {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, + {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, + {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, + {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, + {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, + {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, + {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, ] [[package]] name = "mypy" -version = "1.8.0" +version = "1.10.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3"}, - {file = "mypy-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4"}, - {file = "mypy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d"}, - {file = "mypy-1.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9"}, - {file = "mypy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410"}, - {file = "mypy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae"}, - {file = "mypy-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3"}, - {file = "mypy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817"}, - {file = "mypy-1.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d"}, - {file = "mypy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835"}, - {file = "mypy-1.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd"}, - {file = "mypy-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55"}, - {file = "mypy-1.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218"}, - {file = "mypy-1.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3"}, - {file = "mypy-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e"}, - {file = "mypy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:028cf9f2cae89e202d7b6593cd98db6759379f17a319b5faf4f9978d7084cdc6"}, - {file = "mypy-1.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4e6d97288757e1ddba10dd9549ac27982e3e74a49d8d0179fc14d4365c7add66"}, - {file = "mypy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f1478736fcebb90f97e40aff11a5f253af890c845ee0c850fe80aa060a267c6"}, - {file = "mypy-1.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42419861b43e6962a649068a61f4a4839205a3ef525b858377a960b9e2de6e0d"}, - {file = "mypy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:2b5b6c721bd4aabaadead3a5e6fa85c11c6c795e0c81a7215776ef8afc66de02"}, - {file = "mypy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8"}, - {file = "mypy-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259"}, - {file = "mypy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b"}, - {file = "mypy-1.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592"}, - {file = "mypy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a"}, - {file = "mypy-1.8.0-py3-none-any.whl", hash = "sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d"}, - {file = "mypy-1.8.0.tar.gz", hash = "sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07"}, + {file = "mypy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da1cbf08fb3b851ab3b9523a884c232774008267b1f83371ace57f412fe308c2"}, + {file = "mypy-1.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:12b6bfc1b1a66095ab413160a6e520e1dc076a28f3e22f7fb25ba3b000b4ef99"}, + {file = "mypy-1.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e36fb078cce9904c7989b9693e41cb9711e0600139ce3970c6ef814b6ebc2b2"}, + {file = "mypy-1.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2b0695d605ddcd3eb2f736cd8b4e388288c21e7de85001e9f85df9187f2b50f9"}, + {file = "mypy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:cd777b780312ddb135bceb9bc8722a73ec95e042f911cc279e2ec3c667076051"}, + {file = "mypy-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3be66771aa5c97602f382230165b856c231d1277c511c9a8dd058be4784472e1"}, + {file = "mypy-1.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8b2cbaca148d0754a54d44121b5825ae71868c7592a53b7292eeb0f3fdae95ee"}, + {file = "mypy-1.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ec404a7cbe9fc0e92cb0e67f55ce0c025014e26d33e54d9e506a0f2d07fe5de"}, + {file = "mypy-1.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e22e1527dc3d4aa94311d246b59e47f6455b8729f4968765ac1eacf9a4760bc7"}, + {file = "mypy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:a87dbfa85971e8d59c9cc1fcf534efe664d8949e4c0b6b44e8ca548e746a8d53"}, + {file = "mypy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a781f6ad4bab20eef8b65174a57e5203f4be627b46291f4589879bf4e257b97b"}, + {file = "mypy-1.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b808e12113505b97d9023b0b5e0c0705a90571c6feefc6f215c1df9381256e30"}, + {file = "mypy-1.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f55583b12156c399dce2df7d16f8a5095291354f1e839c252ec6c0611e86e2e"}, + {file = "mypy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cf18f9d0efa1b16478c4c129eabec36148032575391095f73cae2e722fcf9d5"}, + {file = "mypy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:bc6ac273b23c6b82da3bb25f4136c4fd42665f17f2cd850771cb600bdd2ebeda"}, + {file = "mypy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9fd50226364cd2737351c79807775136b0abe084433b55b2e29181a4c3c878c0"}, + {file = "mypy-1.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f90cff89eea89273727d8783fef5d4a934be2fdca11b47def50cf5d311aff727"}, + {file = "mypy-1.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fcfc70599efde5c67862a07a1aaf50e55bce629ace26bb19dc17cece5dd31ca4"}, + {file = "mypy-1.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:075cbf81f3e134eadaf247de187bd604748171d6b79736fa9b6c9685b4083061"}, + {file = "mypy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:3f298531bca95ff615b6e9f2fc0333aae27fa48052903a0ac90215021cdcfa4f"}, + {file = "mypy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa7ef5244615a2523b56c034becde4e9e3f9b034854c93639adb667ec9ec2976"}, + {file = "mypy-1.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3236a4c8f535a0631f85f5fcdffba71c7feeef76a6002fcba7c1a8e57c8be1ec"}, + {file = "mypy-1.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a2b5cdbb5dd35aa08ea9114436e0d79aceb2f38e32c21684dcf8e24e1e92821"}, + {file = "mypy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92f93b21c0fe73dc00abf91022234c79d793318b8a96faac147cd579c1671746"}, + {file = "mypy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:28d0e038361b45f099cc086d9dd99c15ff14d0188f44ac883010e172ce86c38a"}, + {file = "mypy-1.10.0-py3-none-any.whl", hash = "sha256:f8c083976eb530019175aabadb60921e73b4f45736760826aa1689dda8208aee"}, + {file = "mypy-1.10.0.tar.gz", hash = "sha256:3d087fcbec056c4ee34974da493a826ce316947485cef3901f511848e687c131"}, ] [package.dependencies] @@ -2020,7 +2150,7 @@ files = [ name = "nltk" version = "3.8.1" description = "Natural Language Toolkit" -optional = false +optional = true python-versions = ">=3.7" files = [ {file = "nltk-3.8.1-py3-none-any.whl", hash = "sha256:fd5c9109f976fa86bcadba8f91e47f5e9293bd034474752e92a520f81c93dda5"}, @@ -2041,139 +2171,172 @@ plot = ["matplotlib"] tgrep = ["pyparsing"] twitter = ["twython"] -[[package]] -name = "nodeenv" -version = "1.8.0" -description = "Node.js virtual environment builder" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" -files = [ - {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, - {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, -] - -[package.dependencies] -setuptools = "*" - [[package]] name = "numpy" -version = "1.24.4" +version = "1.26.4" description = "Fundamental package for array computing in Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64"}, - {file = "numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1"}, - {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4"}, - {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6"}, - {file = "numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc"}, - {file = "numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e"}, - {file = "numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810"}, - {file = "numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254"}, - {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7"}, - {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5"}, - {file = "numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d"}, - {file = "numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694"}, - {file = "numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61"}, - {file = "numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f"}, - {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e"}, - {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc"}, - {file = "numpy-1.24.4-cp38-cp38-win32.whl", hash = "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2"}, - {file = "numpy-1.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706"}, - {file = "numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400"}, - {file = "numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f"}, - {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9"}, - {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d"}, - {file = "numpy-1.24.4-cp39-cp39-win32.whl", hash = "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835"}, - {file = "numpy-1.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8"}, - {file = "numpy-1.24.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef"}, - {file = "numpy-1.24.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a"}, - {file = "numpy-1.24.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2"}, - {file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"}, -] - -[[package]] -name = "nylas" -version = "5.14.1" -description = "Python bindings for Nylas, the next-generation email platform." optional = true -python-versions = "*" -files = [ - {file = "nylas-5.14.1.tar.gz", hash = "sha256:dfd83d957817a1e0be67c9c5ca677565cfe587d06120cbd08cb36bf89b3bb55f"}, +python-versions = ">=3.9" +files = [ + {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, + {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, + {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, + {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, + {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, + {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, + {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, + {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, + {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, + {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, + {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, ] -[package.dependencies] -requests = {version = ">=2.4.2", extras = ["security"]} -six = ">=1.4.1" -urlobject = "*" -websocket-client = "0.59.0" - -[package.extras] -release = ["bumpversion (>=0.5.0)", "twine (>=3.4.2)"] -test = ["mock", "pytest", "pytest-cov", "pytest-mock", "pytest-timeout", "pytz", "responses (==0.10.5)", "twine"] - [[package]] name = "openai" -version = "0.27.8" -description = "Python client library for the OpenAI API" -optional = false +version = "1.30.5" +description = "The official Python library for the openai API" +optional = true python-versions = ">=3.7.1" files = [ - {file = "openai-0.27.8-py3-none-any.whl", hash = "sha256:e0a7c2f7da26bdbe5354b03c6d4b82a2f34bd4458c7a17ae1a7092c3e397e03c"}, - {file = "openai-0.27.8.tar.gz", hash = "sha256:2483095c7db1eee274cebac79e315a986c4e55207bb4fa7b82d185b3a2ed9536"}, + {file = "openai-1.30.5-py3-none-any.whl", hash = "sha256:2ad95e926de0d2e09cde632a9204b0a6dca4a03c2cdcc84329b01f355784355a"}, + {file = "openai-1.30.5.tar.gz", hash = "sha256:5366562eb2c5917e6116ae0391b7ae6e3acd62b0ae3f565ada32b35d8fcfa106"}, ] [package.dependencies] -aiohttp = "*" -requests = ">=2.20" -tqdm = "*" +anyio = ">=3.5.0,<5" +distro = ">=1.7.0,<2" +httpx = ">=0.23.0,<1" +pydantic = ">=1.9.0,<3" +sniffio = "*" +tqdm = ">4" +typing-extensions = ">=4.7,<5" [package.extras] -datalib = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] -dev = ["black (>=21.6b0,<22.0)", "pytest (==6.*)", "pytest-asyncio", "pytest-mock"] -embeddings = ["matplotlib", "numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "plotly", "scikit-learn (>=1.0.2)", "scipy", "tenacity (>=8.0.1)"] -wandb = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "wandb"] +datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] [[package]] name = "opentelemetry-api" -version = "1.19.0" +version = "1.25.0" description = "OpenTelemetry Python API" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "opentelemetry_api-1.19.0-py3-none-any.whl", hash = "sha256:dcd2a0ad34b691964947e1d50f9e8c415c32827a1d87f0459a72deb9afdf5597"}, - {file = "opentelemetry_api-1.19.0.tar.gz", hash = "sha256:db374fb5bea00f3c7aa290f5d94cea50b659e6ea9343384c5f6c2bb5d5e8db65"}, + {file = "opentelemetry_api-1.25.0-py3-none-any.whl", hash = "sha256:757fa1aa020a0f8fa139f8959e53dec2051cc26b832e76fa839a6d76ecefd737"}, + {file = "opentelemetry_api-1.25.0.tar.gz", hash = "sha256:77c4985f62f2614e42ce77ee4c9da5fa5f0bc1e1821085e9a47533a9323ae869"}, ] [package.dependencies] deprecated = ">=1.2.6" -importlib-metadata = ">=6.0,<7.0" +importlib-metadata = ">=6.0,<=7.1" [[package]] name = "opentelemetry-sdk" -version = "1.19.0" +version = "1.25.0" description = "OpenTelemetry Python SDK" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "opentelemetry_sdk-1.19.0-py3-none-any.whl", hash = "sha256:bb67ad676b1bc671766a40d7fc9d9563854c186fa11f0dc8fa2284e004bd4263"}, - {file = "opentelemetry_sdk-1.19.0.tar.gz", hash = "sha256:765928956262c7a7766eaba27127b543fb40ef710499cad075f261f52163a87f"}, + {file = "opentelemetry_sdk-1.25.0-py3-none-any.whl", hash = "sha256:d97ff7ec4b351692e9d5a15af570c693b8715ad78b8aafbec5c7100fe966b4c9"}, + {file = "opentelemetry_sdk-1.25.0.tar.gz", hash = "sha256:ce7fc319c57707ef5bf8b74fb9f8ebdb8bfafbe11898410e0d2a761d08a98ec7"}, ] [package.dependencies] -opentelemetry-api = "1.19.0" -opentelemetry-semantic-conventions = "0.40b0" +opentelemetry-api = "1.25.0" +opentelemetry-semantic-conventions = "0.46b0" typing-extensions = ">=3.7.4" [[package]] name = "opentelemetry-semantic-conventions" -version = "0.40b0" +version = "0.46b0" description = "OpenTelemetry Semantic Conventions" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "opentelemetry_semantic_conventions-0.40b0-py3-none-any.whl", hash = "sha256:7ebbaf86755a0948902e68637e3ae516c50222c30455e55af154ad3ffe283839"}, - {file = "opentelemetry_semantic_conventions-0.40b0.tar.gz", hash = "sha256:5a7a491873b15ab7c4907bbfd8737645cc87ca55a0a326c1755d1b928d8a0fae"}, + {file = "opentelemetry_semantic_conventions-0.46b0-py3-none-any.whl", hash = "sha256:6daef4ef9fa51d51855d9f8e0ccd3a1bd59e0e545abe99ac6203804e36ab3e07"}, + {file = "opentelemetry_semantic_conventions-0.46b0.tar.gz", hash = "sha256:fbc982ecbb6a6e90869b15c1673be90bd18c8a56ff1cffc0864e38e2edffaefa"}, +] + +[package.dependencies] +opentelemetry-api = "1.25.0" + +[[package]] +name = "orjson" +version = "3.10.3" +description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" +optional = false +python-versions = ">=3.8" +files = [ + {file = "orjson-3.10.3-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9fb6c3f9f5490a3eb4ddd46fc1b6eadb0d6fc16fb3f07320149c3286a1409dd8"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:252124b198662eee80428f1af8c63f7ff077c88723fe206a25df8dc57a57b1fa"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f3e87733823089a338ef9bbf363ef4de45e5c599a9bf50a7a9b82e86d0228da"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8334c0d87103bb9fbbe59b78129f1f40d1d1e8355bbed2ca71853af15fa4ed3"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1952c03439e4dce23482ac846e7961f9d4ec62086eb98ae76d97bd41d72644d7"}, + {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c0403ed9c706dcd2809f1600ed18f4aae50be263bd7112e54b50e2c2bc3ebd6d"}, + {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:382e52aa4270a037d41f325e7d1dfa395b7de0c367800b6f337d8157367bf3a7"}, + {file = "orjson-3.10.3-cp310-none-win32.whl", hash = "sha256:be2aab54313752c04f2cbaab4515291ef5af8c2256ce22abc007f89f42f49109"}, + {file = "orjson-3.10.3-cp310-none-win_amd64.whl", hash = "sha256:416b195f78ae461601893f482287cee1e3059ec49b4f99479aedf22a20b1098b"}, + {file = "orjson-3.10.3-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:73100d9abbbe730331f2242c1fc0bcb46a3ea3b4ae3348847e5a141265479700"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a12eee96e3ab828dbfcb4d5a0023aa971b27143a1d35dc214c176fdfb29b3"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520de5e2ef0b4ae546bea25129d6c7c74edb43fc6cf5213f511a927f2b28148b"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccaa0a401fc02e8828a5bedfd80f8cd389d24f65e5ca3954d72c6582495b4bcf"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7bc9e8bc11bac40f905640acd41cbeaa87209e7e1f57ade386da658092dc16"}, + {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3582b34b70543a1ed6944aca75e219e1192661a63da4d039d088a09c67543b08"}, + {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c23dfa91481de880890d17aa7b91d586a4746a4c2aa9a145bebdbaf233768d5"}, + {file = "orjson-3.10.3-cp311-none-win32.whl", hash = "sha256:1770e2a0eae728b050705206d84eda8b074b65ee835e7f85c919f5705b006c9b"}, + {file = "orjson-3.10.3-cp311-none-win_amd64.whl", hash = "sha256:93433b3c1f852660eb5abdc1f4dd0ced2be031ba30900433223b28ee0140cde5"}, + {file = "orjson-3.10.3-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a39aa73e53bec8d410875683bfa3a8edf61e5a1c7bb4014f65f81d36467ea098"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0943a96b3fa09bee1afdfccc2cb236c9c64715afa375b2af296c73d91c23eab2"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e852baafceff8da3c9defae29414cc8513a1586ad93e45f27b89a639c68e8176"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18566beb5acd76f3769c1d1a7ec06cdb81edc4d55d2765fb677e3eaa10fa99e0"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd2218d5a3aa43060efe649ec564ebedec8ce6ae0a43654b81376216d5ebd42"}, + {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cf20465e74c6e17a104ecf01bf8cd3b7b252565b4ccee4548f18b012ff2f8069"}, + {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba7f67aa7f983c4345eeda16054a4677289011a478ca947cd69c0a86ea45e534"}, + {file = "orjson-3.10.3-cp312-none-win32.whl", hash = "sha256:17e0713fc159abc261eea0f4feda611d32eabc35708b74bef6ad44f6c78d5ea0"}, + {file = "orjson-3.10.3-cp312-none-win_amd64.whl", hash = "sha256:4c895383b1ec42b017dd2c75ae8a5b862fc489006afde06f14afbdd0309b2af0"}, + {file = "orjson-3.10.3-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:be2719e5041e9fb76c8c2c06b9600fe8e8584e6980061ff88dcbc2691a16d20d"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0175a5798bdc878956099f5c54b9837cb62cfbf5d0b86ba6d77e43861bcec2"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:978be58a68ade24f1af7758626806e13cff7748a677faf95fbb298359aa1e20d"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16bda83b5c61586f6f788333d3cf3ed19015e3b9019188c56983b5a299210eb5"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ad1f26bea425041e0a1adad34630c4825a9e3adec49079b1fb6ac8d36f8b754"}, + {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9e253498bee561fe85d6325ba55ff2ff08fb5e7184cd6a4d7754133bd19c9195"}, + {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0a62f9968bab8a676a164263e485f30a0b748255ee2f4ae49a0224be95f4532b"}, + {file = "orjson-3.10.3-cp38-none-win32.whl", hash = "sha256:8d0b84403d287d4bfa9bf7d1dc298d5c1c5d9f444f3737929a66f2fe4fb8f134"}, + {file = "orjson-3.10.3-cp38-none-win_amd64.whl", hash = "sha256:8bc7a4df90da5d535e18157220d7915780d07198b54f4de0110eca6b6c11e290"}, + {file = "orjson-3.10.3-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9059d15c30e675a58fdcd6f95465c1522b8426e092de9fff20edebfdc15e1cb0"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d40c7f7938c9c2b934b297412c067936d0b54e4b8ab916fd1a9eb8f54c02294"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4a654ec1de8fdaae1d80d55cee65893cb06494e124681ab335218be6a0691e7"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:831c6ef73f9aa53c5f40ae8f949ff7681b38eaddb6904aab89dca4d85099cb78"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99b880d7e34542db89f48d14ddecbd26f06838b12427d5a25d71baceb5ba119d"}, + {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e5e176c994ce4bd434d7aafb9ecc893c15f347d3d2bbd8e7ce0b63071c52e25"}, + {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b69a58a37dab856491bf2d3bbf259775fdce262b727f96aafbda359cb1d114d8"}, + {file = "orjson-3.10.3-cp39-none-win32.whl", hash = "sha256:b8d4d1a6868cde356f1402c8faeb50d62cee765a1f7ffcfd6de732ab0581e063"}, + {file = "orjson-3.10.3-cp39-none-win_amd64.whl", hash = "sha256:5102f50c5fc46d94f2033fe00d392588564378260d64377aec702f21a7a22912"}, + {file = "orjson-3.10.3.tar.gz", hash = "sha256:2b166507acae7ba2f7c315dcf185a9111ad5e992ac81f2d507aac39193c2c818"}, ] [[package]] @@ -2189,112 +2352,95 @@ files = [ [[package]] name = "parso" -version = "0.8.3" +version = "0.8.4" description = "A Python Parser" optional = true python-versions = ">=3.6" files = [ - {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, - {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, + {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, + {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"}, ] [package.extras] -qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] -testing = ["docopt", "pytest (<6.0.0)"] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["docopt", "pytest"] [[package]] name = "pathspec" -version = "0.11.2" +version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, - {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] [[package]] name = "pexpect" -version = "4.8.0" +version = "4.9.0" description = "Pexpect allows easy control of interactive console applications." optional = true python-versions = "*" files = [ - {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, - {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, + {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, + {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, ] [package.dependencies] ptyprocess = ">=0.5" [[package]] -name = "pickleshare" -version = "0.7.5" -description = "Tiny 'shelve'-like database with concurrency support" -optional = true +name = "phonenumbers" +version = "8.13.37" +description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers." +optional = false python-versions = "*" files = [ - {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, - {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, + {file = "phonenumbers-8.13.37-py2.py3-none-any.whl", hash = "sha256:4ea00ef5012422c08c7955c21131e7ae5baa9a3ef52cf2d561e963f023006b80"}, + {file = "phonenumbers-8.13.37.tar.gz", hash = "sha256:bd315fed159aea0516f7c367231810fe8344d5bec26156b88fa18374c11d1cf2"}, ] [[package]] name = "platformdirs" -version = "3.10.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +version = "4.2.2" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, - {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, + {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, + {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, ] [package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] +type = ["mypy (>=1.8)"] [[package]] name = "pluggy" -version = "1.2.0" +version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"}, - {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, ] [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] -[[package]] -name = "pre-commit" -version = "3.3.3" -description = "A framework for managing and maintaining multi-language pre-commit hooks." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pre_commit-3.3.3-py2.py3-none-any.whl", hash = "sha256:10badb65d6a38caff29703362271d7dca483d01da88f9d7e05d0b97171c136cb"}, - {file = "pre_commit-3.3.3.tar.gz", hash = "sha256:a2256f489cd913d575c145132ae196fe335da32d91a8294b7afe6622335dd023"}, -] - -[package.dependencies] -cfgv = ">=2.0.0" -identify = ">=1.0.0" -nodeenv = ">=0.11.1" -pyyaml = ">=5.1" -virtualenv = ">=20.10.0" - [[package]] name = "prompt-toolkit" -version = "3.0.39" +version = "3.0.45" description = "Library for building powerful interactive command lines in Python" optional = true python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.39-py3-none-any.whl", hash = "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88"}, - {file = "prompt_toolkit-3.0.39.tar.gz", hash = "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac"}, + {file = "prompt_toolkit-3.0.45-py3-none-any.whl", hash = "sha256:a29b89160e494e3ea8622b09fa5897610b437884dcdcd054fdc1308883326c2a"}, + {file = "prompt_toolkit-3.0.45.tar.gz", hash = "sha256:07c60ee4ab7b7e90824b61afa840c8f5aad2d46b3e2e10acc33d8ecc94a49089"}, ] [package.dependencies] @@ -2302,13 +2448,13 @@ wcwidth = "*" [[package]] name = "proto-plus" -version = "1.22.3" +version = "1.23.0" description = "Beautiful, Pythonic protocol buffers." optional = true python-versions = ">=3.6" files = [ - {file = "proto-plus-1.22.3.tar.gz", hash = "sha256:fdcd09713cbd42480740d2fe29c990f7fbd885a67efc328aa8be6ee3e9f76a6b"}, - {file = "proto_plus-1.22.3-py3-none-any.whl", hash = "sha256:a49cd903bc0b6ab41f76bf65510439d56ca76f868adf0274e738bfdd096894df"}, + {file = "proto-plus-1.23.0.tar.gz", hash = "sha256:89075171ef11988b3fa157f5dbd8b9cf09d65fffee97e29ce403cd8defba19d2"}, + {file = "proto_plus-1.23.0-py3-none-any.whl", hash = "sha256:a829c79e619e1cf632de091013a4173deed13a55f326ef84f05af6f50ff4c82c"}, ] [package.dependencies] @@ -2319,24 +2465,22 @@ testing = ["google-api-core[grpc] (>=1.31.5)"] [[package]] name = "protobuf" -version = "4.24.1" +version = "4.25.3" description = "" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "protobuf-4.24.1-cp310-abi3-win32.whl", hash = "sha256:d414199ca605eeb498adc4d2ba82aedc0379dca4a7c364ff9bc9a179aa28e71b"}, - {file = "protobuf-4.24.1-cp310-abi3-win_amd64.whl", hash = "sha256:5906c5e79ff50fe38b2d49d37db5874e3c8010826f2362f79996d83128a8ed9b"}, - {file = "protobuf-4.24.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:970c701ee16788d74f3de20938520d7a0aebc7e4fff37096a48804c80d2908cf"}, - {file = "protobuf-4.24.1-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:fc361148e902949dcb953bbcb148c99fe8f8854291ad01107e4120361849fd0e"}, - {file = "protobuf-4.24.1-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:5d32363d14aca6e5c9e9d5918ad8fb65b091b6df66740ae9de50ac3916055e43"}, - {file = "protobuf-4.24.1-cp37-cp37m-win32.whl", hash = "sha256:df015c47d6855b8efa0b9be706c70bf7f050a4d5ac6d37fb043fbd95157a0e25"}, - {file = "protobuf-4.24.1-cp37-cp37m-win_amd64.whl", hash = "sha256:d4af4fd9e9418e819be30f8df2a16e72fbad546a7576ac7f3653be92a6966d30"}, - {file = "protobuf-4.24.1-cp38-cp38-win32.whl", hash = "sha256:302e8752c760549ed4c7a508abc86b25d46553c81989343782809e1a062a2ef9"}, - {file = "protobuf-4.24.1-cp38-cp38-win_amd64.whl", hash = "sha256:06437f0d4bb0d5f29e3d392aba69600188d4be5ad1e0a3370e581a9bf75a3081"}, - {file = "protobuf-4.24.1-cp39-cp39-win32.whl", hash = "sha256:0b2b224e9541fe9f046dd7317d05f08769c332b7e4c54d93c7f0f372dedb0b1a"}, - {file = "protobuf-4.24.1-cp39-cp39-win_amd64.whl", hash = "sha256:bd39b9094a4cc003a1f911b847ab379f89059f478c0b611ba1215053e295132e"}, - {file = "protobuf-4.24.1-py3-none-any.whl", hash = "sha256:55dd644adc27d2a624339332755fe077c7f26971045b469ebb9732a69ce1f2ca"}, - {file = "protobuf-4.24.1.tar.gz", hash = "sha256:44837a5ed9c9418ad5d502f89f28ba102e9cd172b6668bc813f21716f9273348"}, + {file = "protobuf-4.25.3-cp310-abi3-win32.whl", hash = "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa"}, + {file = "protobuf-4.25.3-cp310-abi3-win_amd64.whl", hash = "sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8"}, + {file = "protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c"}, + {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019"}, + {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d"}, + {file = "protobuf-4.25.3-cp38-cp38-win32.whl", hash = "sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2"}, + {file = "protobuf-4.25.3-cp38-cp38-win_amd64.whl", hash = "sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4"}, + {file = "protobuf-4.25.3-cp39-cp39-win32.whl", hash = "sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4"}, + {file = "protobuf-4.25.3-cp39-cp39-win_amd64.whl", hash = "sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c"}, + {file = "protobuf-4.25.3-py3-none-any.whl", hash = "sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9"}, + {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, ] [[package]] @@ -2364,56 +2508,67 @@ files = [ [package.extras] tests = ["pytest"] +[[package]] +name = "pvkoala" +version = "2.0.1" +description = "Koala Noise Suppression Engine." +optional = true +python-versions = ">=3.7" +files = [ + {file = "pvkoala-2.0.1-py3-none-any.whl", hash = "sha256:8b153e076b4d14adccdcb4d800aa84e8d2f91e0640b959677582d3128cbcb249"}, + {file = "pvkoala-2.0.1.tar.gz", hash = "sha256:5e017c671fc1338d42dc20f9dee003d0144bbba1757b6f1fcd6272c5308da242"}, +] + [[package]] name = "pyasn1" -version = "0.5.0" +version = "0.6.0" description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" optional = true -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +python-versions = ">=3.8" files = [ - {file = "pyasn1-0.5.0-py2.py3-none-any.whl", hash = "sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57"}, - {file = "pyasn1-0.5.0.tar.gz", hash = "sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde"}, + {file = "pyasn1-0.6.0-py2.py3-none-any.whl", hash = "sha256:cca4bb0f2df5504f02f6f8a775b6e416ff9b0b3b16f7ee80b5a3153d9b804473"}, + {file = "pyasn1-0.6.0.tar.gz", hash = "sha256:3a35ab2c4b5ef98e17dfdec8ab074046fbda76e281c5a706ccd82328cfc8f64c"}, ] [[package]] name = "pyasn1-modules" -version = "0.3.0" +version = "0.4.0" description = "A collection of ASN.1-based protocols modules" optional = true -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +python-versions = ">=3.8" files = [ - {file = "pyasn1_modules-0.3.0-py2.py3-none-any.whl", hash = "sha256:d3ccd6ed470d9ffbc716be08bd90efbd44d0734bc9303818f7336070984a162d"}, - {file = "pyasn1_modules-0.3.0.tar.gz", hash = "sha256:5bd01446b736eb9d31512a30d46c1ac3395d676c6f3cafa4c03eb54b9925631c"}, + {file = "pyasn1_modules-0.4.0-py3-none-any.whl", hash = "sha256:be04f15b66c206eed667e0bb5ab27e2b1855ea54a842e5037738099e8ca4ae0b"}, + {file = "pyasn1_modules-0.4.0.tar.gz", hash = "sha256:831dbcea1b177b28c9baddf4c6d1013c24c3accd14a1873fffaa6a2e905f17b6"}, ] [package.dependencies] -pyasn1 = ">=0.4.6,<0.6.0" +pyasn1 = ">=0.4.6,<0.7.0" [[package]] name = "pycparser" -version = "2.21" +version = "2.22" description = "C parser in Python" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.8" files = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, ] [[package]] name = "pydantic" -version = "2.6.0" +version = "2.7.2" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.6.0-py3-none-any.whl", hash = "sha256:1440966574e1b5b99cf75a13bec7b20e3512e8a61b894ae252f56275e2c465ae"}, - {file = "pydantic-2.6.0.tar.gz", hash = "sha256:ae887bd94eb404b09d86e4d12f93893bdca79d766e738528c6fa1c849f3c6bcf"}, + {file = "pydantic-2.7.2-py3-none-any.whl", hash = "sha256:834ab954175f94e6e68258537dc49402c4a5e9d0409b9f1b86b7e934a8372de7"}, + {file = "pydantic-2.7.2.tar.gz", hash = "sha256:71b2945998f9c9b7919a45bde9a50397b289937d215ae141c1d0903ba7149fd7"}, ] [package.dependencies] annotated-types = ">=0.4.0" -pydantic-core = "2.16.1" +pydantic-core = "2.18.3" typing-extensions = ">=4.6.1" [package.extras] @@ -2421,90 +2576,90 @@ email = ["email-validator (>=2.0.0)"] [[package]] name = "pydantic-core" -version = "2.16.1" -description = "" +version = "2.18.3" +description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.16.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:300616102fb71241ff477a2cbbc847321dbec49428434a2f17f37528721c4948"}, - {file = "pydantic_core-2.16.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5511f962dd1b9b553e9534c3b9c6a4b0c9ded3d8c2be96e61d56f933feef9e1f"}, - {file = "pydantic_core-2.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98f0edee7ee9cc7f9221af2e1b95bd02810e1c7a6d115cfd82698803d385b28f"}, - {file = "pydantic_core-2.16.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9795f56aa6b2296f05ac79d8a424e94056730c0b860a62b0fdcfe6340b658cc8"}, - {file = "pydantic_core-2.16.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c45f62e4107ebd05166717ac58f6feb44471ed450d07fecd90e5f69d9bf03c48"}, - {file = "pydantic_core-2.16.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:462d599299c5971f03c676e2b63aa80fec5ebc572d89ce766cd11ca8bcb56f3f"}, - {file = "pydantic_core-2.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ebaa4bf6386a3b22eec518da7d679c8363fb7fb70cf6972161e5542f470798"}, - {file = "pydantic_core-2.16.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:99f9a50b56713a598d33bc23a9912224fc5d7f9f292444e6664236ae471ddf17"}, - {file = "pydantic_core-2.16.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8ec364e280db4235389b5e1e6ee924723c693cbc98e9d28dc1767041ff9bc388"}, - {file = "pydantic_core-2.16.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:653a5dfd00f601a0ed6654a8b877b18d65ac32c9d9997456e0ab240807be6cf7"}, - {file = "pydantic_core-2.16.1-cp310-none-win32.whl", hash = "sha256:1661c668c1bb67b7cec96914329d9ab66755911d093bb9063c4c8914188af6d4"}, - {file = "pydantic_core-2.16.1-cp310-none-win_amd64.whl", hash = "sha256:561be4e3e952c2f9056fba5267b99be4ec2afadc27261505d4992c50b33c513c"}, - {file = "pydantic_core-2.16.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:102569d371fadc40d8f8598a59379c37ec60164315884467052830b28cc4e9da"}, - {file = "pydantic_core-2.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:735dceec50fa907a3c314b84ed609dec54b76a814aa14eb90da31d1d36873a5e"}, - {file = "pydantic_core-2.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e83ebbf020be727d6e0991c1b192a5c2e7113eb66e3def0cd0c62f9f266247e4"}, - {file = "pydantic_core-2.16.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:30a8259569fbeec49cfac7fda3ec8123486ef1b729225222f0d41d5f840b476f"}, - {file = "pydantic_core-2.16.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:920c4897e55e2881db6a6da151198e5001552c3777cd42b8a4c2f72eedc2ee91"}, - {file = "pydantic_core-2.16.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5247a3d74355f8b1d780d0f3b32a23dd9f6d3ff43ef2037c6dcd249f35ecf4c"}, - {file = "pydantic_core-2.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d5bea8012df5bb6dda1e67d0563ac50b7f64a5d5858348b5c8cb5043811c19d"}, - {file = "pydantic_core-2.16.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ed3025a8a7e5a59817b7494686d449ebfbe301f3e757b852c8d0d1961d6be864"}, - {file = "pydantic_core-2.16.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:06f0d5a1d9e1b7932477c172cc720b3b23c18762ed7a8efa8398298a59d177c7"}, - {file = "pydantic_core-2.16.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:150ba5c86f502c040b822777e2e519b5625b47813bd05f9273a8ed169c97d9ae"}, - {file = "pydantic_core-2.16.1-cp311-none-win32.whl", hash = "sha256:d6cbdf12ef967a6aa401cf5cdf47850559e59eedad10e781471c960583f25aa1"}, - {file = "pydantic_core-2.16.1-cp311-none-win_amd64.whl", hash = "sha256:afa01d25769af33a8dac0d905d5c7bb2d73c7c3d5161b2dd6f8b5b5eea6a3c4c"}, - {file = "pydantic_core-2.16.1-cp311-none-win_arm64.whl", hash = "sha256:1a2fe7b00a49b51047334d84aafd7e39f80b7675cad0083678c58983662da89b"}, - {file = "pydantic_core-2.16.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f478ec204772a5c8218e30eb813ca43e34005dff2eafa03931b3d8caef87d51"}, - {file = "pydantic_core-2.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f1936ef138bed2165dd8573aa65e3095ef7c2b6247faccd0e15186aabdda7f66"}, - {file = "pydantic_core-2.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99d3a433ef5dc3021c9534a58a3686c88363c591974c16c54a01af7efd741f13"}, - {file = "pydantic_core-2.16.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd88f40f2294440d3f3c6308e50d96a0d3d0973d6f1a5732875d10f569acef49"}, - {file = "pydantic_core-2.16.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fac641bbfa43d5a1bed99d28aa1fded1984d31c670a95aac1bf1d36ac6ce137"}, - {file = "pydantic_core-2.16.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72bf9308a82b75039b8c8edd2be2924c352eda5da14a920551a8b65d5ee89253"}, - {file = "pydantic_core-2.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb4363e6c9fc87365c2bc777a1f585a22f2f56642501885ffc7942138499bf54"}, - {file = "pydantic_core-2.16.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:20f724a023042588d0f4396bbbcf4cffd0ddd0ad3ed4f0d8e6d4ac4264bae81e"}, - {file = "pydantic_core-2.16.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:fb4370b15111905bf8b5ba2129b926af9470f014cb0493a67d23e9d7a48348e8"}, - {file = "pydantic_core-2.16.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:23632132f1fd608034f1a56cc3e484be00854db845b3a4a508834be5a6435a6f"}, - {file = "pydantic_core-2.16.1-cp312-none-win32.whl", hash = "sha256:b9f3e0bffad6e238f7acc20c393c1ed8fab4371e3b3bc311020dfa6020d99212"}, - {file = "pydantic_core-2.16.1-cp312-none-win_amd64.whl", hash = "sha256:a0b4cfe408cd84c53bab7d83e4209458de676a6ec5e9c623ae914ce1cb79b96f"}, - {file = "pydantic_core-2.16.1-cp312-none-win_arm64.whl", hash = "sha256:d195add190abccefc70ad0f9a0141ad7da53e16183048380e688b466702195dd"}, - {file = "pydantic_core-2.16.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:502c062a18d84452858f8aea1e520e12a4d5228fc3621ea5061409d666ea1706"}, - {file = "pydantic_core-2.16.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d8c032ccee90b37b44e05948b449a2d6baed7e614df3d3f47fe432c952c21b60"}, - {file = "pydantic_core-2.16.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:920f4633bee43d7a2818e1a1a788906df5a17b7ab6fe411220ed92b42940f818"}, - {file = "pydantic_core-2.16.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9f5d37ff01edcbace53a402e80793640c25798fb7208f105d87a25e6fcc9ea06"}, - {file = "pydantic_core-2.16.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:399166f24c33a0c5759ecc4801f040dbc87d412c1a6d6292b2349b4c505effc9"}, - {file = "pydantic_core-2.16.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ac89ccc39cd1d556cc72d6752f252dc869dde41c7c936e86beac5eb555041b66"}, - {file = "pydantic_core-2.16.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73802194f10c394c2bedce7a135ba1d8ba6cff23adf4217612bfc5cf060de34c"}, - {file = "pydantic_core-2.16.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8fa00fa24ffd8c31fac081bf7be7eb495be6d248db127f8776575a746fa55c95"}, - {file = "pydantic_core-2.16.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:601d3e42452cd4f2891c13fa8c70366d71851c1593ed42f57bf37f40f7dca3c8"}, - {file = "pydantic_core-2.16.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07982b82d121ed3fc1c51faf6e8f57ff09b1325d2efccaa257dd8c0dd937acca"}, - {file = "pydantic_core-2.16.1-cp38-none-win32.whl", hash = "sha256:d0bf6f93a55d3fa7a079d811b29100b019784e2ee6bc06b0bb839538272a5610"}, - {file = "pydantic_core-2.16.1-cp38-none-win_amd64.whl", hash = "sha256:fbec2af0ebafa57eb82c18c304b37c86a8abddf7022955d1742b3d5471a6339e"}, - {file = "pydantic_core-2.16.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a497be217818c318d93f07e14502ef93d44e6a20c72b04c530611e45e54c2196"}, - {file = "pydantic_core-2.16.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:694a5e9f1f2c124a17ff2d0be613fd53ba0c26de588eb4bdab8bca855e550d95"}, - {file = "pydantic_core-2.16.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d4dfc66abea3ec6d9f83e837a8f8a7d9d3a76d25c9911735c76d6745950e62c"}, - {file = "pydantic_core-2.16.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8655f55fe68c4685673265a650ef71beb2d31871c049c8b80262026f23605ee3"}, - {file = "pydantic_core-2.16.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:21e3298486c4ea4e4d5cc6fb69e06fb02a4e22089304308817035ac006a7f506"}, - {file = "pydantic_core-2.16.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:71b4a48a7427f14679f0015b13c712863d28bb1ab700bd11776a5368135c7d60"}, - {file = "pydantic_core-2.16.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10dca874e35bb60ce4f9f6665bfbfad050dd7573596608aeb9e098621ac331dc"}, - {file = "pydantic_core-2.16.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fa496cd45cda0165d597e9d6f01e36c33c9508f75cf03c0a650018c5048f578e"}, - {file = "pydantic_core-2.16.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5317c04349472e683803da262c781c42c5628a9be73f4750ac7d13040efb5d2d"}, - {file = "pydantic_core-2.16.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:42c29d54ed4501a30cd71015bf982fa95e4a60117b44e1a200290ce687d3e640"}, - {file = "pydantic_core-2.16.1-cp39-none-win32.whl", hash = "sha256:ba07646f35e4e49376c9831130039d1b478fbfa1215ae62ad62d2ee63cf9c18f"}, - {file = "pydantic_core-2.16.1-cp39-none-win_amd64.whl", hash = "sha256:2133b0e412a47868a358713287ff9f9a328879da547dc88be67481cdac529118"}, - {file = "pydantic_core-2.16.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d25ef0c33f22649b7a088035fd65ac1ce6464fa2876578df1adad9472f918a76"}, - {file = "pydantic_core-2.16.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:99c095457eea8550c9fa9a7a992e842aeae1429dab6b6b378710f62bfb70b394"}, - {file = "pydantic_core-2.16.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b49c604ace7a7aa8af31196abbf8f2193be605db6739ed905ecaf62af31ccae0"}, - {file = "pydantic_core-2.16.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c56da23034fe66221f2208c813d8aa509eea34d97328ce2add56e219c3a9f41c"}, - {file = "pydantic_core-2.16.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cebf8d56fee3b08ad40d332a807ecccd4153d3f1ba8231e111d9759f02edfd05"}, - {file = "pydantic_core-2.16.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:1ae8048cba95f382dba56766525abca438328455e35c283bb202964f41a780b0"}, - {file = "pydantic_core-2.16.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:780daad9e35b18d10d7219d24bfb30148ca2afc309928e1d4d53de86822593dc"}, - {file = "pydantic_core-2.16.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c94b5537bf6ce66e4d7830c6993152940a188600f6ae044435287753044a8fe2"}, - {file = "pydantic_core-2.16.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:adf28099d061a25fbcc6531febb7a091e027605385de9fe14dd6a97319d614cf"}, - {file = "pydantic_core-2.16.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:644904600c15816a1f9a1bafa6aab0d21db2788abcdf4e2a77951280473f33e1"}, - {file = "pydantic_core-2.16.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87bce04f09f0552b66fca0c4e10da78d17cb0e71c205864bab4e9595122cb9d9"}, - {file = "pydantic_core-2.16.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:877045a7969ace04d59516d5d6a7dee13106822f99a5d8df5e6822941f7bedc8"}, - {file = "pydantic_core-2.16.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9c46e556ee266ed3fb7b7a882b53df3c76b45e872fdab8d9cf49ae5e91147fd7"}, - {file = "pydantic_core-2.16.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4eebbd049008eb800f519578e944b8dc8e0f7d59a5abb5924cc2d4ed3a1834ff"}, - {file = "pydantic_core-2.16.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:c0be58529d43d38ae849a91932391eb93275a06b93b79a8ab828b012e916a206"}, - {file = "pydantic_core-2.16.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b1fc07896fc1851558f532dffc8987e526b682ec73140886c831d773cef44b76"}, - {file = "pydantic_core-2.16.1.tar.gz", hash = "sha256:daff04257b49ab7f4b3f73f98283d3dbb1a65bf3500d55c7beac3c66c310fe34"}, + {file = "pydantic_core-2.18.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:744697428fcdec6be5670460b578161d1ffe34743a5c15656be7ea82b008197c"}, + {file = "pydantic_core-2.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b40c05ced1ba4218b14986fe6f283d22e1ae2ff4c8e28881a70fb81fbfcda7"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a9a75622357076efb6b311983ff190fbfb3c12fc3a853122b34d3d358126c"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e2e253af04ceaebde8eb201eb3f3e3e7e390f2d275a88300d6a1959d710539e2"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:855ec66589c68aa367d989da5c4755bb74ee92ccad4fdb6af942c3612c067e34"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d3e42bb54e7e9d72c13ce112e02eb1b3b55681ee948d748842171201a03a98a"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6ac9ffccc9d2e69d9fba841441d4259cb668ac180e51b30d3632cd7abca2b9b"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c56eca1686539fa0c9bda992e7bd6a37583f20083c37590413381acfc5f192d6"}, + {file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:17954d784bf8abfc0ec2a633108207ebc4fa2df1a0e4c0c3ccbaa9bb01d2c426"}, + {file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:98ed737567d8f2ecd54f7c8d4f8572ca7c7921ede93a2e52939416170d357812"}, + {file = "pydantic_core-2.18.3-cp310-none-win32.whl", hash = "sha256:9f9e04afebd3ed8c15d67a564ed0a34b54e52136c6d40d14c5547b238390e779"}, + {file = "pydantic_core-2.18.3-cp310-none-win_amd64.whl", hash = "sha256:45e4ffbae34f7ae30d0047697e724e534a7ec0a82ef9994b7913a412c21462a0"}, + {file = "pydantic_core-2.18.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b9ebe8231726c49518b16b237b9fe0d7d361dd221302af511a83d4ada01183ab"}, + {file = "pydantic_core-2.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b8e20e15d18bf7dbb453be78a2d858f946f5cdf06c5072453dace00ab652e2b2"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0d9ff283cd3459fa0bf9b0256a2b6f01ac1ff9ffb034e24457b9035f75587cb"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f7ef5f0ebb77ba24c9970da18b771711edc5feaf00c10b18461e0f5f5949231"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73038d66614d2e5cde30435b5afdced2b473b4c77d4ca3a8624dd3e41a9c19be"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6afd5c867a74c4d314c557b5ea9520183fadfbd1df4c2d6e09fd0d990ce412cd"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd7df92f28d351bb9f12470f4c533cf03d1b52ec5a6e5c58c65b183055a60106"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:80aea0ffeb1049336043d07799eace1c9602519fb3192916ff525b0287b2b1e4"}, + {file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaee40f25bba38132e655ffa3d1998a6d576ba7cf81deff8bfa189fb43fd2bbe"}, + {file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9128089da8f4fe73f7a91973895ebf2502539d627891a14034e45fb9e707e26d"}, + {file = "pydantic_core-2.18.3-cp311-none-win32.whl", hash = "sha256:fec02527e1e03257aa25b1a4dcbe697b40a22f1229f5d026503e8b7ff6d2eda7"}, + {file = "pydantic_core-2.18.3-cp311-none-win_amd64.whl", hash = "sha256:58ff8631dbab6c7c982e6425da8347108449321f61fe427c52ddfadd66642af7"}, + {file = "pydantic_core-2.18.3-cp311-none-win_arm64.whl", hash = "sha256:3fc1c7f67f34c6c2ef9c213e0f2a351797cda98249d9ca56a70ce4ebcaba45f4"}, + {file = "pydantic_core-2.18.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f0928cde2ae416a2d1ebe6dee324709c6f73e93494d8c7aea92df99aab1fc40f"}, + {file = "pydantic_core-2.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0bee9bb305a562f8b9271855afb6ce00223f545de3d68560b3c1649c7c5295e9"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e862823be114387257dacbfa7d78547165a85d7add33b446ca4f4fae92c7ff5c"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a36f78674cbddc165abab0df961b5f96b14461d05feec5e1f78da58808b97e7"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba905d184f62e7ddbb7a5a751d8a5c805463511c7b08d1aca4a3e8c11f2e5048"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fdd362f6a586e681ff86550b2379e532fee63c52def1c666887956748eaa326"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24b214b7ee3bd3b865e963dbed0f8bc5375f49449d70e8d407b567af3222aae4"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:691018785779766127f531674fa82bb368df5b36b461622b12e176c18e119022"}, + {file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:60e4c625e6f7155d7d0dcac151edf5858102bc61bf959d04469ca6ee4e8381bd"}, + {file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4e651e47d981c1b701dcc74ab8fec5a60a5b004650416b4abbef13db23bc7be"}, + {file = "pydantic_core-2.18.3-cp312-none-win32.whl", hash = "sha256:ffecbb5edb7f5ffae13599aec33b735e9e4c7676ca1633c60f2c606beb17efc5"}, + {file = "pydantic_core-2.18.3-cp312-none-win_amd64.whl", hash = "sha256:2c8333f6e934733483c7eddffdb094c143b9463d2af7e6bd85ebcb2d4a1b82c6"}, + {file = "pydantic_core-2.18.3-cp312-none-win_arm64.whl", hash = "sha256:7a20dded653e516a4655f4c98e97ccafb13753987434fe7cf044aa25f5b7d417"}, + {file = "pydantic_core-2.18.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:eecf63195be644b0396f972c82598cd15693550f0ff236dcf7ab92e2eb6d3522"}, + {file = "pydantic_core-2.18.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c44efdd3b6125419c28821590d7ec891c9cb0dff33a7a78d9d5c8b6f66b9702"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e59fca51ffbdd1638b3856779342ed69bcecb8484c1d4b8bdb237d0eb5a45e2"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70cf099197d6b98953468461d753563b28e73cf1eade2ffe069675d2657ed1d5"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63081a49dddc6124754b32a3774331467bfc3d2bd5ff8f10df36a95602560361"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:370059b7883485c9edb9655355ff46d912f4b03b009d929220d9294c7fd9fd60"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a64faeedfd8254f05f5cf6fc755023a7e1606af3959cfc1a9285744cc711044"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19d2e725de0f90d8671f89e420d36c3dd97639b98145e42fcc0e1f6d492a46dc"}, + {file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:67bc078025d70ec5aefe6200ef094576c9d86bd36982df1301c758a9fff7d7f4"}, + {file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:adf952c3f4100e203cbaf8e0c907c835d3e28f9041474e52b651761dc248a3c0"}, + {file = "pydantic_core-2.18.3-cp38-none-win32.whl", hash = "sha256:9a46795b1f3beb167eaee91736d5d17ac3a994bf2215a996aed825a45f897558"}, + {file = "pydantic_core-2.18.3-cp38-none-win_amd64.whl", hash = "sha256:200ad4e3133cb99ed82342a101a5abf3d924722e71cd581cc113fe828f727fbc"}, + {file = "pydantic_core-2.18.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:304378b7bf92206036c8ddd83a2ba7b7d1a5b425acafff637172a3aa72ad7083"}, + {file = "pydantic_core-2.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c826870b277143e701c9ccf34ebc33ddb4d072612683a044e7cce2d52f6c3fef"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e201935d282707394f3668380e41ccf25b5794d1b131cdd96b07f615a33ca4b1"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5560dda746c44b48bf82b3d191d74fe8efc5686a9ef18e69bdabccbbb9ad9442"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b32c2a1f8032570842257e4c19288eba9a2bba4712af542327de9a1204faff8"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:929c24e9dea3990bc8bcd27c5f2d3916c0c86f5511d2caa69e0d5290115344a9"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a8376fef60790152564b0eab376b3e23dd6e54f29d84aad46f7b264ecca943"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dccf3ef1400390ddd1fb55bf0632209d39140552d068ee5ac45553b556780e06"}, + {file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:41dbdcb0c7252b58fa931fec47937edb422c9cb22528f41cb8963665c372caf6"}, + {file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:666e45cf071669fde468886654742fa10b0e74cd0fa0430a46ba6056b24fb0af"}, + {file = "pydantic_core-2.18.3-cp39-none-win32.whl", hash = "sha256:f9c08cabff68704a1b4667d33f534d544b8a07b8e5d039c37067fceb18789e78"}, + {file = "pydantic_core-2.18.3-cp39-none-win_amd64.whl", hash = "sha256:4afa5f5973e8572b5c0dcb4e2d4fda7890e7cd63329bd5cc3263a25c92ef0026"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:77319771a026f7c7d29c6ebc623de889e9563b7087911b46fd06c044a12aa5e9"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:df11fa992e9f576473038510d66dd305bcd51d7dd508c163a8c8fe148454e059"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d531076bdfb65af593326ffd567e6ab3da145020dafb9187a1d131064a55f97c"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d33ce258e4e6e6038f2b9e8b8a631d17d017567db43483314993b3ca345dcbbb"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1f9cd7f5635b719939019be9bda47ecb56e165e51dd26c9a217a433e3d0d59a9"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cd4a032bb65cc132cae1fe3e52877daecc2097965cd3914e44fbd12b00dae7c5"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f2718430098bcdf60402136c845e4126a189959d103900ebabb6774a5d9fdb"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c0037a92cf0c580ed14e10953cdd26528e8796307bb8bb312dc65f71547df04d"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b95a0972fac2b1ff3c94629fc9081b16371dad870959f1408cc33b2f78ad347a"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a62e437d687cc148381bdd5f51e3e81f5b20a735c55f690c5be94e05da2b0d5c"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b367a73a414bbb08507da102dc2cde0fa7afe57d09b3240ce82a16d608a7679c"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ecce4b2360aa3f008da3327d652e74a0e743908eac306198b47e1c58b03dd2b"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd4435b8d83f0c9561a2a9585b1de78f1abb17cb0cef5f39bf6a4b47d19bafe3"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:616221a6d473c5b9aa83fa8982745441f6a4a62a66436be9445c65f241b86c94"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7e6382ce89a92bc1d0c0c5edd51e931432202b9080dc921d8d003e616402efd1"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ff58f379345603d940e461eae474b6bbb6dab66ed9a851ecd3cb3709bf4dcf6a"}, + {file = "pydantic_core-2.18.3.tar.gz", hash = "sha256:432e999088d85c8f36b9a3f769a8e2b57aabd817bbb729a90d1fe7f18f6f1f39"}, ] [package.dependencies] @@ -2514,7 +2669,7 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" name = "pydub" version = "0.25.1" description = "Manipulate audio with an simple and easy high level interface" -optional = false +optional = true python-versions = "*" files = [ {file = "pydub-0.25.1-py2.py3-none-any.whl", hash = "sha256:65617e33033874b59d87db603aa1ed450633288aefead953b30bded59cb599a6"}, @@ -2523,28 +2678,48 @@ files = [ [[package]] name = "pydub-stubs" -version = "0.25.1.0" +version = "0.25.1.1" description = "Stub-only package containing type information for pydub" optional = false python-versions = ">=3.8,<4.0" files = [ - {file = "pydub-stubs-0.25.1.0.tar.gz", hash = "sha256:57ff97da5faf221eda0f508e62a187766342490e07a450c63a76ca7e970da4da"}, - {file = "pydub_stubs-0.25.1.0-py3-none-any.whl", hash = "sha256:7ff185c40838dfdfb344222ad6d962e99682fa2787557d771023af8c24593ddc"}, + {file = "pydub_stubs-0.25.1.1-py3-none-any.whl", hash = "sha256:8cd0c0b73c8d89c8273e3a500b542a8cf150346a61f35191e9d59cc2f5ba6c1b"}, + {file = "pydub_stubs-0.25.1.1.tar.gz", hash = "sha256:4a7a783e0455d2b7dcc3034f3dc21aaee284413751aa9705357017931d257bd1"}, ] +[package.dependencies] +typing-extensions = ">=4.0.0" + [[package]] name = "pygments" -version = "2.16.1" +version = "2.18.0" description = "Pygments is a syntax highlighting package written in Python." -optional = true -python-versions = ">=3.7" +optional = false +python-versions = ">=3.8" files = [ - {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, - {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, ] [package.extras] -plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pyht" +version = "0.0.28" +description = "" +optional = true +python-versions = "<4.0,>=3.8" +files = [ + {file = "pyht-0.0.28-py3-none-any.whl", hash = "sha256:ad8801acaa906eff5d6b39ce5ca76a08c154f705a2d0b2b6e841b219ef7875be"}, + {file = "pyht-0.0.28.tar.gz", hash = "sha256:00792e8c068fc905557525de9db0dbd7dcb651e15f05c6cc49490340b95a444a"}, +] + +[package.dependencies] +filelock = ">=3.12.4,<4.0.0" +grpcio = ">=1.58.0,<2.0.0" +protobuf = ">=4.24.3,<5.0.0" +requests = ">=2.31.0,<3.0.0" [[package]] name = "pyjwt" @@ -2568,13 +2743,13 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] [[package]] name = "pytest" -version = "7.4.4" +version = "8.2.1" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, + {file = "pytest-8.2.1-py3-none-any.whl", hash = "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1"}, + {file = "pytest-8.2.1.tar.gz", hash = "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd"}, ] [package.dependencies] @@ -2582,70 +2757,110 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} +pluggy = ">=1.5,<2.0" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-asyncio" -version = "0.21.1" +version = "0.23.7" description = "Pytest support for asyncio" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-asyncio-0.21.1.tar.gz", hash = "sha256:40a7eae6dded22c7b604986855ea48400ab15b069ae38116e8c01238e9eeb64d"}, - {file = "pytest_asyncio-0.21.1-py3-none-any.whl", hash = "sha256:8666c1c8ac02631d7c51ba282e0c69a8a452b211ffedf2599099845da5c5c37b"}, + {file = "pytest_asyncio-0.23.7-py3-none-any.whl", hash = "sha256:009b48127fbe44518a547bddd25611551b0e43ccdbf1e67d12479f569832c20b"}, + {file = "pytest_asyncio-0.23.7.tar.gz", hash = "sha256:5f5c72948f4c49e7db4f29f2521d4031f1c27f86e57b046126654083d4770268"}, ] [package.dependencies] -pytest = ">=7.0.0" +pytest = ">=7.0.0,<9" [package.extras] docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] -testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"] +testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] [[package]] -name = "pytest-mock" -version = "3.12.0" -description = "Thin-wrapper around the mock package for easier use with pytest" +name = "pytest-cov" +version = "5.0.0" +description = "Pytest plugin for measuring coverage." optional = false python-versions = ">=3.8" files = [ - {file = "pytest-mock-3.12.0.tar.gz", hash = "sha256:31a40f038c22cad32287bb43932054451ff5583ff094bca6f675df2f8bc1a6e9"}, - {file = "pytest_mock-3.12.0-py3-none-any.whl", hash = "sha256:0972719a7263072da3a21c7f4773069bcc7486027d7e8e1f81d98a47e701bc4f"}, + {file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"}, + {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"}, ] [package.dependencies] -pytest = ">=5.0" +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" [package.extras] -dev = ["pre-commit", "pytest-asyncio", "tox"] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] [[package]] -name = "python-dateutil" -version = "2.8.2" -description = "Extensions to the standard Python datetime module" +name = "pytest-env" +version = "1.1.3" +description = "pytest plugin that allows you to add environment variables." optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +python-versions = ">=3.8" files = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, + {file = "pytest_env-1.1.3-py3-none-any.whl", hash = "sha256:aada77e6d09fcfb04540a6e462c58533c37df35fa853da78707b17ec04d17dfc"}, + {file = "pytest_env-1.1.3.tar.gz", hash = "sha256:fcd7dc23bb71efd3d35632bde1bbe5ee8c8dc4489d6617fb010674880d96216b"}, ] [package.dependencies] -six = ">=1.5" +pytest = ">=7.4.3" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} + +[package.extras] +test = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "pytest-mock (>=3.12)"] + +[[package]] +name = "pytest-httpx" +version = "0.30.0" +description = "Send responses to httpx." +optional = false +python-versions = ">=3.9" +files = [ + {file = "pytest-httpx-0.30.0.tar.gz", hash = "sha256:755b8edca87c974dd4f3605c374fda11db84631de3d163b99c0df5807023a19a"}, + {file = "pytest_httpx-0.30.0-py3-none-any.whl", hash = "sha256:6d47849691faf11d2532565d0c8e0e02b9f4ee730da31687feae315581d7520c"}, +] + +[package.dependencies] +httpx = "==0.27.*" +pytest = ">=7,<9" + +[package.extras] +testing = ["pytest-asyncio (==0.23.*)", "pytest-cov (==4.*)"] + +[[package]] +name = "pytest-mock" +version = "3.14.0" +description = "Thin-wrapper around the mock package for easier use with pytest" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, + {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, +] + +[package.dependencies] +pytest = ">=6.2.5" + +[package.extras] +dev = ["pre-commit", "pytest-asyncio", "tox"] [[package]] name = "python-dotenv" -version = "1.0.0" +version = "1.0.1" description = "Read key-value pairs from a .env file and set them as environment variables" optional = false python-versions = ">=3.8" files = [ - {file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"}, - {file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"}, + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, ] [package.extras] @@ -2653,27 +2868,27 @@ cli = ["click (>=5.0)"] [[package]] name = "python-multipart" -version = "0.0.6" +version = "0.0.9" description = "A streaming multipart parser for Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "python_multipart-0.0.6-py3-none-any.whl", hash = "sha256:ee698bab5ef148b0a760751c261902cd096e57e10558e11aca17646b74ee1c18"}, - {file = "python_multipart-0.0.6.tar.gz", hash = "sha256:e9925a80bb668529f1b67c7fdb0a5dacdd7cbfc6fb0bff3ea443fe22bdd62132"}, + {file = "python_multipart-0.0.9-py3-none-any.whl", hash = "sha256:97ca7b8ea7b05f977dc3849c3ba99d51689822fab725c3703af7c866a0c2b215"}, + {file = "python_multipart-0.0.9.tar.gz", hash = "sha256:03f54688c663f1b7977105f021043b0793151e4cb1c1a9d4a11fc13d622c4026"}, ] [package.extras] -dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==1.7.3)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"] +dev = ["atomicwrites (==1.4.1)", "attrs (==23.2.0)", "coverage (==7.4.1)", "hatch", "invoke (==2.2.0)", "more-itertools (==10.2.0)", "pbr (==6.0.0)", "pluggy (==1.4.0)", "py (==1.11.0)", "pytest (==8.0.0)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.2.0)", "pyyaml (==6.0.1)", "ruff (==0.2.1)"] [[package]] name = "pytz" -version = "2023.3" +version = "2024.1" description = "World timezone definitions, modern and historical" optional = true python-versions = "*" files = [ - {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"}, - {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"}, + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, ] [[package]] @@ -2688,6 +2903,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -2695,8 +2911,16 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -2713,6 +2937,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -2720,6 +2945,7 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -2727,128 +2953,134 @@ files = [ [[package]] name = "redis" -version = "4.6.0" +version = "5.0.4" description = "Python client for Redis database and key-value store" -optional = true +optional = false python-versions = ">=3.7" files = [ - {file = "redis-4.6.0-py3-none-any.whl", hash = "sha256:e2b03db868160ee4591de3cb90d40ebb50a90dd302138775937f6a42b7ed183c"}, - {file = "redis-4.6.0.tar.gz", hash = "sha256:585dc516b9eb042a619ef0a39c3d7d55fe81bdb4df09a52c9cdde0d07bf1aa7d"}, + {file = "redis-5.0.4-py3-none-any.whl", hash = "sha256:7adc2835c7a9b5033b7ad8f8918d09b7344188228809c98df07af226d39dec91"}, + {file = "redis-5.0.4.tar.gz", hash = "sha256:ec31f2ed9675cc54c21ba854cfe0462e6faf1d83c8ce5944709db8a4700b9c61"}, ] [package.dependencies] -async-timeout = {version = ">=4.0.2", markers = "python_full_version <= \"3.11.2\""} +async-timeout = {version = ">=4.0.3", markers = "python_full_version < \"3.11.3\""} [package.extras] hiredis = ["hiredis (>=1.0.0)"] ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"] +[[package]] +name = "referencing" +version = "0.35.1" +description = "JSON Referencing + Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"}, + {file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + [[package]] name = "regex" -version = "2023.8.8" +version = "2024.5.15" description = "Alternative regular expression module, to replace re." -optional = false -python-versions = ">=3.6" +optional = true +python-versions = ">=3.8" files = [ - {file = "regex-2023.8.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:88900f521c645f784260a8d346e12a1590f79e96403971241e64c3a265c8ecdb"}, - {file = "regex-2023.8.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3611576aff55918af2697410ff0293d6071b7e00f4b09e005d614686ac4cd57c"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8a0ccc8f2698f120e9e5742f4b38dc944c38744d4bdfc427616f3a163dd9de5"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c662a4cbdd6280ee56f841f14620787215a171c4e2d1744c9528bed8f5816c96"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf0633e4a1b667bfe0bb10b5e53fe0d5f34a6243ea2530eb342491f1adf4f739"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:551ad543fa19e94943c5b2cebc54c73353ffff08228ee5f3376bd27b3d5b9800"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54de2619f5ea58474f2ac211ceea6b615af2d7e4306220d4f3fe690c91988a61"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5ec4b3f0aebbbe2fc0134ee30a791af522a92ad9f164858805a77442d7d18570"}, - {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3ae646c35cb9f820491760ac62c25b6d6b496757fda2d51be429e0e7b67ae0ab"}, - {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ca339088839582d01654e6f83a637a4b8194d0960477b9769d2ff2cfa0fa36d2"}, - {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:d9b6627408021452dcd0d2cdf8da0534e19d93d070bfa8b6b4176f99711e7f90"}, - {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:bd3366aceedf274f765a3a4bc95d6cd97b130d1dda524d8f25225d14123c01db"}, - {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7aed90a72fc3654fba9bc4b7f851571dcc368120432ad68b226bd593f3f6c0b7"}, - {file = "regex-2023.8.8-cp310-cp310-win32.whl", hash = "sha256:80b80b889cb767cc47f31d2b2f3dec2db8126fbcd0cff31b3925b4dc6609dcdb"}, - {file = "regex-2023.8.8-cp310-cp310-win_amd64.whl", hash = "sha256:b82edc98d107cbc7357da7a5a695901b47d6eb0420e587256ba3ad24b80b7d0b"}, - {file = "regex-2023.8.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1e7d84d64c84ad97bf06f3c8cb5e48941f135ace28f450d86af6b6512f1c9a71"}, - {file = "regex-2023.8.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ce0f9fbe7d295f9922c0424a3637b88c6c472b75eafeaff6f910494a1fa719ef"}, - {file = "regex-2023.8.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06c57e14ac723b04458df5956cfb7e2d9caa6e9d353c0b4c7d5d54fcb1325c46"}, - {file = "regex-2023.8.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e7a9aaa5a1267125eef22cef3b63484c3241aaec6f48949b366d26c7250e0357"}, - {file = "regex-2023.8.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b7408511fca48a82a119d78a77c2f5eb1b22fe88b0d2450ed0756d194fe7a9a"}, - {file = "regex-2023.8.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14dc6f2d88192a67d708341f3085df6a4f5a0c7b03dec08d763ca2cd86e9f559"}, - {file = "regex-2023.8.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48c640b99213643d141550326f34f0502fedb1798adb3c9eb79650b1ecb2f177"}, - {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0085da0f6c6393428bf0d9c08d8b1874d805bb55e17cb1dfa5ddb7cfb11140bf"}, - {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:964b16dcc10c79a4a2be9f1273fcc2684a9eedb3906439720598029a797b46e6"}, - {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7ce606c14bb195b0e5108544b540e2c5faed6843367e4ab3deb5c6aa5e681208"}, - {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:40f029d73b10fac448c73d6eb33d57b34607f40116e9f6e9f0d32e9229b147d7"}, - {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3b8e6ea6be6d64104d8e9afc34c151926f8182f84e7ac290a93925c0db004bfd"}, - {file = "regex-2023.8.8-cp311-cp311-win32.whl", hash = "sha256:942f8b1f3b223638b02df7df79140646c03938d488fbfb771824f3d05fc083a8"}, - {file = "regex-2023.8.8-cp311-cp311-win_amd64.whl", hash = "sha256:51d8ea2a3a1a8fe4f67de21b8b93757005213e8ac3917567872f2865185fa7fb"}, - {file = "regex-2023.8.8-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e951d1a8e9963ea51efd7f150450803e3b95db5939f994ad3d5edac2b6f6e2b4"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704f63b774218207b8ccc6c47fcef5340741e5d839d11d606f70af93ee78e4d4"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22283c769a7b01c8ac355d5be0715bf6929b6267619505e289f792b01304d898"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91129ff1bb0619bc1f4ad19485718cc623a2dc433dff95baadbf89405c7f6b57"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de35342190deb7b866ad6ba5cbcccb2d22c0487ee0cbb251efef0843d705f0d4"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b993b6f524d1e274a5062488a43e3f9f8764ee9745ccd8e8193df743dbe5ee61"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3026cbcf11d79095a32d9a13bbc572a458727bd5b1ca332df4a79faecd45281c"}, - {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:293352710172239bf579c90a9864d0df57340b6fd21272345222fb6371bf82b3"}, - {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:d909b5a3fff619dc7e48b6b1bedc2f30ec43033ba7af32f936c10839e81b9217"}, - {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:3d370ff652323c5307d9c8e4c62efd1956fb08051b0e9210212bc51168b4ff56"}, - {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:b076da1ed19dc37788f6a934c60adf97bd02c7eea461b73730513921a85d4235"}, - {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e9941a4ada58f6218694f382e43fdd256e97615db9da135e77359da257a7168b"}, - {file = "regex-2023.8.8-cp36-cp36m-win32.whl", hash = "sha256:a8c65c17aed7e15a0c824cdc63a6b104dfc530f6fa8cb6ac51c437af52b481c7"}, - {file = "regex-2023.8.8-cp36-cp36m-win_amd64.whl", hash = "sha256:aadf28046e77a72f30dcc1ab185639e8de7f4104b8cb5c6dfa5d8ed860e57236"}, - {file = "regex-2023.8.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:423adfa872b4908843ac3e7a30f957f5d5282944b81ca0a3b8a7ccbbfaa06103"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ae594c66f4a7e1ea67232a0846649a7c94c188d6c071ac0210c3e86a5f92109"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e51c80c168074faa793685656c38eb7a06cbad7774c8cbc3ea05552d615393d8"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:09b7f4c66aa9d1522b06e31a54f15581c37286237208df1345108fcf4e050c18"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e73e5243af12d9cd6a9d6a45a43570dbe2e5b1cdfc862f5ae2b031e44dd95a8"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:941460db8fe3bd613db52f05259c9336f5a47ccae7d7def44cc277184030a116"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f0ccf3e01afeb412a1a9993049cb160d0352dba635bbca7762b2dc722aa5742a"}, - {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:2e9216e0d2cdce7dbc9be48cb3eacb962740a09b011a116fd7af8c832ab116ca"}, - {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:5cd9cd7170459b9223c5e592ac036e0704bee765706445c353d96f2890e816c8"}, - {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:4873ef92e03a4309b3ccd8281454801b291b689f6ad45ef8c3658b6fa761d7ac"}, - {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:239c3c2a339d3b3ddd51c2daef10874410917cd2b998f043c13e2084cb191684"}, - {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1005c60ed7037be0d9dea1f9c53cc42f836188227366370867222bda4c3c6bd7"}, - {file = "regex-2023.8.8-cp37-cp37m-win32.whl", hash = "sha256:e6bd1e9b95bc5614a7a9c9c44fde9539cba1c823b43a9f7bc11266446dd568e3"}, - {file = "regex-2023.8.8-cp37-cp37m-win_amd64.whl", hash = "sha256:9a96edd79661e93327cfeac4edec72a4046e14550a1d22aa0dd2e3ca52aec921"}, - {file = "regex-2023.8.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f2181c20ef18747d5f4a7ea513e09ea03bdd50884a11ce46066bb90fe4213675"}, - {file = "regex-2023.8.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a2ad5add903eb7cdde2b7c64aaca405f3957ab34f16594d2b78d53b8b1a6a7d6"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9233ac249b354c54146e392e8a451e465dd2d967fc773690811d3a8c240ac601"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:920974009fb37b20d32afcdf0227a2e707eb83fe418713f7a8b7de038b870d0b"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2b6c5dfe0929b6c23dde9624483380b170b6e34ed79054ad131b20203a1a63"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96979d753b1dc3b2169003e1854dc67bfc86edf93c01e84757927f810b8c3c93"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ae54a338191e1356253e7883d9d19f8679b6143703086245fb14d1f20196be9"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2162ae2eb8b079622176a81b65d486ba50b888271302190870b8cc488587d280"}, - {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c884d1a59e69e03b93cf0dfee8794c63d7de0ee8f7ffb76e5f75be8131b6400a"}, - {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf9273e96f3ee2ac89ffcb17627a78f78e7516b08f94dc435844ae72576a276e"}, - {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:83215147121e15d5f3a45d99abeed9cf1fe16869d5c233b08c56cdf75f43a504"}, - {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3f7454aa427b8ab9101f3787eb178057c5250478e39b99540cfc2b889c7d0586"}, - {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0640913d2c1044d97e30d7c41728195fc37e54d190c5385eacb52115127b882"}, - {file = "regex-2023.8.8-cp38-cp38-win32.whl", hash = "sha256:0c59122ceccb905a941fb23b087b8eafc5290bf983ebcb14d2301febcbe199c7"}, - {file = "regex-2023.8.8-cp38-cp38-win_amd64.whl", hash = "sha256:c12f6f67495ea05c3d542d119d270007090bad5b843f642d418eb601ec0fa7be"}, - {file = "regex-2023.8.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:82cd0a69cd28f6cc3789cc6adeb1027f79526b1ab50b1f6062bbc3a0ccb2dbc3"}, - {file = "regex-2023.8.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bb34d1605f96a245fc39790a117ac1bac8de84ab7691637b26ab2c5efb8f228c"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:987b9ac04d0b38ef4f89fbc035e84a7efad9cdd5f1e29024f9289182c8d99e09"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9dd6082f4e2aec9b6a0927202c85bc1b09dcab113f97265127c1dc20e2e32495"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7eb95fe8222932c10d4436e7a6f7c99991e3fdd9f36c949eff16a69246dee2dc"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7098c524ba9f20717a56a8d551d2ed491ea89cbf37e540759ed3b776a4f8d6eb"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b694430b3f00eb02c594ff5a16db30e054c1b9589a043fe9174584c6efa8033"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2aeab3895d778155054abea5238d0eb9a72e9242bd4b43f42fd911ef9a13470"}, - {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:988631b9d78b546e284478c2ec15c8a85960e262e247b35ca5eaf7ee22f6050a"}, - {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:67ecd894e56a0c6108ec5ab1d8fa8418ec0cff45844a855966b875d1039a2e34"}, - {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:14898830f0a0eb67cae2bbbc787c1a7d6e34ecc06fbd39d3af5fe29a4468e2c9"}, - {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:f2200e00b62568cfd920127782c61bc1c546062a879cdc741cfcc6976668dfcf"}, - {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9691a549c19c22d26a4f3b948071e93517bdf86e41b81d8c6ac8a964bb71e5a6"}, - {file = "regex-2023.8.8-cp39-cp39-win32.whl", hash = "sha256:6ab2ed84bf0137927846b37e882745a827458689eb969028af8032b1b3dac78e"}, - {file = "regex-2023.8.8-cp39-cp39-win_amd64.whl", hash = "sha256:5543c055d8ec7801901e1193a51570643d6a6ab8751b1f7dd9af71af467538bb"}, - {file = "regex-2023.8.8.tar.gz", hash = "sha256:fcbdc5f2b0f1cd0f6a56cdb46fe41d2cce1e644e3b68832f3eeebc5fb0f7712e"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53"}, + {file = "regex-2024.5.15-cp310-cp310-win32.whl", hash = "sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3"}, + {file = "regex-2024.5.15-cp310-cp310-win_amd64.whl", hash = "sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68"}, + {file = "regex-2024.5.15-cp311-cp311-win32.whl", hash = "sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa"}, + {file = "regex-2024.5.15-cp311-cp311-win_amd64.whl", hash = "sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80"}, + {file = "regex-2024.5.15-cp312-cp312-win32.whl", hash = "sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe"}, + {file = "regex-2024.5.15-cp312-cp312-win_amd64.whl", hash = "sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741"}, + {file = "regex-2024.5.15-cp38-cp38-win32.whl", hash = "sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9"}, + {file = "regex-2024.5.15-cp38-cp38-win_amd64.whl", hash = "sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456"}, + {file = "regex-2024.5.15-cp39-cp39-win32.whl", hash = "sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694"}, + {file = "regex-2024.5.15-cp39-cp39-win_amd64.whl", hash = "sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388"}, + {file = "regex-2024.5.15.tar.gz", hash = "sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c"}, ] [[package]] name = "requests" -version = "2.31.0" +version = "2.32.3" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -2861,6 +3093,132 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "rich" +version = "13.7.1" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"}, + {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + +[[package]] +name = "rpds-py" +version = "0.18.1" +description = "Python bindings to Rust's persistent data structures (rpds)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "rpds_py-0.18.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:d31dea506d718693b6b2cffc0648a8929bdc51c70a311b2770f09611caa10d53"}, + {file = "rpds_py-0.18.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:732672fbc449bab754e0b15356c077cc31566df874964d4801ab14f71951ea80"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a98a1f0552b5f227a3d6422dbd61bc6f30db170939bd87ed14f3c339aa6c7c9"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f1944ce16401aad1e3f7d312247b3d5de7981f634dc9dfe90da72b87d37887d"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38e14fb4e370885c4ecd734f093a2225ee52dc384b86fa55fe3f74638b2cfb09"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08d74b184f9ab6289b87b19fe6a6d1a97fbfea84b8a3e745e87a5de3029bf944"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d70129cef4a8d979caa37e7fe957202e7eee8ea02c5e16455bc9808a59c6b2f0"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ce0bb20e3a11bd04461324a6a798af34d503f8d6f1aa3d2aa8901ceaf039176d"}, + {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81c5196a790032e0fc2464c0b4ab95f8610f96f1f2fa3d4deacce6a79852da60"}, + {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f3027be483868c99b4985fda802a57a67fdf30c5d9a50338d9db646d590198da"}, + {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d44607f98caa2961bab4fa3c4309724b185b464cdc3ba6f3d7340bac3ec97cc1"}, + {file = "rpds_py-0.18.1-cp310-none-win32.whl", hash = "sha256:c273e795e7a0f1fddd46e1e3cb8be15634c29ae8ff31c196debb620e1edb9333"}, + {file = "rpds_py-0.18.1-cp310-none-win_amd64.whl", hash = "sha256:8352f48d511de5f973e4f2f9412736d7dea76c69faa6d36bcf885b50c758ab9a"}, + {file = "rpds_py-0.18.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6b5ff7e1d63a8281654b5e2896d7f08799378e594f09cf3674e832ecaf396ce8"}, + {file = "rpds_py-0.18.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8927638a4d4137a289e41d0fd631551e89fa346d6dbcfc31ad627557d03ceb6d"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:154bf5c93d79558b44e5b50cc354aa0459e518e83677791e6adb0b039b7aa6a7"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07f2139741e5deb2c5154a7b9629bc5aa48c766b643c1a6750d16f865a82c5fc"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c7672e9fba7425f79019db9945b16e308ed8bc89348c23d955c8c0540da0a07"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:489bdfe1abd0406eba6b3bb4fdc87c7fa40f1031de073d0cfb744634cc8fa261"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c20f05e8e3d4fc76875fc9cb8cf24b90a63f5a1b4c5b9273f0e8225e169b100"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:967342e045564cef76dfcf1edb700b1e20838d83b1aa02ab313e6a497cf923b8"}, + {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2cc7c1a47f3a63282ab0f422d90ddac4aa3034e39fc66a559ab93041e6505da7"}, + {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f7afbfee1157e0f9376c00bb232e80a60e59ed716e3211a80cb8506550671e6e"}, + {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9e6934d70dc50f9f8ea47081ceafdec09245fd9f6032669c3b45705dea096b88"}, + {file = "rpds_py-0.18.1-cp311-none-win32.whl", hash = "sha256:c69882964516dc143083d3795cb508e806b09fc3800fd0d4cddc1df6c36e76bb"}, + {file = "rpds_py-0.18.1-cp311-none-win_amd64.whl", hash = "sha256:70a838f7754483bcdc830444952fd89645569e7452e3226de4a613a4c1793fb2"}, + {file = "rpds_py-0.18.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3dd3cd86e1db5aadd334e011eba4e29d37a104b403e8ca24dcd6703c68ca55b3"}, + {file = "rpds_py-0.18.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:05f3d615099bd9b13ecf2fc9cf2d839ad3f20239c678f461c753e93755d629ee"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35b2b771b13eee8729a5049c976197ff58a27a3829c018a04341bcf1ae409b2b"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ee17cd26b97d537af8f33635ef38be873073d516fd425e80559f4585a7b90c43"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b646bf655b135ccf4522ed43d6902af37d3f5dbcf0da66c769a2b3938b9d8184"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19ba472b9606c36716062c023afa2484d1e4220548751bda14f725a7de17b4f6"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e30ac5e329098903262dc5bdd7e2086e0256aa762cc8b744f9e7bf2a427d3f8"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d58ad6317d188c43750cb76e9deacf6051d0f884d87dc6518e0280438648a9ac"}, + {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e1735502458621921cee039c47318cb90b51d532c2766593be6207eec53e5c4c"}, + {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f5bab211605d91db0e2995a17b5c6ee5edec1270e46223e513eaa20da20076ac"}, + {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2fc24a329a717f9e2448f8cd1f960f9dac4e45b6224d60734edeb67499bab03a"}, + {file = "rpds_py-0.18.1-cp312-none-win32.whl", hash = "sha256:1805d5901779662d599d0e2e4159d8a82c0b05faa86ef9222bf974572286b2b6"}, + {file = "rpds_py-0.18.1-cp312-none-win_amd64.whl", hash = "sha256:720edcb916df872d80f80a1cc5ea9058300b97721efda8651efcd938a9c70a72"}, + {file = "rpds_py-0.18.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:c827576e2fa017a081346dce87d532a5310241648eb3700af9a571a6e9fc7e74"}, + {file = "rpds_py-0.18.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aa3679e751408d75a0b4d8d26d6647b6d9326f5e35c00a7ccd82b78ef64f65f8"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0abeee75434e2ee2d142d650d1e54ac1f8b01e6e6abdde8ffd6eeac6e9c38e20"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed402d6153c5d519a0faf1bb69898e97fb31613b49da27a84a13935ea9164dfc"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:338dee44b0cef8b70fd2ef54b4e09bb1b97fc6c3a58fea5db6cc083fd9fc2724"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7750569d9526199c5b97e5a9f8d96a13300950d910cf04a861d96f4273d5b104"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:607345bd5912aacc0c5a63d45a1f73fef29e697884f7e861094e443187c02be5"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:207c82978115baa1fd8d706d720b4a4d2b0913df1c78c85ba73fe6c5804505f0"}, + {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6d1e42d2735d437e7e80bab4d78eb2e459af48c0a46e686ea35f690b93db792d"}, + {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5463c47c08630007dc0fe99fb480ea4f34a89712410592380425a9b4e1611d8e"}, + {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:06d218939e1bf2ca50e6b0ec700ffe755e5216a8230ab3e87c059ebb4ea06afc"}, + {file = "rpds_py-0.18.1-cp38-none-win32.whl", hash = "sha256:312fe69b4fe1ffbe76520a7676b1e5ac06ddf7826d764cc10265c3b53f96dbe9"}, + {file = "rpds_py-0.18.1-cp38-none-win_amd64.whl", hash = "sha256:9437ca26784120a279f3137ee080b0e717012c42921eb07861b412340f85bae2"}, + {file = "rpds_py-0.18.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:19e515b78c3fc1039dd7da0a33c28c3154458f947f4dc198d3c72db2b6b5dc93"}, + {file = "rpds_py-0.18.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7b28c5b066bca9a4eb4e2f2663012debe680f097979d880657f00e1c30875a0"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:673fdbbf668dd958eff750e500495ef3f611e2ecc209464f661bc82e9838991e"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d960de62227635d2e61068f42a6cb6aae91a7fe00fca0e3aeed17667c8a34611"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:352a88dc7892f1da66b6027af06a2e7e5d53fe05924cc2cfc56495b586a10b72"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e0ee01ad8260184db21468a6e1c37afa0529acc12c3a697ee498d3c2c4dcaf3"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4c39ad2f512b4041343ea3c7894339e4ca7839ac38ca83d68a832fc8b3748ab"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aaa71ee43a703c321906813bb252f69524f02aa05bf4eec85f0c41d5d62d0f4c"}, + {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6cd8098517c64a85e790657e7b1e509b9fe07487fd358e19431cb120f7d96338"}, + {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:4adec039b8e2928983f885c53b7cc4cda8965b62b6596501a0308d2703f8af1b"}, + {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:32b7daaa3e9389db3695964ce8e566e3413b0c43e3394c05e4b243a4cd7bef26"}, + {file = "rpds_py-0.18.1-cp39-none-win32.whl", hash = "sha256:2625f03b105328729f9450c8badda34d5243231eef6535f80064d57035738360"}, + {file = "rpds_py-0.18.1-cp39-none-win_amd64.whl", hash = "sha256:bf18932d0003c8c4d51a39f244231986ab23ee057d235a12b2684ea26a353590"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cbfbea39ba64f5e53ae2915de36f130588bba71245b418060ec3330ebf85678e"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:a3d456ff2a6a4d2adcdf3c1c960a36f4fd2fec6e3b4902a42a384d17cf4e7a65"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7700936ef9d006b7ef605dc53aa364da2de5a3aa65516a1f3ce73bf82ecfc7ae"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:51584acc5916212e1bf45edd17f3a6b05fe0cbb40482d25e619f824dccb679de"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:942695a206a58d2575033ff1e42b12b2aece98d6003c6bc739fbf33d1773b12f"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b906b5f58892813e5ba5c6056d6a5ad08f358ba49f046d910ad992196ea61397"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6f8e3fecca256fefc91bb6765a693d96692459d7d4c644660a9fff32e517843"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7732770412bab81c5a9f6d20aeb60ae943a9b36dcd990d876a773526468e7163"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:bd1105b50ede37461c1d51b9698c4f4be6e13e69a908ab7751e3807985fc0346"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:618916f5535784960f3ecf8111581f4ad31d347c3de66d02e728de460a46303c"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:17c6d2155e2423f7e79e3bb18151c686d40db42d8645e7977442170c360194d4"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c4c4c3f878df21faf5fac86eda32671c27889e13570645a9eea0a1abdd50922"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:fab6ce90574645a0d6c58890e9bcaac8d94dff54fb51c69e5522a7358b80ab64"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:531796fb842b53f2695e94dc338929e9f9dbf473b64710c28af5a160b2a8927d"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:740884bc62a5e2bbb31e584f5d23b32320fd75d79f916f15a788d527a5e83644"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:998125738de0158f088aef3cb264a34251908dd2e5d9966774fdab7402edfab7"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e2be6e9dd4111d5b31ba3b74d17da54a8319d8168890fbaea4b9e5c3de630ae5"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0cee71bc618cd93716f3c1bf56653740d2d13ddbd47673efa8bf41435a60daa"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2c3caec4ec5cd1d18e5dd6ae5194d24ed12785212a90b37f5f7f06b8bedd7139"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:27bba383e8c5231cd559affe169ca0b96ec78d39909ffd817f28b166d7ddd4d8"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:a888e8bdb45916234b99da2d859566f1e8a1d2275a801bb8e4a9644e3c7e7909"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6031b25fb1b06327b43d841f33842b383beba399884f8228a6bb3df3088485ff"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48c2faaa8adfacefcbfdb5f2e2e7bdad081e5ace8d182e5f4ade971f128e6bb3"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:d85164315bd68c0806768dc6bb0429c6f95c354f87485ee3593c4f6b14def2bd"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6afd80f6c79893cfc0574956f78a0add8c76e3696f2d6a15bca2c66c415cf2d4"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa242ac1ff583e4ec7771141606aafc92b361cd90a05c30d93e343a0c2d82a89"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21be4770ff4e08698e1e8e0bce06edb6ea0626e7c8f560bc08222880aca6a6f"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c45a639e93a0c5d4b788b2613bd637468edd62f8f95ebc6fcc303d58ab3f0a8"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910e71711d1055b2768181efa0a17537b2622afeb0424116619817007f8a2b10"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b9bb1f182a97880f6078283b3505a707057c42bf55d8fca604f70dedfdc0772a"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d54f74f40b1f7aaa595a02ff42ef38ca654b1469bef7d52867da474243cc633"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:8d2e182c9ee01135e11e9676e9a62dfad791a7a467738f06726872374a83db49"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:636a15acc588f70fda1661234761f9ed9ad79ebed3f2125d44be0862708b666e"}, + {file = "rpds_py-0.18.1.tar.gz", hash = "sha256:dc48b479d540770c811fbd1eb9ba2bb66951863e448efec2e2c102625328e92f"}, +] + [[package]] name = "rsa" version = "4.9" @@ -2876,137 +3234,72 @@ files = [ pyasn1 = ">=0.1.3" [[package]] -name = "s3transfer" -version = "0.6.2" -description = "An Amazon S3 Transfer Manager" -optional = false -python-versions = ">= 3.7" -files = [ - {file = "s3transfer-0.6.2-py3-none-any.whl", hash = "sha256:b014be3a8a2aab98cfe1abc7229cc5a9a0cf05eb9c1f2b86b230fd8df3f78084"}, - {file = "s3transfer-0.6.2.tar.gz", hash = "sha256:cab66d3380cca3e70939ef2255d01cd8aece6a4907a9528740f668c4b0611861"}, -] - -[package.dependencies] -botocore = ">=1.12.36,<2.0a.0" - -[package.extras] -crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] - -[[package]] -name = "scipy" -version = "1.10.1" -description = "Fundamental algorithms for scientific computing in Python" -optional = false -python-versions = "<3.12,>=3.8" +name = "sentry-sdk" +version = "2.3.1" +description = "Python client for Sentry (https://sentry.io)" +optional = true +python-versions = ">=3.6" files = [ - {file = "scipy-1.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e7354fd7527a4b0377ce55f286805b34e8c54b91be865bac273f527e1b839019"}, - {file = "scipy-1.10.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:4b3f429188c66603a1a5c549fb414e4d3bdc2a24792e061ffbd607d3d75fd84e"}, - {file = "scipy-1.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1553b5dcddd64ba9a0d95355e63fe6c3fc303a8fd77c7bc91e77d61363f7433f"}, - {file = "scipy-1.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c0ff64b06b10e35215abce517252b375e580a6125fd5fdf6421b98efbefb2d2"}, - {file = "scipy-1.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:fae8a7b898c42dffe3f7361c40d5952b6bf32d10c4569098d276b4c547905ee1"}, - {file = "scipy-1.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0f1564ea217e82c1bbe75ddf7285ba0709ecd503f048cb1236ae9995f64217bd"}, - {file = "scipy-1.10.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:d925fa1c81b772882aa55bcc10bf88324dadb66ff85d548c71515f6689c6dac5"}, - {file = "scipy-1.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaea0a6be54462ec027de54fca511540980d1e9eea68b2d5c1dbfe084797be35"}, - {file = "scipy-1.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15a35c4242ec5f292c3dd364a7c71a61be87a3d4ddcc693372813c0b73c9af1d"}, - {file = "scipy-1.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:43b8e0bcb877faf0abfb613d51026cd5cc78918e9530e375727bf0625c82788f"}, - {file = "scipy-1.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5678f88c68ea866ed9ebe3a989091088553ba12c6090244fdae3e467b1139c35"}, - {file = "scipy-1.10.1-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:39becb03541f9e58243f4197584286e339029e8908c46f7221abeea4b749fa88"}, - {file = "scipy-1.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bce5869c8d68cf383ce240e44c1d9ae7c06078a9396df68ce88a1230f93a30c1"}, - {file = "scipy-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07c3457ce0b3ad5124f98a86533106b643dd811dd61b548e78cf4c8786652f6f"}, - {file = "scipy-1.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:049a8bbf0ad95277ffba9b3b7d23e5369cc39e66406d60422c8cfef40ccc8415"}, - {file = "scipy-1.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cd9f1027ff30d90618914a64ca9b1a77a431159df0e2a195d8a9e8a04c78abf9"}, - {file = "scipy-1.10.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:79c8e5a6c6ffaf3a2262ef1be1e108a035cf4f05c14df56057b64acc5bebffb6"}, - {file = "scipy-1.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51af417a000d2dbe1ec6c372dfe688e041a7084da4fdd350aeb139bd3fb55353"}, - {file = "scipy-1.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b4735d6c28aad3cdcf52117e0e91d6b39acd4272f3f5cd9907c24ee931ad601"}, - {file = "scipy-1.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:7ff7f37b1bf4417baca958d254e8e2875d0cc23aaadbe65b3d5b3077b0eb23ea"}, - {file = "scipy-1.10.1.tar.gz", hash = "sha256:2cf9dfb80a7b4589ba4c40ce7588986d6d5cebc5457cad2c2880f6bc2d42f3a5"}, + {file = "sentry_sdk-2.3.1-py2.py3-none-any.whl", hash = "sha256:c5aeb095ba226391d337dd42a6f9470d86c9fc236ecc71cfc7cd1942b45010c6"}, + {file = "sentry_sdk-2.3.1.tar.gz", hash = "sha256:139a71a19f5e9eb5d3623942491ce03cf8ebc14ea2e39ba3e6fe79560d8a5b1f"}, ] [package.dependencies] -numpy = ">=1.19.5,<1.27.0" +certifi = "*" +fastapi = {version = ">=0.79.0", optional = true, markers = "extra == \"fastapi\""} +urllib3 = ">=1.26.11" [package.extras] -dev = ["click", "doit (>=0.36.0)", "flake8", "mypy", "pycodestyle", "pydevtool", "rich-click", "typing_extensions"] -doc = ["matplotlib (>2)", "numpydoc", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-design (>=0.2.0)"] -test = ["asv", "gmpy2", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] - -[[package]] -name = "setuptools" -version = "68.1.2" -description = "Easily download, build, install, upgrade, and uninstall Python packages" +aiohttp = ["aiohttp (>=3.5)"] +anthropic = ["anthropic (>=0.16)"] +arq = ["arq (>=0.23)"] +asyncpg = ["asyncpg (>=0.23)"] +beam = ["apache-beam (>=2.12)"] +bottle = ["bottle (>=0.12.13)"] +celery = ["celery (>=3)"] +celery-redbeat = ["celery-redbeat (>=2)"] +chalice = ["chalice (>=1.16.0)"] +clickhouse-driver = ["clickhouse-driver (>=0.2.0)"] +django = ["django (>=1.8)"] +falcon = ["falcon (>=1.4)"] +fastapi = ["fastapi (>=0.79.0)"] +flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"] +grpcio = ["grpcio (>=1.21.1)", "protobuf (>=3.8.0)"] +httpx = ["httpx (>=0.16.0)"] +huey = ["huey (>=2)"] +huggingface-hub = ["huggingface-hub (>=0.22)"] +langchain = ["langchain (>=0.0.210)"] +loguru = ["loguru (>=0.5)"] +openai = ["openai (>=1.0.0)", "tiktoken (>=0.3.0)"] +opentelemetry = ["opentelemetry-distro (>=0.35b0)"] +opentelemetry-experimental = ["opentelemetry-distro (>=0.40b0,<1.0)", "opentelemetry-instrumentation-aiohttp-client (>=0.40b0,<1.0)", "opentelemetry-instrumentation-django (>=0.40b0,<1.0)", "opentelemetry-instrumentation-fastapi (>=0.40b0,<1.0)", "opentelemetry-instrumentation-flask (>=0.40b0,<1.0)", "opentelemetry-instrumentation-requests (>=0.40b0,<1.0)", "opentelemetry-instrumentation-sqlite3 (>=0.40b0,<1.0)", "opentelemetry-instrumentation-urllib (>=0.40b0,<1.0)"] +pure-eval = ["asttokens", "executing", "pure-eval"] +pymongo = ["pymongo (>=3.1)"] +pyspark = ["pyspark (>=2.4.4)"] +quart = ["blinker (>=1.1)", "quart (>=0.16.1)"] +rq = ["rq (>=0.6)"] +sanic = ["sanic (>=0.8)"] +sqlalchemy = ["sqlalchemy (>=1.2)"] +starlette = ["starlette (>=0.19.1)"] +starlite = ["starlite (>=1.48)"] +tornado = ["tornado (>=5)"] + +[[package]] +name = "shellingham" +version = "1.5.4" +description = "Tool to Detect Surrounding Shell" optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "setuptools-68.1.2-py3-none-any.whl", hash = "sha256:3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b"}, - {file = "setuptools-68.1.2.tar.gz", hash = "sha256:3d4dfa6d95f1b101d695a6160a7626e15583af71a5f52176efa5d39a054d475d"}, + {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, + {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, ] -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5,<=7.1.2)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - -[[package]] -name = "shapely" -version = "1.8.5.post1" -description = "Geometric objects, predicates, and operations" -optional = true -python-versions = ">=3.6" -files = [ - {file = "Shapely-1.8.5.post1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d048f93e42ba578b82758c15d8ae037d08e69d91d9872bca5a1895b118f4e2b0"}, - {file = "Shapely-1.8.5.post1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99ab0ddc05e44acabdbe657c599fdb9b2d82e86c5493bdae216c0c4018a82dee"}, - {file = "Shapely-1.8.5.post1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:99a2f0da0109e81e0c101a2b4cd8412f73f5f299e7b5b2deaf64cd2a100ac118"}, - {file = "Shapely-1.8.5.post1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6fe855e7d45685926b6ba00aaeb5eba5862611f7465775dacd527e081a8ced6d"}, - {file = "Shapely-1.8.5.post1-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec14ceca36f67cb48b34d02d7f65a9acae15cd72b48e303531893ba4a960f3ea"}, - {file = "Shapely-1.8.5.post1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a2b2a65fa7f97115c1cd989fe9d6f39281ca2a8a014f1d4904c1a6e34d7f25"}, - {file = "Shapely-1.8.5.post1-cp310-cp310-win32.whl", hash = "sha256:21776184516a16bf82a0c3d6d6a312b3cd15a4cabafc61ee01cf2714a82e8396"}, - {file = "Shapely-1.8.5.post1-cp310-cp310-win_amd64.whl", hash = "sha256:a354199219c8d836f280b88f2c5102c81bb044ccea45bd361dc38a79f3873714"}, - {file = "Shapely-1.8.5.post1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:783bad5f48e2708a0e2f695a34ed382e4162c795cb2f0368b39528ac1d6db7ed"}, - {file = "Shapely-1.8.5.post1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a23ef3882d6aa203dd3623a3d55d698f59bfbd9f8a3bfed52c2da05a7f0f8640"}, - {file = "Shapely-1.8.5.post1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ab38f7b5196ace05725e407cb8cab9ff66edb8e6f7bb36a398e8f73f52a7aaa2"}, - {file = "Shapely-1.8.5.post1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d086591f744be483b34628b391d741e46f2645fe37594319e0a673cc2c26bcf"}, - {file = "Shapely-1.8.5.post1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4728666fff8cccc65a07448cae72c75a8773fea061c3f4f139c44adc429b18c3"}, - {file = "Shapely-1.8.5.post1-cp311-cp311-win32.whl", hash = "sha256:84010db15eb364a52b74ea8804ef92a6a930dfc1981d17a369444b6ddec66efd"}, - {file = "Shapely-1.8.5.post1-cp311-cp311-win_amd64.whl", hash = "sha256:48dcfffb9e225c0481120f4bdf622131c8c95f342b00b158cdbe220edbbe20b6"}, - {file = "Shapely-1.8.5.post1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2fd15397638df291c427a53d641d3e6fd60458128029c8c4f487190473a69a91"}, - {file = "Shapely-1.8.5.post1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a74631e511153366c6dbe3229fa93f877e3c87ea8369cd00f1d38c76b0ed9ace"}, - {file = "Shapely-1.8.5.post1-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:66bdac74fbd1d3458fa787191a90fa0ae610f09e2a5ec398c36f968cc0ed743f"}, - {file = "Shapely-1.8.5.post1-cp36-cp36m-win32.whl", hash = "sha256:6d388c0c1bd878ed1af4583695690aa52234b02ed35f93a1c8486ff52a555838"}, - {file = "Shapely-1.8.5.post1-cp36-cp36m-win_amd64.whl", hash = "sha256:be9423d5a3577ac2e92c7e758bd8a2b205f5e51a012177a590bc46fc51eb4834"}, - {file = "Shapely-1.8.5.post1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5d7f85c2d35d39ff53c9216bc76b7641c52326f7e09aaad1789a3611a0f812f2"}, - {file = "Shapely-1.8.5.post1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:adcf8a11b98af9375e32bff91de184f33a68dc48b9cb9becad4f132fa25cfa3c"}, - {file = "Shapely-1.8.5.post1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:753ed0e21ab108bd4282405b9b659f2e985e8502b1a72b978eaa51d3496dee19"}, - {file = "Shapely-1.8.5.post1-cp37-cp37m-win32.whl", hash = "sha256:65b21243d8f6bcd421210daf1fabb9de84de2c04353c5b026173b88d17c1a581"}, - {file = "Shapely-1.8.5.post1-cp37-cp37m-win_amd64.whl", hash = "sha256:370b574c78dc5af3a198a6da5d9b3d7c04654bd2ef7e80e80a3a0992dfb2d9cd"}, - {file = "Shapely-1.8.5.post1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:532a55ee2a6c52d23d6f7d1567c8f0473635f3b270262c44e1b0c88096827e22"}, - {file = "Shapely-1.8.5.post1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3480657460e939f45a7d359ef0e172a081f249312557fe9aa78c4fd3a362d993"}, - {file = "Shapely-1.8.5.post1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b65f5d530ba91e49ffc7c589255e878d2506a8b96ffce69d3b7c4500a9a9eaf8"}, - {file = "Shapely-1.8.5.post1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:147066da0be41b147a61f8eb805dea3b13709dbc873a431ccd7306e24d712bc0"}, - {file = "Shapely-1.8.5.post1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c2822111ddc5bcfb116e6c663e403579d0fe3f147d2a97426011a191c43a7458"}, - {file = "Shapely-1.8.5.post1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b47bb6f9369e8bf3e6dbd33e6a25a47ee02b2874792a529fe04a49bf8bc0df6"}, - {file = "Shapely-1.8.5.post1-cp38-cp38-win32.whl", hash = "sha256:2e0a8c2e55f1be1312b51c92b06462ea89e6bb703fab4b114e7a846d941cfc40"}, - {file = "Shapely-1.8.5.post1-cp38-cp38-win_amd64.whl", hash = "sha256:0d885cb0cf670c1c834df3f371de8726efdf711f18e2a75da5cfa82843a7ab65"}, - {file = "Shapely-1.8.5.post1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0b4ee3132ee90f07d63db3aea316c4c065ed7a26231458dda0874414a09d6ba3"}, - {file = "Shapely-1.8.5.post1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:02dd5d7dc6e46515d88874134dc8fcdc65826bca93c3eecee59d1910c42c1b17"}, - {file = "Shapely-1.8.5.post1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c6a9a4a31cd6e86d0fbe8473ceed83d4fe760b19d949fb557ef668defafea0f6"}, - {file = "Shapely-1.8.5.post1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:38f0fbbcb8ca20c16451c966c1f527cc43968e121c8a048af19ed3e339a921cd"}, - {file = "Shapely-1.8.5.post1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:78fb9d929b8ee15cfd424b6c10879ce1907f24e05fb83310fc47d2cd27088e40"}, - {file = "Shapely-1.8.5.post1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89164e7a9776a19e29f01369a98529321994e2e4d852b92b7e01d4d9804c55bf"}, - {file = "Shapely-1.8.5.post1-cp39-cp39-win32.whl", hash = "sha256:8e59817b0fe63d34baedaabba8c393c0090f061917d18fc0bcc2f621937a8f73"}, - {file = "Shapely-1.8.5.post1-cp39-cp39-win_amd64.whl", hash = "sha256:e9c30b311de2513555ab02464ebb76115d242842b29c412f5a9aa0cac57be9f6"}, - {file = "Shapely-1.8.5.post1.tar.gz", hash = "sha256:ef3be705c3eac282a28058e6c6e5503419b250f482320df2172abcbea642c831"}, -] - -[package.extras] -all = ["numpy", "pytest", "pytest-cov"] -test = ["pytest", "pytest-cov"] -vectorized = ["numpy"] - [[package]] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -optional = false +optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, @@ -3015,109 +3308,112 @@ files = [ [[package]] name = "sniffio" -version = "1.3.0" +version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" files = [ - {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, - {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] [[package]] -name = "sounddevice" -version = "0.4.6" -description = "Play and Record Sound with Python" +name = "sortedcontainers" +version = "2.4.0" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" optional = false -python-versions = ">=3.7" +python-versions = "*" files = [ - {file = "sounddevice-0.4.6-py3-none-any.whl", hash = "sha256:5de768ba6fe56ad2b5aaa2eea794b76b73e427961c95acad2ee2ed7f866a4b20"}, - {file = "sounddevice-0.4.6-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl", hash = "sha256:8b0b806c205dd3e3cd5a97262b2482624fd21db7d47083b887090148a08051c8"}, - {file = "sounddevice-0.4.6-py3-none-win32.whl", hash = "sha256:e3ba6e674ffa8f79a591d744a1d4ab922fe5bdfd4faf8b25069a08e051010b7b"}, - {file = "sounddevice-0.4.6-py3-none-win_amd64.whl", hash = "sha256:7830d4f8f8570f2e5552942f81d96999c5fcd9a0b682d6fc5d5c5529df23be2c"}, - {file = "sounddevice-0.4.6.tar.gz", hash = "sha256:3236b78f15f0415bdf006a620cef073d0c0522851d66f4a961ed6d8eb1482fe9"}, + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, ] -[package.dependencies] -CFFI = ">=1.0" - -[package.extras] -numpy = ["NumPy"] - [[package]] -name = "speechrecognition" -version = "3.10.0" -description = "Library for performing speech recognition, with support for several engines and APIs, online and offline." +name = "sounddevice" +version = "0.4.7" +description = "Play and Record Sound with Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "SpeechRecognition-3.10.0-py2.py3-none-any.whl", hash = "sha256:7ae9966887d9909ce3e5a0c27ecc3eacfca16fd0c0829f77f552919418e86306"}, - {file = "SpeechRecognition-3.10.0.tar.gz", hash = "sha256:14131155e8a8ba00ead1b7b9b1a2fa71c845e4db5f9a5f66a33a1bd6c55c6c35"}, + {file = "sounddevice-0.4.7-py3-none-any.whl", hash = "sha256:1c3f18bfa4d9a257f5715f2ab83f2c0eb412a09f3e6a9fa73720886ca88f6bc7"}, + {file = "sounddevice-0.4.7-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl", hash = "sha256:d6ddfd341ad7412b14ca001f2c4dbf5fa2503bdc9eb15ad2c3105f6c260b698a"}, + {file = "sounddevice-0.4.7-py3-none-win32.whl", hash = "sha256:1ec1df094c468a210113aa22c4f390d5b4d9c7a73e41a6cb6ecfec83db59b380"}, + {file = "sounddevice-0.4.7-py3-none-win_amd64.whl", hash = "sha256:0c8b3543da1496f282b66a7bc54b755577ba638b1af06c146d4ac7f39d86b548"}, + {file = "sounddevice-0.4.7.tar.gz", hash = "sha256:69b386818d50a2d518607d4b973442e8d524760c7cd6c8b8be03d8c98fc4bce7"}, ] [package.dependencies] -requests = ">=2.26.0" +CFFI = ">=1.0" [package.extras] -whisper-api = ["openai"] +numpy = ["NumPy"] [[package]] name = "sqlalchemy" -version = "2.0.20" +version = "2.0.30" description = "Database Abstraction Library" -optional = false +optional = true python-versions = ">=3.7" files = [ - {file = "SQLAlchemy-2.0.20-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759b51346aa388c2e606ee206c0bc6f15a5299f6174d1e10cadbe4530d3c7a98"}, - {file = "SQLAlchemy-2.0.20-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1506e988ebeaaf316f183da601f24eedd7452e163010ea63dbe52dc91c7fc70e"}, - {file = "SQLAlchemy-2.0.20-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5768c268df78bacbde166b48be788b83dddaa2a5974b8810af422ddfe68a9bc8"}, - {file = "SQLAlchemy-2.0.20-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3f0dd6d15b6dc8b28a838a5c48ced7455c3e1fb47b89da9c79cc2090b072a50"}, - {file = "SQLAlchemy-2.0.20-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:243d0fb261f80a26774829bc2cee71df3222587ac789b7eaf6555c5b15651eed"}, - {file = "SQLAlchemy-2.0.20-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6eb6d77c31e1bf4268b4d61b549c341cbff9842f8e115ba6904249c20cb78a61"}, - {file = "SQLAlchemy-2.0.20-cp310-cp310-win32.whl", hash = "sha256:bcb04441f370cbe6e37c2b8d79e4af9e4789f626c595899d94abebe8b38f9a4d"}, - {file = "SQLAlchemy-2.0.20-cp310-cp310-win_amd64.whl", hash = "sha256:d32b5ffef6c5bcb452723a496bad2d4c52b346240c59b3e6dba279f6dcc06c14"}, - {file = "SQLAlchemy-2.0.20-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd81466bdbc82b060c3c110b2937ab65ace41dfa7b18681fdfad2f37f27acdd7"}, - {file = "SQLAlchemy-2.0.20-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6fe7d61dc71119e21ddb0094ee994418c12f68c61b3d263ebaae50ea8399c4d4"}, - {file = "SQLAlchemy-2.0.20-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4e571af672e1bb710b3cc1a9794b55bce1eae5aed41a608c0401885e3491179"}, - {file = "SQLAlchemy-2.0.20-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3364b7066b3c7f4437dd345d47271f1251e0cfb0aba67e785343cdbdb0fff08c"}, - {file = "SQLAlchemy-2.0.20-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1be86ccea0c965a1e8cd6ccf6884b924c319fcc85765f16c69f1ae7148eba64b"}, - {file = "SQLAlchemy-2.0.20-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1d35d49a972649b5080557c603110620a86aa11db350d7a7cb0f0a3f611948a0"}, - {file = "SQLAlchemy-2.0.20-cp311-cp311-win32.whl", hash = "sha256:27d554ef5d12501898d88d255c54eef8414576f34672e02fe96d75908993cf53"}, - {file = "SQLAlchemy-2.0.20-cp311-cp311-win_amd64.whl", hash = "sha256:411e7f140200c02c4b953b3dbd08351c9f9818d2bd591b56d0fa0716bd014f1e"}, - {file = "SQLAlchemy-2.0.20-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3c6aceebbc47db04f2d779db03afeaa2c73ea3f8dcd3987eb9efdb987ffa09a3"}, - {file = "SQLAlchemy-2.0.20-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d3f175410a6db0ad96b10bfbb0a5530ecd4fcf1e2b5d83d968dd64791f810ed"}, - {file = "SQLAlchemy-2.0.20-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea8186be85da6587456c9ddc7bf480ebad1a0e6dcbad3967c4821233a4d4df57"}, - {file = "SQLAlchemy-2.0.20-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c3d99ba99007dab8233f635c32b5cd24fb1df8d64e17bc7df136cedbea427897"}, - {file = "SQLAlchemy-2.0.20-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:76fdfc0f6f5341987474ff48e7a66c3cd2b8a71ddda01fa82fedb180b961630a"}, - {file = "SQLAlchemy-2.0.20-cp37-cp37m-win32.whl", hash = "sha256:d3793dcf5bc4d74ae1e9db15121250c2da476e1af8e45a1d9a52b1513a393459"}, - {file = "SQLAlchemy-2.0.20-cp37-cp37m-win_amd64.whl", hash = "sha256:79fde625a0a55220d3624e64101ed68a059c1c1f126c74f08a42097a72ff66a9"}, - {file = "SQLAlchemy-2.0.20-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:599ccd23a7146e126be1c7632d1d47847fa9f333104d03325c4e15440fc7d927"}, - {file = "SQLAlchemy-2.0.20-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1a58052b5a93425f656675673ef1f7e005a3b72e3f2c91b8acca1b27ccadf5f4"}, - {file = "SQLAlchemy-2.0.20-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79543f945be7a5ada9943d555cf9b1531cfea49241809dd1183701f94a748624"}, - {file = "SQLAlchemy-2.0.20-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63e73da7fb030ae0a46a9ffbeef7e892f5def4baf8064786d040d45c1d6d1dc5"}, - {file = "SQLAlchemy-2.0.20-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3ce5e81b800a8afc870bb8e0a275d81957e16f8c4b62415a7b386f29a0cb9763"}, - {file = "SQLAlchemy-2.0.20-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb0d3e94c2a84215532d9bcf10229476ffd3b08f481c53754113b794afb62d14"}, - {file = "SQLAlchemy-2.0.20-cp38-cp38-win32.whl", hash = "sha256:8dd77fd6648b677d7742d2c3cc105a66e2681cc5e5fb247b88c7a7b78351cf74"}, - {file = "SQLAlchemy-2.0.20-cp38-cp38-win_amd64.whl", hash = "sha256:6f8a934f9dfdf762c844e5164046a9cea25fabbc9ec865c023fe7f300f11ca4a"}, - {file = "SQLAlchemy-2.0.20-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:26a3399eaf65e9ab2690c07bd5cf898b639e76903e0abad096cd609233ce5208"}, - {file = "SQLAlchemy-2.0.20-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4cde2e1096cbb3e62002efdb7050113aa5f01718035ba9f29f9d89c3758e7e4e"}, - {file = "SQLAlchemy-2.0.20-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1b09ba72e4e6d341bb5bdd3564f1cea6095d4c3632e45dc69375a1dbe4e26ec"}, - {file = "SQLAlchemy-2.0.20-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b74eeafaa11372627ce94e4dc88a6751b2b4d263015b3523e2b1e57291102f0"}, - {file = "SQLAlchemy-2.0.20-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:77d37c1b4e64c926fa3de23e8244b964aab92963d0f74d98cbc0783a9e04f501"}, - {file = "SQLAlchemy-2.0.20-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:eefebcc5c555803065128401a1e224a64607259b5eb907021bf9b175f315d2a6"}, - {file = "SQLAlchemy-2.0.20-cp39-cp39-win32.whl", hash = "sha256:3423dc2a3b94125094897118b52bdf4d37daf142cbcf26d48af284b763ab90e9"}, - {file = "SQLAlchemy-2.0.20-cp39-cp39-win_amd64.whl", hash = "sha256:5ed61e3463021763b853628aef8bc5d469fe12d95f82c74ef605049d810f3267"}, - {file = "SQLAlchemy-2.0.20-py3-none-any.whl", hash = "sha256:63a368231c53c93e2b67d0c5556a9836fdcd383f7e3026a39602aad775b14acf"}, - {file = "SQLAlchemy-2.0.20.tar.gz", hash = "sha256:ca8a5ff2aa7f3ade6c498aaafce25b1eaeabe4e42b73e25519183e4566a16fc6"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3b48154678e76445c7ded1896715ce05319f74b1e73cf82d4f8b59b46e9c0ddc"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2753743c2afd061bb95a61a51bbb6a1a11ac1c44292fad898f10c9839a7f75b2"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7bfc726d167f425d4c16269a9a10fe8630ff6d14b683d588044dcef2d0f6be7"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4f61ada6979223013d9ab83a3ed003ded6959eae37d0d685db2c147e9143797"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a365eda439b7a00732638f11072907c1bc8e351c7665e7e5da91b169af794af"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bba002a9447b291548e8d66fd8c96a6a7ed4f2def0bb155f4f0a1309fd2735d5"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-win32.whl", hash = "sha256:0138c5c16be3600923fa2169532205d18891b28afa817cb49b50e08f62198bb8"}, + {file = "SQLAlchemy-2.0.30-cp310-cp310-win_amd64.whl", hash = "sha256:99650e9f4cf3ad0d409fed3eec4f071fadd032e9a5edc7270cd646a26446feeb"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:955991a09f0992c68a499791a753523f50f71a6885531568404fa0f231832aa0"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f69e4c756ee2686767eb80f94c0125c8b0a0b87ede03eacc5c8ae3b54b99dc46"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69c9db1ce00e59e8dd09d7bae852a9add716efdc070a3e2068377e6ff0d6fdaa"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1429a4b0f709f19ff3b0cf13675b2b9bfa8a7e79990003207a011c0db880a13"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:efedba7e13aa9a6c8407c48facfdfa108a5a4128e35f4c68f20c3407e4376aa9"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:16863e2b132b761891d6c49f0a0f70030e0bcac4fd208117f6b7e053e68668d0"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-win32.whl", hash = "sha256:2ecabd9ccaa6e914e3dbb2aa46b76dede7eadc8cbf1b8083c94d936bcd5ffb49"}, + {file = "SQLAlchemy-2.0.30-cp311-cp311-win_amd64.whl", hash = "sha256:0b3f4c438e37d22b83e640f825ef0f37b95db9aa2d68203f2c9549375d0b2260"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5a79d65395ac5e6b0c2890935bad892eabb911c4aa8e8015067ddb37eea3d56c"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9a5baf9267b752390252889f0c802ea13b52dfee5e369527da229189b8bd592e"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cb5a646930c5123f8461f6468901573f334c2c63c795b9af350063a736d0134"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:296230899df0b77dec4eb799bcea6fbe39a43707ce7bb166519c97b583cfcab3"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c62d401223f468eb4da32627bffc0c78ed516b03bb8a34a58be54d618b74d472"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3b69e934f0f2b677ec111b4d83f92dc1a3210a779f69bf905273192cf4ed433e"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-win32.whl", hash = "sha256:77d2edb1f54aff37e3318f611637171e8ec71472f1fdc7348b41dcb226f93d90"}, + {file = "SQLAlchemy-2.0.30-cp312-cp312-win_amd64.whl", hash = "sha256:b6c7ec2b1f4969fc19b65b7059ed00497e25f54069407a8701091beb69e591a5"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5a8e3b0a7e09e94be7510d1661339d6b52daf202ed2f5b1f9f48ea34ee6f2d57"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b60203c63e8f984df92035610c5fb76d941254cf5d19751faab7d33b21e5ddc0"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1dc3eabd8c0232ee8387fbe03e0a62220a6f089e278b1f0aaf5e2d6210741ad"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:40ad017c672c00b9b663fcfcd5f0864a0a97828e2ee7ab0c140dc84058d194cf"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e42203d8d20dc704604862977b1470a122e4892791fe3ed165f041e4bf447a1b"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-win32.whl", hash = "sha256:2a4f4da89c74435f2bc61878cd08f3646b699e7d2eba97144030d1be44e27584"}, + {file = "SQLAlchemy-2.0.30-cp37-cp37m-win_amd64.whl", hash = "sha256:b6bf767d14b77f6a18b6982cbbf29d71bede087edae495d11ab358280f304d8e"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc0c53579650a891f9b83fa3cecd4e00218e071d0ba00c4890f5be0c34887ed3"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:311710f9a2ee235f1403537b10c7687214bb1f2b9ebb52702c5aa4a77f0b3af7"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:408f8b0e2c04677e9c93f40eef3ab22f550fecb3011b187f66a096395ff3d9fd"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37a4b4fb0dd4d2669070fb05b8b8824afd0af57587393015baee1cf9890242d9"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a943d297126c9230719c27fcbbeab57ecd5d15b0bd6bfd26e91bfcfe64220621"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0a089e218654e740a41388893e090d2e2c22c29028c9d1353feb38638820bbeb"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-win32.whl", hash = "sha256:fa561138a64f949f3e889eb9ab8c58e1504ab351d6cf55259dc4c248eaa19da6"}, + {file = "SQLAlchemy-2.0.30-cp38-cp38-win_amd64.whl", hash = "sha256:7d74336c65705b986d12a7e337ba27ab2b9d819993851b140efdf029248e818e"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae8c62fe2480dd61c532ccafdbce9b29dacc126fe8be0d9a927ca3e699b9491a"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2383146973a15435e4717f94c7509982770e3e54974c71f76500a0136f22810b"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8409de825f2c3b62ab15788635ccaec0c881c3f12a8af2b12ae4910a0a9aeef6"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0094c5dc698a5f78d3d1539853e8ecec02516b62b8223c970c86d44e7a80f6c7"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:edc16a50f5e1b7a06a2dcc1f2205b0b961074c123ed17ebda726f376a5ab0953"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f7703c2010355dd28f53deb644a05fc30f796bd8598b43f0ba678878780b6e4c"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-win32.whl", hash = "sha256:1f9a727312ff6ad5248a4367358e2cf7e625e98b1028b1d7ab7b806b7d757513"}, + {file = "SQLAlchemy-2.0.30-cp39-cp39-win_amd64.whl", hash = "sha256:a0ef36b28534f2a5771191be6edb44cc2673c7b2edf6deac6562400288664221"}, + {file = "SQLAlchemy-2.0.30-py3-none-any.whl", hash = "sha256:7108d569d3990c71e26a42f60474b4c02c8586c4681af5fd67e51a044fdea86a"}, + {file = "SQLAlchemy-2.0.30.tar.gz", hash = "sha256:2b1708916730f4830bc69d6f49d37f7698b5bd7530aca7f04f785f8849e95255"}, ] [package.dependencies] greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} -typing-extensions = ">=4.2.0" +typing-extensions = ">=4.6.0" [package.extras] aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] -aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"] +aioodbc = ["aioodbc", "greenlet (!=0.4.17)"] +aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"] asyncio = ["greenlet (!=0.4.17)"] asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] @@ -3127,7 +3423,7 @@ mssql-pyodbc = ["pyodbc"] mypy = ["mypy (>=0.910)"] mysql = ["mysqlclient (>=1.4.0)"] mysql-connector = ["mysql-connector-python"] -oracle = ["cx-oracle (>=7)"] +oracle = ["cx_oracle (>=8)"] oracle-oracledb = ["oracledb (>=1.0.1)"] postgresql = ["psycopg2 (>=2.7)"] postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] @@ -3137,17 +3433,17 @@ postgresql-psycopg2binary = ["psycopg2-binary"] postgresql-psycopg2cffi = ["psycopg2cffi"] postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] pymysql = ["pymysql"] -sqlcipher = ["sqlcipher3-binary"] +sqlcipher = ["sqlcipher3_binary"] [[package]] name = "stack-data" -version = "0.6.2" +version = "0.6.3" description = "Extract data from python stack frames and tracebacks for informative displays" optional = true python-versions = "*" files = [ - {file = "stack_data-0.6.2-py3-none-any.whl", hash = "sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8"}, - {file = "stack_data-0.6.2.tar.gz", hash = "sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815"}, + {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, + {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, ] [package.dependencies] @@ -3160,89 +3456,204 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] [[package]] name = "starlette" -version = "0.27.0" +version = "0.37.2" description = "The little ASGI library that shines." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"}, - {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"}, + {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"}, + {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"}, ] [package.dependencies] anyio = ">=3.4.0,<5" -typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [package.extras] -full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] +full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"] [[package]] name = "tenacity" -version = "8.2.3" +version = "8.3.0" description = "Retry code until it succeeds" -optional = false -python-versions = ">=3.7" +optional = true +python-versions = ">=3.8" +files = [ + {file = "tenacity-8.3.0-py3-none-any.whl", hash = "sha256:3649f6443dbc0d9b01b9d8020a9c4ec7a1ff5f6f3c6c8a036ef371f573fe9185"}, + {file = "tenacity-8.3.0.tar.gz", hash = "sha256:953d4e6ad24357bceffbc9707bc74349aca9d245f68eb65419cf0c249a1949a2"}, +] + +[package.extras] +doc = ["reno", "sphinx"] +test = ["pytest", "tornado (>=4.5)", "typeguard"] + +[[package]] +name = "tiktoken" +version = "0.7.0" +description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" +optional = true +python-versions = ">=3.8" files = [ - {file = "tenacity-8.2.3-py3-none-any.whl", hash = "sha256:ce510e327a630c9e1beaf17d42e6ffacc88185044ad85cf74c0a8887c6a0f88c"}, - {file = "tenacity-8.2.3.tar.gz", hash = "sha256:5398ef0d78e63f40007c1fb4c0bff96e1911394d2fa8d194f77619c05ff6cc8a"}, + {file = "tiktoken-0.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485f3cc6aba7c6b6ce388ba634fbba656d9ee27f766216f45146beb4ac18b25f"}, + {file = "tiktoken-0.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e54be9a2cd2f6d6ffa3517b064983fb695c9a9d8aa7d574d1ef3c3f931a99225"}, + {file = "tiktoken-0.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79383a6e2c654c6040e5f8506f3750db9ddd71b550c724e673203b4f6b4b4590"}, + {file = "tiktoken-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d4511c52caacf3c4981d1ae2df85908bd31853f33d30b345c8b6830763f769c"}, + {file = "tiktoken-0.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13c94efacdd3de9aff824a788353aa5749c0faee1fbe3816df365ea450b82311"}, + {file = "tiktoken-0.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8e58c7eb29d2ab35a7a8929cbeea60216a4ccdf42efa8974d8e176d50c9a3df5"}, + {file = "tiktoken-0.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:21a20c3bd1dd3e55b91c1331bf25f4af522c525e771691adbc9a69336fa7f702"}, + {file = "tiktoken-0.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:10c7674f81e6e350fcbed7c09a65bca9356eaab27fb2dac65a1e440f2bcfe30f"}, + {file = "tiktoken-0.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:084cec29713bc9d4189a937f8a35dbdfa785bd1235a34c1124fe2323821ee93f"}, + {file = "tiktoken-0.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:811229fde1652fedcca7c6dfe76724d0908775b353556d8a71ed74d866f73f7b"}, + {file = "tiktoken-0.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86b6e7dc2e7ad1b3757e8a24597415bafcfb454cebf9a33a01f2e6ba2e663992"}, + {file = "tiktoken-0.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1063c5748be36344c7e18c7913c53e2cca116764c2080177e57d62c7ad4576d1"}, + {file = "tiktoken-0.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:20295d21419bfcca092644f7e2f2138ff947a6eb8cfc732c09cc7d76988d4a89"}, + {file = "tiktoken-0.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:959d993749b083acc57a317cbc643fb85c014d055b2119b739487288f4e5d1cb"}, + {file = "tiktoken-0.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:71c55d066388c55a9c00f61d2c456a6086673ab7dec22dd739c23f77195b1908"}, + {file = "tiktoken-0.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:09ed925bccaa8043e34c519fbb2f99110bd07c6fd67714793c21ac298e449410"}, + {file = "tiktoken-0.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03c6c40ff1db0f48a7b4d2dafeae73a5607aacb472fa11f125e7baf9dce73704"}, + {file = "tiktoken-0.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d20b5c6af30e621b4aca094ee61777a44118f52d886dbe4f02b70dfe05c15350"}, + {file = "tiktoken-0.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d427614c3e074004efa2f2411e16c826f9df427d3c70a54725cae860f09e4bf4"}, + {file = "tiktoken-0.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8c46d7af7b8c6987fac9b9f61041b452afe92eb087d29c9ce54951280f899a97"}, + {file = "tiktoken-0.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:0bc603c30b9e371e7c4c7935aba02af5994a909fc3c0fe66e7004070858d3f8f"}, + {file = "tiktoken-0.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2398fecd38c921bcd68418675a6d155fad5f5e14c2e92fcf5fe566fa5485a858"}, + {file = "tiktoken-0.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f5f6afb52fb8a7ea1c811e435e4188f2bef81b5e0f7a8635cc79b0eef0193d6"}, + {file = "tiktoken-0.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:861f9ee616766d736be4147abac500732b505bf7013cfaf019b85892637f235e"}, + {file = "tiktoken-0.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54031f95c6939f6b78122c0aa03a93273a96365103793a22e1793ee86da31685"}, + {file = "tiktoken-0.7.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fffdcb319b614cf14f04d02a52e26b1d1ae14a570f90e9b55461a72672f7b13d"}, + {file = "tiktoken-0.7.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c72baaeaefa03ff9ba9688624143c858d1f6b755bb85d456d59e529e17234769"}, + {file = "tiktoken-0.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:131b8aeb043a8f112aad9f46011dced25d62629091e51d9dc1adbf4a1cc6aa98"}, + {file = "tiktoken-0.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cabc6dc77460df44ec5b879e68692c63551ae4fae7460dd4ff17181df75f1db7"}, + {file = "tiktoken-0.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8d57f29171255f74c0aeacd0651e29aa47dff6f070cb9f35ebc14c82278f3b25"}, + {file = "tiktoken-0.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ee92776fdbb3efa02a83f968c19d4997a55c8e9ce7be821ceee04a1d1ee149c"}, + {file = "tiktoken-0.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e215292e99cb41fbc96988ef62ea63bb0ce1e15f2c147a61acc319f8b4cbe5bf"}, + {file = "tiktoken-0.7.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8a81bac94769cab437dd3ab0b8a4bc4e0f9cf6835bcaa88de71f39af1791727a"}, + {file = "tiktoken-0.7.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d6d73ea93e91d5ca771256dfc9d1d29f5a554b83821a1dc0891987636e0ae226"}, + {file = "tiktoken-0.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:2bcb28ddf79ffa424f171dfeef9a4daff61a94c631ca6813f43967cb263b83b9"}, + {file = "tiktoken-0.7.0.tar.gz", hash = "sha256:1077266e949c24e0291f6c350433c6f0971365ece2b173a23bc3b9f9defef6b6"}, ] +[package.dependencies] +regex = ">=2022.1.18" +requests = ">=2.26.0" + [package.extras] -doc = ["reno", "sphinx", "tornado (>=4.5)"] +blobfile = ["blobfile (>=2)"] [[package]] name = "tokenizers" -version = "0.13.3" -description = "Fast and Customizable Tokenizers" -optional = false -python-versions = "*" +version = "0.19.1" +description = "" +optional = true +python-versions = ">=3.7" files = [ - {file = "tokenizers-0.13.3-cp310-cp310-macosx_10_11_x86_64.whl", hash = "sha256:f3835c5be51de8c0a092058a4d4380cb9244fb34681fd0a295fbf0a52a5fdf33"}, - {file = "tokenizers-0.13.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:4ef4c3e821730f2692489e926b184321e887f34fb8a6b80b8096b966ba663d07"}, - {file = "tokenizers-0.13.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5fd1a6a25353e9aa762e2aae5a1e63883cad9f4e997c447ec39d071020459bc"}, - {file = "tokenizers-0.13.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee0b1b311d65beab83d7a41c56a1e46ab732a9eed4460648e8eb0bd69fc2d059"}, - {file = "tokenizers-0.13.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ef4215284df1277dadbcc5e17d4882bda19f770d02348e73523f7e7d8b8d396"}, - {file = "tokenizers-0.13.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4d53976079cff8a033f778fb9adca2d9d69d009c02fa2d71a878b5f3963ed30"}, - {file = "tokenizers-0.13.3-cp310-cp310-win32.whl", hash = "sha256:1f0e3b4c2ea2cd13238ce43548959c118069db7579e5d40ec270ad77da5833ce"}, - {file = "tokenizers-0.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:89649c00d0d7211e8186f7a75dfa1db6996f65edce4b84821817eadcc2d3c79e"}, - {file = "tokenizers-0.13.3-cp311-cp311-macosx_10_11_universal2.whl", hash = "sha256:56b726e0d2bbc9243872b0144515ba684af5b8d8cd112fb83ee1365e26ec74c8"}, - {file = "tokenizers-0.13.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:cc5c022ce692e1f499d745af293ab9ee6f5d92538ed2faf73f9708c89ee59ce6"}, - {file = "tokenizers-0.13.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f55c981ac44ba87c93e847c333e58c12abcbb377a0c2f2ef96e1a266e4184ff2"}, - {file = "tokenizers-0.13.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f247eae99800ef821a91f47c5280e9e9afaeed9980fc444208d5aa6ba69ff148"}, - {file = "tokenizers-0.13.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b3e3215d048e94f40f1c95802e45dcc37c5b05eb46280fc2ccc8cd351bff839"}, - {file = "tokenizers-0.13.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ba2b0bf01777c9b9bc94b53764d6684554ce98551fec496f71bc5be3a03e98b"}, - {file = "tokenizers-0.13.3-cp311-cp311-win32.whl", hash = "sha256:cc78d77f597d1c458bf0ea7c2a64b6aa06941c7a99cb135b5969b0278824d808"}, - {file = "tokenizers-0.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:ecf182bf59bd541a8876deccf0360f5ae60496fd50b58510048020751cf1724c"}, - {file = "tokenizers-0.13.3-cp37-cp37m-macosx_10_11_x86_64.whl", hash = "sha256:0527dc5436a1f6bf2c0327da3145687d3bcfbeab91fed8458920093de3901b44"}, - {file = "tokenizers-0.13.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07cbb2c307627dc99b44b22ef05ff4473aa7c7cc1fec8f0a8b37d8a64b1a16d2"}, - {file = "tokenizers-0.13.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4560dbdeaae5b7ee0d4e493027e3de6d53c991b5002d7ff95083c99e11dd5ac0"}, - {file = "tokenizers-0.13.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64064bd0322405c9374305ab9b4c07152a1474370327499911937fd4a76d004b"}, - {file = "tokenizers-0.13.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8c6e2ab0f2e3d939ca66aa1d596602105fe33b505cd2854a4c1717f704c51de"}, - {file = "tokenizers-0.13.3-cp37-cp37m-win32.whl", hash = "sha256:6cc29d410768f960db8677221e497226e545eaaea01aa3613fa0fdf2cc96cff4"}, - {file = "tokenizers-0.13.3-cp37-cp37m-win_amd64.whl", hash = "sha256:fc2a7fdf864554a0dacf09d32e17c0caa9afe72baf9dd7ddedc61973bae352d8"}, - {file = "tokenizers-0.13.3-cp38-cp38-macosx_10_11_x86_64.whl", hash = "sha256:8791dedba834c1fc55e5f1521be325ea3dafb381964be20684b92fdac95d79b7"}, - {file = "tokenizers-0.13.3-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:d607a6a13718aeb20507bdf2b96162ead5145bbbfa26788d6b833f98b31b26e1"}, - {file = "tokenizers-0.13.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3791338f809cd1bf8e4fee6b540b36822434d0c6c6bc47162448deee3f77d425"}, - {file = "tokenizers-0.13.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2f35f30e39e6aab8716f07790f646bdc6e4a853816cc49a95ef2a9016bf9ce6"}, - {file = "tokenizers-0.13.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:310204dfed5aa797128b65d63538a9837cbdd15da2a29a77d67eefa489edda26"}, - {file = "tokenizers-0.13.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0f9b92ea052305166559f38498b3b0cae159caea712646648aaa272f7160963"}, - {file = "tokenizers-0.13.3-cp38-cp38-win32.whl", hash = "sha256:9a3fa134896c3c1f0da6e762d15141fbff30d094067c8f1157b9fdca593b5806"}, - {file = "tokenizers-0.13.3-cp38-cp38-win_amd64.whl", hash = "sha256:8e7b0cdeace87fa9e760e6a605e0ae8fc14b7d72e9fc19c578116f7287bb873d"}, - {file = "tokenizers-0.13.3-cp39-cp39-macosx_10_11_x86_64.whl", hash = "sha256:00cee1e0859d55507e693a48fa4aef07060c4bb6bd93d80120e18fea9371c66d"}, - {file = "tokenizers-0.13.3-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:a23ff602d0797cea1d0506ce69b27523b07e70f6dda982ab8cf82402de839088"}, - {file = "tokenizers-0.13.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70ce07445050b537d2696022dafb115307abdffd2a5c106f029490f84501ef97"}, - {file = "tokenizers-0.13.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:280ffe95f50eaaf655b3a1dc7ff1d9cf4777029dbbc3e63a74e65a056594abc3"}, - {file = "tokenizers-0.13.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97acfcec592f7e9de8cadcdcda50a7134423ac8455c0166b28c9ff04d227b371"}, - {file = "tokenizers-0.13.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd7730c98a3010cd4f523465867ff95cd9d6430db46676ce79358f65ae39797b"}, - {file = "tokenizers-0.13.3-cp39-cp39-win32.whl", hash = "sha256:48625a108029cb1ddf42e17a81b5a3230ba6888a70c9dc14e81bc319e812652d"}, - {file = "tokenizers-0.13.3-cp39-cp39-win_amd64.whl", hash = "sha256:bc0a6f1ba036e482db6453571c9e3e60ecd5489980ffd95d11dc9f960483d783"}, - {file = "tokenizers-0.13.3.tar.gz", hash = "sha256:2e546dbb68b623008a5442353137fbb0123d311a6d7ba52f2667c8862a75af2e"}, -] - -[package.extras] -dev = ["black (==22.3)", "datasets", "numpy", "pytest", "requests"] + {file = "tokenizers-0.19.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:952078130b3d101e05ecfc7fc3640282d74ed26bcf691400f872563fca15ac97"}, + {file = "tokenizers-0.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82c8b8063de6c0468f08e82c4e198763e7b97aabfe573fd4cf7b33930ca4df77"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f03727225feaf340ceeb7e00604825addef622d551cbd46b7b775ac834c1e1c4"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:453e4422efdfc9c6b6bf2eae00d5e323f263fff62b29a8c9cd526c5003f3f642"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:02e81bf089ebf0e7f4df34fa0207519f07e66d8491d963618252f2e0729e0b46"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b07c538ba956843833fee1190cf769c60dc62e1cf934ed50d77d5502194d63b1"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e28cab1582e0eec38b1f38c1c1fb2e56bce5dc180acb1724574fc5f47da2a4fe"}, + {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b01afb7193d47439f091cd8f070a1ced347ad0f9144952a30a41836902fe09e"}, + {file = "tokenizers-0.19.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7fb297edec6c6841ab2e4e8f357209519188e4a59b557ea4fafcf4691d1b4c98"}, + {file = "tokenizers-0.19.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2e8a3dd055e515df7054378dc9d6fa8c8c34e1f32777fb9a01fea81496b3f9d3"}, + {file = "tokenizers-0.19.1-cp310-none-win32.whl", hash = "sha256:7ff898780a155ea053f5d934925f3902be2ed1f4d916461e1a93019cc7250837"}, + {file = "tokenizers-0.19.1-cp310-none-win_amd64.whl", hash = "sha256:bea6f9947e9419c2fda21ae6c32871e3d398cba549b93f4a65a2d369662d9403"}, + {file = "tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5c88d1481f1882c2e53e6bb06491e474e420d9ac7bdff172610c4f9ad3898059"}, + {file = "tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ddf672ed719b4ed82b51499100f5417d7d9f6fb05a65e232249268f35de5ed14"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:dadc509cc8a9fe460bd274c0e16ac4184d0958117cf026e0ea8b32b438171594"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfedf31824ca4915b511b03441784ff640378191918264268e6923da48104acc"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac11016d0a04aa6487b1513a3a36e7bee7eec0e5d30057c9c0408067345c48d2"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76951121890fea8330d3a0df9a954b3f2a37e3ec20e5b0530e9a0044ca2e11fe"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b342d2ce8fc8d00f376af068e3274e2e8649562e3bc6ae4a67784ded6b99428d"}, + {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d16ff18907f4909dca9b076b9c2d899114dd6abceeb074eca0c93e2353f943aa"}, + {file = "tokenizers-0.19.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:706a37cc5332f85f26efbe2bdc9ef8a9b372b77e4645331a405073e4b3a8c1c6"}, + {file = "tokenizers-0.19.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:16baac68651701364b0289979ecec728546133e8e8fe38f66fe48ad07996b88b"}, + {file = "tokenizers-0.19.1-cp311-none-win32.whl", hash = "sha256:9ed240c56b4403e22b9584ee37d87b8bfa14865134e3e1c3fb4b2c42fafd3256"}, + {file = "tokenizers-0.19.1-cp311-none-win_amd64.whl", hash = "sha256:ad57d59341710b94a7d9dbea13f5c1e7d76fd8d9bcd944a7a6ab0b0da6e0cc66"}, + {file = "tokenizers-0.19.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:621d670e1b1c281a1c9698ed89451395d318802ff88d1fc1accff0867a06f153"}, + {file = "tokenizers-0.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d924204a3dbe50b75630bd16f821ebda6a5f729928df30f582fb5aade90c818a"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4f3fefdc0446b1a1e6d81cd4c07088ac015665d2e812f6dbba4a06267d1a2c95"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9620b78e0b2d52ef07b0d428323fb34e8ea1219c5eac98c2596311f20f1f9266"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04ce49e82d100594715ac1b2ce87d1a36e61891a91de774755f743babcd0dd52"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5c2ff13d157afe413bf7e25789879dd463e5a4abfb529a2d8f8473d8042e28f"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3174c76efd9d08f836bfccaca7cfec3f4d1c0a4cf3acbc7236ad577cc423c840"}, + {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c9d5b6c0e7a1e979bec10ff960fae925e947aab95619a6fdb4c1d8ff3708ce3"}, + {file = "tokenizers-0.19.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a179856d1caee06577220ebcfa332af046d576fb73454b8f4d4b0ba8324423ea"}, + {file = "tokenizers-0.19.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:952b80dac1a6492170f8c2429bd11fcaa14377e097d12a1dbe0ef2fb2241e16c"}, + {file = "tokenizers-0.19.1-cp312-none-win32.whl", hash = "sha256:01d62812454c188306755c94755465505836fd616f75067abcae529c35edeb57"}, + {file = "tokenizers-0.19.1-cp312-none-win_amd64.whl", hash = "sha256:b70bfbe3a82d3e3fb2a5e9b22a39f8d1740c96c68b6ace0086b39074f08ab89a"}, + {file = "tokenizers-0.19.1-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:bb9dfe7dae85bc6119d705a76dc068c062b8b575abe3595e3c6276480e67e3f1"}, + {file = "tokenizers-0.19.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:1f0360cbea28ea99944ac089c00de7b2e3e1c58f479fb8613b6d8d511ce98267"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:71e3ec71f0e78780851fef28c2a9babe20270404c921b756d7c532d280349214"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b82931fa619dbad979c0ee8e54dd5278acc418209cc897e42fac041f5366d626"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e8ff5b90eabdcdaa19af697885f70fe0b714ce16709cf43d4952f1f85299e73a"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e742d76ad84acbdb1a8e4694f915fe59ff6edc381c97d6dfdd054954e3478ad4"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d8c5d59d7b59885eab559d5bc082b2985555a54cda04dda4c65528d90ad252ad"}, + {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b2da5c32ed869bebd990c9420df49813709e953674c0722ff471a116d97b22d"}, + {file = "tokenizers-0.19.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:638e43936cc8b2cbb9f9d8dde0fe5e7e30766a3318d2342999ae27f68fdc9bd6"}, + {file = "tokenizers-0.19.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:78e769eb3b2c79687d9cb0f89ef77223e8e279b75c0a968e637ca7043a84463f"}, + {file = "tokenizers-0.19.1-cp37-none-win32.whl", hash = "sha256:72791f9bb1ca78e3ae525d4782e85272c63faaef9940d92142aa3eb79f3407a3"}, + {file = "tokenizers-0.19.1-cp37-none-win_amd64.whl", hash = "sha256:f3bbb7a0c5fcb692950b041ae11067ac54826204318922da754f908d95619fbc"}, + {file = "tokenizers-0.19.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:07f9295349bbbcedae8cefdbcfa7f686aa420be8aca5d4f7d1ae6016c128c0c5"}, + {file = "tokenizers-0.19.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:10a707cc6c4b6b183ec5dbfc5c34f3064e18cf62b4a938cb41699e33a99e03c1"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6309271f57b397aa0aff0cbbe632ca9d70430839ca3178bf0f06f825924eca22"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ad23d37d68cf00d54af184586d79b84075ada495e7c5c0f601f051b162112dc"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:427c4f0f3df9109314d4f75b8d1f65d9477033e67ffaec4bca53293d3aca286d"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e83a31c9cf181a0a3ef0abad2b5f6b43399faf5da7e696196ddd110d332519ee"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c27b99889bd58b7e301468c0838c5ed75e60c66df0d4db80c08f43462f82e0d3"}, + {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bac0b0eb952412b0b196ca7a40e7dce4ed6f6926489313414010f2e6b9ec2adf"}, + {file = "tokenizers-0.19.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8a6298bde623725ca31c9035a04bf2ef63208d266acd2bed8c2cb7d2b7d53ce6"}, + {file = "tokenizers-0.19.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:08a44864e42fa6d7d76d7be4bec62c9982f6f6248b4aa42f7302aa01e0abfd26"}, + {file = "tokenizers-0.19.1-cp38-none-win32.whl", hash = "sha256:1de5bc8652252d9357a666e609cb1453d4f8e160eb1fb2830ee369dd658e8975"}, + {file = "tokenizers-0.19.1-cp38-none-win_amd64.whl", hash = "sha256:0bcce02bf1ad9882345b34d5bd25ed4949a480cf0e656bbd468f4d8986f7a3f1"}, + {file = "tokenizers-0.19.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:0b9394bd204842a2a1fd37fe29935353742be4a3460b6ccbaefa93f58a8df43d"}, + {file = "tokenizers-0.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4692ab92f91b87769d950ca14dbb61f8a9ef36a62f94bad6c82cc84a51f76f6a"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6258c2ef6f06259f70a682491c78561d492e885adeaf9f64f5389f78aa49a051"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c85cf76561fbd01e0d9ea2d1cbe711a65400092bc52b5242b16cfd22e51f0c58"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:670b802d4d82bbbb832ddb0d41df7015b3e549714c0e77f9bed3e74d42400fbe"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:85aa3ab4b03d5e99fdd31660872249df5e855334b6c333e0bc13032ff4469c4a"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cbf001afbbed111a79ca47d75941e9e5361297a87d186cbfc11ed45e30b5daba"}, + {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4c89aa46c269e4e70c4d4f9d6bc644fcc39bb409cb2a81227923404dd6f5227"}, + {file = "tokenizers-0.19.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:39c1ec76ea1027438fafe16ecb0fb84795e62e9d643444c1090179e63808c69d"}, + {file = "tokenizers-0.19.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c2a0d47a89b48d7daa241e004e71fb5a50533718897a4cd6235cb846d511a478"}, + {file = "tokenizers-0.19.1-cp39-none-win32.whl", hash = "sha256:61b7fe8886f2e104d4caf9218b157b106207e0f2a4905c9c7ac98890688aabeb"}, + {file = "tokenizers-0.19.1-cp39-none-win_amd64.whl", hash = "sha256:f97660f6c43efd3e0bfd3f2e3e5615bf215680bad6ee3d469df6454b8c6e8256"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3b11853f17b54c2fe47742c56d8a33bf49ce31caf531e87ac0d7d13d327c9334"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d26194ef6c13302f446d39972aaa36a1dda6450bc8949f5eb4c27f51191375bd"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e8d1ed93beda54bbd6131a2cb363a576eac746d5c26ba5b7556bc6f964425594"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca407133536f19bdec44b3da117ef0d12e43f6d4b56ac4c765f37eca501c7bda"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce05fde79d2bc2e46ac08aacbc142bead21614d937aac950be88dc79f9db9022"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:35583cd46d16f07c054efd18b5d46af4a2f070a2dd0a47914e66f3ff5efb2b1e"}, + {file = "tokenizers-0.19.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:43350270bfc16b06ad3f6f07eab21f089adb835544417afda0f83256a8bf8b75"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b4399b59d1af5645bcee2072a463318114c39b8547437a7c2d6a186a1b5a0e2d"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6852c5b2a853b8b0ddc5993cd4f33bfffdca4fcc5d52f89dd4b8eada99379285"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcd266ae85c3d39df2f7e7d0e07f6c41a55e9a3123bb11f854412952deacd828"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecb2651956eea2aa0a2d099434134b1b68f1c31f9a5084d6d53f08ed43d45ff2"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:b279ab506ec4445166ac476fb4d3cc383accde1ea152998509a94d82547c8e2a"}, + {file = "tokenizers-0.19.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:89183e55fb86e61d848ff83753f64cded119f5d6e1f553d14ffee3700d0a4a49"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2edbc75744235eea94d595a8b70fe279dd42f3296f76d5a86dde1d46e35f574"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:0e64bfde9a723274e9a71630c3e9494ed7b4c0f76a1faacf7fe294cd26f7ae7c"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0b5ca92bfa717759c052e345770792d02d1f43b06f9e790ca0a1db62838816f3"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f8a20266e695ec9d7a946a019c1d5ca4eddb6613d4f466888eee04f16eedb85"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63c38f45d8f2a2ec0f3a20073cccb335b9f99f73b3c69483cd52ebc75369d8a1"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:dd26e3afe8a7b61422df3176e06664503d3f5973b94f45d5c45987e1cb711876"}, + {file = "tokenizers-0.19.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:eddd5783a4a6309ce23432353cdb36220e25cbb779bfa9122320666508b44b88"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:56ae39d4036b753994476a1b935584071093b55c7a72e3b8288e68c313ca26e7"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f9939ca7e58c2758c01b40324a59c034ce0cebad18e0d4563a9b1beab3018243"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6c330c0eb815d212893c67a032e9dc1b38a803eccb32f3e8172c19cc69fbb439"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec11802450a2487cdf0e634b750a04cbdc1c4d066b97d94ce7dd2cb51ebb325b"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2b718f316b596f36e1dae097a7d5b91fc5b85e90bf08b01ff139bd8953b25af"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:ed69af290c2b65169f0ba9034d1dc39a5db9459b32f1dd8b5f3f32a3fcf06eab"}, + {file = "tokenizers-0.19.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f8a9c828277133af13f3859d1b6bf1c3cb6e9e1637df0e45312e6b7c2e622b1f"}, + {file = "tokenizers-0.19.1.tar.gz", hash = "sha256:ee59e6680ed0fdbe6b724cf38bd70400a0c1dd623b07ac729087270caeac88e3"}, +] + +[package.dependencies] +huggingface-hub = ">=0.16.4,<1.0" + +[package.extras] +dev = ["tokenizers[testing]"] docs = ["setuptools-rust", "sphinx", "sphinx-rtd-theme"] -testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests"] +testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests", "ruff"] [[package]] name = "tomli" @@ -3257,13 +3668,13 @@ files = [ [[package]] name = "tqdm" -version = "4.66.1" +version = "4.66.4" description = "Fast, Extensible Progress Meter" -optional = false +optional = true python-versions = ">=3.7" files = [ - {file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"}, - {file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"}, + {file = "tqdm-4.66.4-py3-none-any.whl", hash = "sha256:b75ca56b413b030bc3f00af51fd2c1a1a5eac6a0c1cca83cbb37a5c52abce644"}, + {file = "tqdm-4.66.4.tar.gz", hash = "sha256:e4d936c9de8727928f3be6079590e97d9abfe8d39a590be678eb5919ffc186bb"}, ] [package.dependencies] @@ -3277,60 +3688,91 @@ telegram = ["requests"] [[package]] name = "traitlets" -version = "5.9.0" +version = "5.14.3" description = "Traitlets Python configuration system" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "traitlets-5.9.0-py3-none-any.whl", hash = "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8"}, - {file = "traitlets-5.9.0.tar.gz", hash = "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9"}, + {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}, + {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"}, ] [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"] [[package]] name = "twilio" -version = "8.5.0" +version = "9.1.0" description = "Twilio API client and TwiML generator" optional = true python-versions = ">=3.7.0" files = [ - {file = "twilio-8.5.0-py2.py3-none-any.whl", hash = "sha256:a6fdea2252cb7a8a47b5750d58abe1888bba9777482bac8e9bc3be47970facc7"}, - {file = "twilio-8.5.0.tar.gz", hash = "sha256:f55da9b485f9070aef09836e56230d0e6fd83811d2e6668f20d9057dd3668143"}, + {file = "twilio-9.1.0-py2.py3-none-any.whl", hash = "sha256:eb4687a9f81dc3118e8981c5a46d9f8184baee135c79afed47c714c759c31bbc"}, + {file = "twilio-9.1.0.tar.gz", hash = "sha256:ab2eb19c779855bf02cdca8a7e02ebaa64feee47da7b591ac9088ec07a6962e2"}, ] [package.dependencies] aiohttp = ">=3.8.4" aiohttp-retry = ">=2.8.3" PyJWT = ">=2.0.0,<3.0.0" -pytz = "*" requests = ">=2.0.0" +[[package]] +name = "typer" +version = "0.12.3" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +optional = false +python-versions = ">=3.7" +files = [ + {file = "typer-0.12.3-py3-none-any.whl", hash = "sha256:070d7ca53f785acbccba8e7d28b08dcd88f79f1fbda035ade0aecec71ca5c914"}, + {file = "typer-0.12.3.tar.gz", hash = "sha256:49e73131481d804288ef62598d97a1ceef3058905aa536a1134f90891ba35482"}, +] + +[package.dependencies] +click = ">=8.0.0" +rich = ">=10.11.0" +shellingham = ">=1.3.0" +typing-extensions = ">=3.7.4.3" + +[[package]] +name = "types-cffi" +version = "1.16.0.20240331" +description = "Typing stubs for cffi" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-cffi-1.16.0.20240331.tar.gz", hash = "sha256:b8b20d23a2b89cfed5f8c5bc53b0cb8677c3aac6d970dbc771e28b9c698f5dee"}, + {file = "types_cffi-1.16.0.20240331-py3-none-any.whl", hash = "sha256:a363e5ea54a4eb6a4a105d800685fde596bc318089b025b27dee09849fe41ff0"}, +] + +[package.dependencies] +types-setuptools = "*" + [[package]] name = "types-pyopenssl" -version = "23.2.0.2" +version = "24.1.0.20240425" description = "Typing stubs for pyOpenSSL" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "types-pyOpenSSL-23.2.0.2.tar.gz", hash = "sha256:6a010dac9ecd42b582d7dd2cc3e9e40486b79b3b64bb2fffba1474ff96af906d"}, - {file = "types_pyOpenSSL-23.2.0.2-py3-none-any.whl", hash = "sha256:19536aa3debfbe25a918cf0d898e9f5fbbe6f3594a429da7914bf331deb1b342"}, + {file = "types-pyOpenSSL-24.1.0.20240425.tar.gz", hash = "sha256:0a7e82626c1983dc8dc59292bf20654a51c3c3881bcbb9b337c1da6e32f0204e"}, + {file = "types_pyOpenSSL-24.1.0.20240425-py3-none-any.whl", hash = "sha256:f51a156835555dd2a1f025621e8c4fbe7493470331afeef96884d1d29bf3a473"}, ] [package.dependencies] cryptography = ">=35.0.0" +types-cffi = "*" [[package]] name = "types-redis" -version = "4.6.0.4" +version = "4.6.0.20240425" description = "Typing stubs for redis" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "types-redis-4.6.0.4.tar.gz", hash = "sha256:c475a9d3cf73dd696c3887d30644323fc56f5e00af96151035b3b5b52875c9b3"}, - {file = "types_redis-4.6.0.4-py3-none-any.whl", hash = "sha256:03a1e1659ae4d8f6543bc2b8b11e94b1ee53937f313b1dc6f67dc7bde7d38fe0"}, + {file = "types-redis-4.6.0.20240425.tar.gz", hash = "sha256:9402a10ee931d241fdfcc04592ebf7a661d7bb92a8dea631279f0d8acbcf3a22"}, + {file = "types_redis-4.6.0.20240425-py3-none-any.whl", hash = "sha256:ac5bc19e8f5997b9e76ad5d9cf15d0392d9f28cf5fc7746ea4a64b989c45c6a8"}, ] [package.dependencies] @@ -3339,56 +3781,56 @@ types-pyOpenSSL = "*" [[package]] name = "types-regex" -version = "2023.8.8.0" +version = "2024.5.15.20240519" description = "Typing stubs for regex" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "types-regex-2023.8.8.0.tar.gz", hash = "sha256:ec87fbb69802b7224d8067bf65048fbfa7bc061efde65cfe471471c0c4d561e0"}, - {file = "types_regex-2023.8.8.0-py3-none-any.whl", hash = "sha256:52cc3e7748292fc0157388166e23b6d7b661459ae9dda8cec3c6a85ead3b1f98"}, + {file = "types-regex-2024.5.15.20240519.tar.gz", hash = "sha256:ef3f594a95a95d6b9b5704a1facf3511a73e4731209ddb8868461db4c42dc12b"}, + {file = "types_regex-2024.5.15.20240519-py3-none-any.whl", hash = "sha256:d5895079cc66f91ae8818aeef14e9337c492ceb87ad0ff3df8c1c04d418cb9dd"}, ] [[package]] name = "types-requests" -version = "2.31.0.2" +version = "2.32.0.20240523" description = "Typing stubs for requests" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "types-requests-2.31.0.2.tar.gz", hash = "sha256:6aa3f7faf0ea52d728bb18c0a0d1522d9bfd8c72d26ff6f61bfc3d06a411cf40"}, - {file = "types_requests-2.31.0.2-py3-none-any.whl", hash = "sha256:56d181c85b5925cbc59f4489a57e72a8b2166f18273fd8ba7b6fe0c0b986f12a"}, + {file = "types-requests-2.32.0.20240523.tar.gz", hash = "sha256:26b8a6de32d9f561192b9942b41c0ab2d8010df5677ca8aa146289d11d505f57"}, + {file = "types_requests-2.32.0.20240523-py3-none-any.whl", hash = "sha256:f19ed0e2daa74302069bbbbf9e82902854ffa780bc790742a810a9aaa52f65ec"}, ] [package.dependencies] -types-urllib3 = "*" +urllib3 = ">=2" [[package]] -name = "types-urllib3" -version = "1.26.25.14" -description = "Typing stubs for urllib3" +name = "types-setuptools" +version = "70.0.0.20240524" +description = "Typing stubs for setuptools" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "types-urllib3-1.26.25.14.tar.gz", hash = "sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f"}, - {file = "types_urllib3-1.26.25.14-py3-none-any.whl", hash = "sha256:9683bbb7fb72e32bfe9d2be6e04875fbe1b3eeec3cbb4ea231435aa7fd6b4f0e"}, + {file = "types-setuptools-70.0.0.20240524.tar.gz", hash = "sha256:e31fee7b9d15ef53980526579ac6089b3ae51a005a281acf97178e90ac71aff6"}, + {file = "types_setuptools-70.0.0.20240524-py3-none-any.whl", hash = "sha256:8f5379b9948682d72a9ab531fbe52932e84c4f38deda570255f9bae3edd766bc"}, ] [[package]] name = "typing-extensions" -version = "4.7.1" -description = "Backported and Experimental Type Hints for Python 3.7+" +version = "4.12.0" +description = "Backported and Experimental Type Hints for Python 3.8+" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, - {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, + {file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"}, + {file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"}, ] [[package]] name = "typing-inspect" version = "0.9.0" description = "Runtime inspection utilities for typing module." -optional = false +optional = true python-versions = "*" files = [ {file = "typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f"}, @@ -3400,78 +3842,188 @@ mypy-extensions = ">=0.3.0" typing-extensions = ">=3.7.4" [[package]] -name = "urllib3" -version = "1.26.16" -description = "HTTP library with thread-safe connection pooling, file post, and more." +name = "ujson" +version = "5.10.0" +description = "Ultra fast JSON encoder and decoder for Python" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.8" files = [ - {file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"}, - {file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"}, + {file = "ujson-5.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2601aa9ecdbee1118a1c2065323bda35e2c5a2cf0797ef4522d485f9d3ef65bd"}, + {file = "ujson-5.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:348898dd702fc1c4f1051bc3aacbf894caa0927fe2c53e68679c073375f732cf"}, + {file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22cffecf73391e8abd65ef5f4e4dd523162a3399d5e84faa6aebbf9583df86d6"}, + {file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26b0e2d2366543c1bb4fbd457446f00b0187a2bddf93148ac2da07a53fe51569"}, + {file = "ujson-5.10.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:caf270c6dba1be7a41125cd1e4fc7ba384bf564650beef0df2dd21a00b7f5770"}, + {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a245d59f2ffe750446292b0094244df163c3dc96b3ce152a2c837a44e7cda9d1"}, + {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:94a87f6e151c5f483d7d54ceef83b45d3a9cca7a9cb453dbdbb3f5a6f64033f5"}, + {file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:29b443c4c0a113bcbb792c88bea67b675c7ca3ca80c3474784e08bba01c18d51"}, + {file = "ujson-5.10.0-cp310-cp310-win32.whl", hash = "sha256:c18610b9ccd2874950faf474692deee4223a994251bc0a083c114671b64e6518"}, + {file = "ujson-5.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:924f7318c31874d6bb44d9ee1900167ca32aa9b69389b98ecbde34c1698a250f"}, + {file = "ujson-5.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00"}, + {file = "ujson-5.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126"}, + {file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8"}, + {file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b"}, + {file = "ujson-5.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9"}, + {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f"}, + {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4"}, + {file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1"}, + {file = "ujson-5.10.0-cp311-cp311-win32.whl", hash = "sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f"}, + {file = "ujson-5.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720"}, + {file = "ujson-5.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5"}, + {file = "ujson-5.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e"}, + {file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043"}, + {file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1"}, + {file = "ujson-5.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3"}, + {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21"}, + {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2"}, + {file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e"}, + {file = "ujson-5.10.0-cp312-cp312-win32.whl", hash = "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e"}, + {file = "ujson-5.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc"}, + {file = "ujson-5.10.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287"}, + {file = "ujson-5.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e"}, + {file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557"}, + {file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988"}, + {file = "ujson-5.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816"}, + {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20"}, + {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0"}, + {file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f"}, + {file = "ujson-5.10.0-cp313-cp313-win32.whl", hash = "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165"}, + {file = "ujson-5.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539"}, + {file = "ujson-5.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a984a3131da7f07563057db1c3020b1350a3e27a8ec46ccbfbf21e5928a43050"}, + {file = "ujson-5.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73814cd1b9db6fc3270e9d8fe3b19f9f89e78ee9d71e8bd6c9a626aeaeaf16bd"}, + {file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61e1591ed9376e5eddda202ec229eddc56c612b61ac6ad07f96b91460bb6c2fb"}, + {file = "ujson-5.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2c75269f8205b2690db4572a4a36fe47cd1338e4368bc73a7a0e48789e2e35a"}, + {file = "ujson-5.10.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7223f41e5bf1f919cd8d073e35b229295aa8e0f7b5de07ed1c8fddac63a6bc5d"}, + {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d4dc2fd6b3067c0782e7002ac3b38cf48608ee6366ff176bbd02cf969c9c20fe"}, + {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:232cc85f8ee3c454c115455195a205074a56ff42608fd6b942aa4c378ac14dd7"}, + {file = "ujson-5.10.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cc6139531f13148055d691e442e4bc6601f6dba1e6d521b1585d4788ab0bfad4"}, + {file = "ujson-5.10.0-cp38-cp38-win32.whl", hash = "sha256:e7ce306a42b6b93ca47ac4a3b96683ca554f6d35dd8adc5acfcd55096c8dfcb8"}, + {file = "ujson-5.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:e82d4bb2138ab05e18f089a83b6564fee28048771eb63cdecf4b9b549de8a2cc"}, + {file = "ujson-5.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dfef2814c6b3291c3c5f10065f745a1307d86019dbd7ea50e83504950136ed5b"}, + {file = "ujson-5.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4734ee0745d5928d0ba3a213647f1c4a74a2a28edc6d27b2d6d5bd9fa4319e27"}, + {file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d47ebb01bd865fdea43da56254a3930a413f0c5590372a1241514abae8aa7c76"}, + {file = "ujson-5.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dee5e97c2496874acbf1d3e37b521dd1f307349ed955e62d1d2f05382bc36dd5"}, + {file = "ujson-5.10.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7490655a2272a2d0b072ef16b0b58ee462f4973a8f6bbe64917ce5e0a256f9c0"}, + {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ba17799fcddaddf5c1f75a4ba3fd6441f6a4f1e9173f8a786b42450851bd74f1"}, + {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2aff2985cef314f21d0fecc56027505804bc78802c0121343874741650a4d3d1"}, + {file = "ujson-5.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ad88ac75c432674d05b61184178635d44901eb749786c8eb08c102330e6e8996"}, + {file = "ujson-5.10.0-cp39-cp39-win32.whl", hash = "sha256:2544912a71da4ff8c4f7ab5606f947d7299971bdd25a45e008e467ca638d13c9"}, + {file = "ujson-5.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:3ff201d62b1b177a46f113bb43ad300b424b7847f9c5d38b1b4ad8f75d4a282a"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5b6fee72fa77dc172a28f21693f64d93166534c263adb3f96c413ccc85ef6e64"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:61d0af13a9af01d9f26d2331ce49bb5ac1fb9c814964018ac8df605b5422dcb3"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecb24f0bdd899d368b715c9e6664166cf694d1e57be73f17759573a6986dd95a"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbd8fd427f57a03cff3ad6574b5e299131585d9727c8c366da4624a9069ed746"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beeaf1c48e32f07d8820c705ff8e645f8afa690cca1544adba4ebfa067efdc88"}, + {file = "ujson-5.10.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:baed37ea46d756aca2955e99525cc02d9181de67f25515c468856c38d52b5f3b"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7663960f08cd5a2bb152f5ee3992e1af7690a64c0e26d31ba7b3ff5b2ee66337"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:d8640fb4072d36b08e95a3a380ba65779d356b2fee8696afeb7794cf0902d0a1"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78778a3aa7aafb11e7ddca4e29f46bc5139131037ad628cc10936764282d6753"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0111b27f2d5c820e7f2dbad7d48e3338c824e7ac4d2a12da3dc6061cc39c8e6"}, + {file = "ujson-5.10.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:c66962ca7565605b355a9ed478292da628b8f18c0f2793021ca4425abf8b01e5"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ba43cc34cce49cf2d4bc76401a754a81202d8aa926d0e2b79f0ee258cb15d3a4"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ac56eb983edce27e7f51d05bc8dd820586c6e6be1c5216a6809b0c668bb312b8"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44bd4b23a0e723bf8b10628288c2c7c335161d6840013d4d5de20e48551773b"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c10f4654e5326ec14a46bcdeb2b685d4ada6911050aa8baaf3501e57024b804"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0de4971a89a762398006e844ae394bd46991f7c385d7a6a3b93ba229e6dac17e"}, + {file = "ujson-5.10.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e1402f0564a97d2a52310ae10a64d25bcef94f8dd643fcf5d310219d915484f7"}, + {file = "ujson-5.10.0.tar.gz", hash = "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1"}, ] -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] - [[package]] -name = "urlobject" -version = "2.4.3" -description = "A utility class for manipulating URLs." -optional = true -python-versions = "*" +name = "urllib3" +version = "2.2.1" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" files = [ - {file = "URLObject-2.4.3.tar.gz", hash = "sha256:47b2e20e6ab9c8366b2f4a3566b6ff4053025dad311c4bb71279bbcfa2430caa"}, + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, ] +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + [[package]] name = "uvicorn" -version = "0.21.1" +version = "0.30.0" description = "The lightning-fast ASGI server." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "uvicorn-0.21.1-py3-none-any.whl", hash = "sha256:e47cac98a6da10cd41e6fd036d472c6f58ede6c5dbee3dbee3ef7a100ed97742"}, - {file = "uvicorn-0.21.1.tar.gz", hash = "sha256:0fac9cb342ba099e0d582966005f3fdba5b0290579fed4a6266dc702ca7bb032"}, + {file = "uvicorn-0.30.0-py3-none-any.whl", hash = "sha256:78fa0b5f56abb8562024a59041caeb555c86e48d0efdd23c3fe7de7a4075bdab"}, + {file = "uvicorn-0.30.0.tar.gz", hash = "sha256:f678dec4fa3a39706bbf49b9ec5fc40049d42418716cea52b53f07828a60aa37"}, ] [package.dependencies] click = ">=7.0" +colorama = {version = ">=0.4", optional = true, markers = "sys_platform == \"win32\" and extra == \"standard\""} h11 = ">=0.8" +httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standard\""} +python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} +pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} +typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} +uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\" and extra == \"standard\""} +watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} +websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""} [package.extras] standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] [[package]] -name = "virtualenv" -version = "20.24.3" -description = "Virtual Python Environment builder" +name = "uvloop" +version = "0.19.0" +description = "Fast implementation of asyncio event loop on top of libuv" optional = false -python-versions = ">=3.7" -files = [ - {file = "virtualenv-20.24.3-py3-none-any.whl", hash = "sha256:95a6e9398b4967fbcb5fef2acec5efaf9aa4972049d9ae41f95e0972a683fd02"}, - {file = "virtualenv-20.24.3.tar.gz", hash = "sha256:e5c3b4ce817b0b328af041506a2a299418c98747c4b1e68cb7527e74ced23efc"}, +python-versions = ">=3.8.0" +files = [ + {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e"}, + {file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428"}, + {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8"}, + {file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849"}, + {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957"}, + {file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd"}, + {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef"}, + {file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2"}, + {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1"}, + {file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24"}, + {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533"}, + {file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12"}, + {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650"}, + {file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec"}, + {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc"}, + {file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6"}, + {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593"}, + {file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3"}, + {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:78ab247f0b5671cc887c31d33f9b3abfb88d2614b84e4303f1a63b46c046c8bd"}, + {file = "uvloop-0.19.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:472d61143059c84947aa8bb74eabbace30d577a03a1805b77933d6bd13ddebbd"}, + {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45bf4c24c19fb8a50902ae37c5de50da81de4922af65baf760f7c0c42e1088be"}, + {file = "uvloop-0.19.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271718e26b3e17906b28b67314c45d19106112067205119dddbd834c2b7ce797"}, + {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:34175c9fd2a4bc3adc1380e1261f60306344e3407c20a4d684fd5f3be010fa3d"}, + {file = "uvloop-0.19.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e27f100e1ff17f6feeb1f33968bc185bf8ce41ca557deee9d9bbbffeb72030b7"}, + {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13dfdf492af0aa0a0edf66807d2b465607d11c4fa48f4a1fd41cbea5b18e8e8b"}, + {file = "uvloop-0.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6e3d4e85ac060e2342ff85e90d0c04157acb210b9ce508e784a944f852a40e67"}, + {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ca4956c9ab567d87d59d49fa3704cf29e37109ad348f2d5223c9bf761a332e7"}, + {file = "uvloop-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f467a5fd23b4fc43ed86342641f3936a68ded707f4627622fa3f82a120e18256"}, + {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:492e2c32c2af3f971473bc22f086513cedfc66a130756145a931a90c3958cb17"}, + {file = "uvloop-0.19.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2df95fca285a9f5bfe730e51945ffe2fa71ccbfdde3b0da5772b4ee4f2e770d5"}, + {file = "uvloop-0.19.0.tar.gz", hash = "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd"}, ] -[package.dependencies] -distlib = ">=0.3.7,<1" -filelock = ">=3.12.2,<4" -platformdirs = ">=3.9.1,<4" - [package.extras] -docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] -test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] +docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] +test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"] [[package]] name = "vonage" -version = "3.13.0" +version = "3.14.0" description = "Vonage Server SDK for Python" optional = true python-versions = ">=3.8" files = [ - {file = "vonage-3.13.0-py2.py3-none-any.whl", hash = "sha256:f84e74f4c2dd8c8f97bffecda9016d503de1d4b9df98efcbd6e7ddfb1a3359dc"}, - {file = "vonage-3.13.0.tar.gz", hash = "sha256:1e82fa51b6d9d0af300b85f3ee25a3ef2f96c4f3ab753f20ba4b38e164b06db8"}, + {file = "vonage-3.14.0-py2.py3-none-any.whl", hash = "sha256:f8d28b8fcd157c0610d84b880779aadd3ab3768abfb18ef863e08669de163ccf"}, + {file = "vonage-3.14.0.tar.gz", hash = "sha256:ea001e9616abb19670c4250a1ac46288207030ebc9d9ecbcf5fcffef61fa5850"}, ] [package.dependencies] @@ -3483,287 +4035,403 @@ vonage-jwt = ">=1.1.0" [[package]] name = "vonage-jwt" -version = "1.1.0" -description = "A JWT Generator for Python. Creates JWTs for use with Vonage APIs." +version = "1.1.1" +description = "Tooling for working with JWTs for Vonage APIs in Python." optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "vonage_jwt-1.1.0-py3-none-any.whl", hash = "sha256:f41d2fc51f80cebddff1d65ec2146527ee83ca95f3e8a8fe9cda2263a435e2ed"}, - {file = "vonage_jwt-1.1.0.tar.gz", hash = "sha256:ed6af2bf82dc7cffe42ad453295472b86e02852baaaa3f2b97cd49fcb4e9019d"}, + {file = "vonage_jwt-1.1.1-py3-none-any.whl", hash = "sha256:4b751571e013deeab9f13b68f9e1478d8aa7f0a91f0cb7f6d793fa7b859859df"}, + {file = "vonage_jwt-1.1.1.tar.gz", hash = "sha256:15f4b1cd8fa5909390a4074a909053ae823df0557b1edb9b675d0a013295dc10"}, ] [package.dependencies] pyjwt = {version = ">=1.6.4", extras = ["crypto"]} +vonage-utils = ">=1.1.2" [[package]] -name = "wcwidth" -version = "0.2.6" -description = "Measures the displayed width of unicode strings in a terminal" +name = "vonage-utils" +version = "1.1.2" +description = "Utils package containing objects for use with Vonage APIs" optional = true -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"}, - {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, + {file = "vonage_utils-1.1.2-py3-none-any.whl", hash = "sha256:a815a8be8f5fdba558d090d0f81b469a2eb0ded4cccbfe4e27dc9276e84c4b7e"}, + {file = "vonage_utils-1.1.2.tar.gz", hash = "sha256:a86c1eafe62e6f82d18dda6fd4dc78c898dea81888b83f18ea75105365307daf"}, ] +[package.dependencies] +pydantic = ">=2.7.1" +typing-extensions = ">=4.9.0" + [[package]] -name = "websocket-client" -version = "0.59.0" -description = "WebSocket client for Python with low level API options" -optional = true -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +name = "watchfiles" +version = "0.22.0" +description = "Simple, modern and high performance file watching and code reload in python." +optional = false +python-versions = ">=3.8" files = [ - {file = "websocket-client-0.59.0.tar.gz", hash = "sha256:d376bd60eace9d437ab6d7ee16f4ab4e821c9dae591e1b783c58ebd8aaf80c5c"}, - {file = "websocket_client-0.59.0-py2.py3-none-any.whl", hash = "sha256:2e50d26ca593f70aba7b13a489435ef88b8fc3b5c5643c1ce8808ff9b40f0b32"}, + {file = "watchfiles-0.22.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:da1e0a8caebf17976e2ffd00fa15f258e14749db5e014660f53114b676e68538"}, + {file = "watchfiles-0.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61af9efa0733dc4ca462347becb82e8ef4945aba5135b1638bfc20fad64d4f0e"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d9188979a58a096b6f8090e816ccc3f255f137a009dd4bbec628e27696d67c1"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2bdadf6b90c099ca079d468f976fd50062905d61fae183f769637cb0f68ba59a"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:067dea90c43bf837d41e72e546196e674f68c23702d3ef80e4e816937b0a3ffd"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbf8a20266136507abf88b0df2328e6a9a7c7309e8daff124dda3803306a9fdb"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1235c11510ea557fe21be5d0e354bae2c655a8ee6519c94617fe63e05bca4171"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2444dc7cb9d8cc5ab88ebe792a8d75709d96eeef47f4c8fccb6df7c7bc5be71"}, + {file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c5af2347d17ab0bd59366db8752d9e037982e259cacb2ba06f2c41c08af02c39"}, + {file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9624a68b96c878c10437199d9a8b7d7e542feddda8d5ecff58fdc8e67b460848"}, + {file = "watchfiles-0.22.0-cp310-none-win32.whl", hash = "sha256:4b9f2a128a32a2c273d63eb1fdbf49ad64852fc38d15b34eaa3f7ca2f0d2b797"}, + {file = "watchfiles-0.22.0-cp310-none-win_amd64.whl", hash = "sha256:2627a91e8110b8de2406d8b2474427c86f5a62bf7d9ab3654f541f319ef22bcb"}, + {file = "watchfiles-0.22.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8c39987a1397a877217be1ac0fb1d8b9f662c6077b90ff3de2c05f235e6a8f96"}, + {file = "watchfiles-0.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a927b3034d0672f62fb2ef7ea3c9fc76d063c4b15ea852d1db2dc75fe2c09696"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052d668a167e9fc345c24203b104c313c86654dd6c0feb4b8a6dfc2462239249"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e45fb0d70dda1623a7045bd00c9e036e6f1f6a85e4ef2c8ae602b1dfadf7550"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c49b76a78c156979759d759339fb62eb0549515acfe4fd18bb151cc07366629c"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4a65474fd2b4c63e2c18ac67a0c6c66b82f4e73e2e4d940f837ed3d2fd9d4da"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc0cba54f47c660d9fa3218158b8963c517ed23bd9f45fe463f08262a4adae1"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ebe84a035993bb7668f58a0ebf998174fb723a39e4ef9fce95baabb42b787f"}, + {file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e0f0a874231e2839abbf473256efffe577d6ee2e3bfa5b540479e892e47c172d"}, + {file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:213792c2cd3150b903e6e7884d40660e0bcec4465e00563a5fc03f30ea9c166c"}, + {file = "watchfiles-0.22.0-cp311-none-win32.whl", hash = "sha256:b44b70850f0073b5fcc0b31ede8b4e736860d70e2dbf55701e05d3227a154a67"}, + {file = "watchfiles-0.22.0-cp311-none-win_amd64.whl", hash = "sha256:00f39592cdd124b4ec5ed0b1edfae091567c72c7da1487ae645426d1b0ffcad1"}, + {file = "watchfiles-0.22.0-cp311-none-win_arm64.whl", hash = "sha256:3218a6f908f6a276941422b035b511b6d0d8328edd89a53ae8c65be139073f84"}, + {file = "watchfiles-0.22.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:c7b978c384e29d6c7372209cbf421d82286a807bbcdeb315427687f8371c340a"}, + {file = "watchfiles-0.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd4c06100bce70a20c4b81e599e5886cf504c9532951df65ad1133e508bf20be"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:425440e55cd735386ec7925f64d5dde392e69979d4c8459f6bb4e920210407f2"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68fe0c4d22332d7ce53ad094622b27e67440dacefbaedd29e0794d26e247280c"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a8a31bfd98f846c3c284ba694c6365620b637debdd36e46e1859c897123aa232"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc2e8fe41f3cac0660197d95216c42910c2b7e9c70d48e6d84e22f577d106fc1"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b7cc10261c2786c41d9207193a85c1db1b725cf87936df40972aab466179b6"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28585744c931576e535860eaf3f2c0ec7deb68e3b9c5a85ca566d69d36d8dd27"}, + {file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:00095dd368f73f8f1c3a7982a9801190cc88a2f3582dd395b289294f8975172b"}, + {file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:52fc9b0dbf54d43301a19b236b4a4614e610605f95e8c3f0f65c3a456ffd7d35"}, + {file = "watchfiles-0.22.0-cp312-none-win32.whl", hash = "sha256:581f0a051ba7bafd03e17127735d92f4d286af941dacf94bcf823b101366249e"}, + {file = "watchfiles-0.22.0-cp312-none-win_amd64.whl", hash = "sha256:aec83c3ba24c723eac14225194b862af176d52292d271c98820199110e31141e"}, + {file = "watchfiles-0.22.0-cp312-none-win_arm64.whl", hash = "sha256:c668228833c5619f6618699a2c12be057711b0ea6396aeaece4ded94184304ea"}, + {file = "watchfiles-0.22.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d47e9ef1a94cc7a536039e46738e17cce058ac1593b2eccdede8bf72e45f372a"}, + {file = "watchfiles-0.22.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28f393c1194b6eaadcdd8f941307fc9bbd7eb567995232c830f6aef38e8a6e88"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd64f3a4db121bc161644c9e10a9acdb836853155a108c2446db2f5ae1778c3d"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2abeb79209630da981f8ebca30a2c84b4c3516a214451bfc5f106723c5f45843"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cc382083afba7918e32d5ef12321421ef43d685b9a67cc452a6e6e18920890e"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d048ad5d25b363ba1d19f92dcf29023988524bee6f9d952130b316c5802069cb"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:103622865599f8082f03af4214eaff90e2426edff5e8522c8f9e93dc17caee13"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3e1f3cf81f1f823e7874ae563457828e940d75573c8fbf0ee66818c8b6a9099"}, + {file = "watchfiles-0.22.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8597b6f9dc410bdafc8bb362dac1cbc9b4684a8310e16b1ff5eee8725d13dcd6"}, + {file = "watchfiles-0.22.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0b04a2cbc30e110303baa6d3ddce8ca3664bc3403be0f0ad513d1843a41c97d1"}, + {file = "watchfiles-0.22.0-cp38-none-win32.whl", hash = "sha256:b610fb5e27825b570554d01cec427b6620ce9bd21ff8ab775fc3a32f28bba63e"}, + {file = "watchfiles-0.22.0-cp38-none-win_amd64.whl", hash = "sha256:fe82d13461418ca5e5a808a9e40f79c1879351fcaeddbede094028e74d836e86"}, + {file = "watchfiles-0.22.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3973145235a38f73c61474d56ad6199124e7488822f3a4fc97c72009751ae3b0"}, + {file = "watchfiles-0.22.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:280a4afbc607cdfc9571b9904b03a478fc9f08bbeec382d648181c695648202f"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a0d883351a34c01bd53cfa75cd0292e3f7e268bacf2f9e33af4ecede7e21d1d"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9165bcab15f2b6d90eedc5c20a7f8a03156b3773e5fb06a790b54ccecdb73385"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc1b9b56f051209be458b87edb6856a449ad3f803315d87b2da4c93b43a6fe72"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dc1fc25a1dedf2dd952909c8e5cb210791e5f2d9bc5e0e8ebc28dd42fed7562"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc92d2d2706d2b862ce0568b24987eba51e17e14b79a1abcd2edc39e48e743c8"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97b94e14b88409c58cdf4a8eaf0e67dfd3ece7e9ce7140ea6ff48b0407a593ec"}, + {file = "watchfiles-0.22.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96eec15e5ea7c0b6eb5bfffe990fc7c6bd833acf7e26704eb18387fb2f5fd087"}, + {file = "watchfiles-0.22.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:28324d6b28bcb8d7c1041648d7b63be07a16db5510bea923fc80b91a2a6cbed6"}, + {file = "watchfiles-0.22.0-cp39-none-win32.whl", hash = "sha256:8c3e3675e6e39dc59b8fe5c914a19d30029e36e9f99468dddffd432d8a7b1c93"}, + {file = "watchfiles-0.22.0-cp39-none-win_amd64.whl", hash = "sha256:25c817ff2a86bc3de3ed2df1703e3d24ce03479b27bb4527c57e722f8554d971"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b810a2c7878cbdecca12feae2c2ae8af59bea016a78bc353c184fa1e09f76b68"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7e1f9c5d1160d03b93fc4b68a0aeb82fe25563e12fbcdc8507f8434ab6f823c"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:030bc4e68d14bcad2294ff68c1ed87215fbd9a10d9dea74e7cfe8a17869785ab"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ace7d060432acde5532e26863e897ee684780337afb775107c0a90ae8dbccfd2"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5834e1f8b71476a26df97d121c0c0ed3549d869124ed2433e02491553cb468c2"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:0bc3b2f93a140df6806c8467c7f51ed5e55a931b031b5c2d7ff6132292e803d6"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fdebb655bb1ba0122402352b0a4254812717a017d2dc49372a1d47e24073795"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c8e0aa0e8cc2a43561e0184c0513e291ca891db13a269d8d47cb9841ced7c71"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2f350cbaa4bb812314af5dab0eb8d538481e2e2279472890864547f3fe2281ed"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7a74436c415843af2a769b36bf043b6ccbc0f8d784814ba3d42fc961cdb0a9dc"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00ad0bcd399503a84cc688590cdffbe7a991691314dde5b57b3ed50a41319a31"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72a44e9481afc7a5ee3291b09c419abab93b7e9c306c9ef9108cb76728ca58d2"}, + {file = "watchfiles-0.22.0.tar.gz", hash = "sha256:988e981aaab4f3955209e7e28c7794acdb690be1efa7f16f8ea5aba7ffdadacb"}, ] [package.dependencies] -six = "*" +anyio = ">=3.0.0" + +[[package]] +name = "wcwidth" +version = "0.2.13" +description = "Measures the displayed width of unicode strings in a terminal" +optional = true +python-versions = "*" +files = [ + {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, + {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, +] [[package]] name = "websockets" -version = "11.0.3" +version = "12.0" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +files = [ + {file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"}, + {file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"}, + {file = "websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603"}, + {file = "websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f"}, + {file = "websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf"}, + {file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"}, + {file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"}, + {file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"}, + {file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"}, + {file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"}, + {file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"}, + {file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"}, + {file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113"}, + {file = "websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d"}, + {file = "websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f"}, + {file = "websockets-12.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438"}, + {file = "websockets-12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2"}, + {file = "websockets-12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7"}, + {file = "websockets-12.0-cp38-cp38-win32.whl", hash = "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62"}, + {file = "websockets-12.0-cp38-cp38-win_amd64.whl", hash = "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892"}, + {file = "websockets-12.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d"}, + {file = "websockets-12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28"}, + {file = "websockets-12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9"}, + {file = "websockets-12.0-cp39-cp39-win32.whl", hash = "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6"}, + {file = "websockets-12.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8"}, + {file = "websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b"}, + {file = "websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30"}, + {file = "websockets-12.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2"}, + {file = "websockets-12.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468"}, + {file = "websockets-12.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611"}, + {file = "websockets-12.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370"}, + {file = "websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e"}, + {file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"}, +] + +[[package]] +name = "win32-setctime" +version = "1.1.0" +description = "A small Python utility to set file creation time on Windows" +optional = false +python-versions = ">=3.5" files = [ - {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3ccc8a0c387629aec40f2fc9fdcb4b9d5431954f934da3eaf16cdc94f67dbfac"}, - {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d67ac60a307f760c6e65dad586f556dde58e683fab03323221a4e530ead6f74d"}, - {file = "websockets-11.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84d27a4832cc1a0ee07cdcf2b0629a8a72db73f4cf6de6f0904f6661227f256f"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffd7dcaf744f25f82190856bc26ed81721508fc5cbf2a330751e135ff1283564"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7622a89d696fc87af8e8d280d9b421db5133ef5b29d3f7a1ce9f1a7bf7fcfa11"}, - {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bceab846bac555aff6427d060f2fcfff71042dba6f5fca7dc4f75cac815e57ca"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:54c6e5b3d3a8936a4ab6870d46bdd6ec500ad62bde9e44462c32d18f1e9a8e54"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:41f696ba95cd92dc047e46b41b26dd24518384749ed0d99bea0a941ca87404c4"}, - {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:86d2a77fd490ae3ff6fae1c6ceaecad063d3cc2320b44377efdde79880e11526"}, - {file = "websockets-11.0.3-cp310-cp310-win32.whl", hash = "sha256:2d903ad4419f5b472de90cd2d40384573b25da71e33519a67797de17ef849b69"}, - {file = "websockets-11.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:1d2256283fa4b7f4c7d7d3e84dc2ece74d341bce57d5b9bf385df109c2a1a82f"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e848f46a58b9fcf3d06061d17be388caf70ea5b8cc3466251963c8345e13f7eb"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa5003845cdd21ac0dc6c9bf661c5beddd01116f6eb9eb3c8e272353d45b3288"}, - {file = "websockets-11.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b58cbf0697721120866820b89f93659abc31c1e876bf20d0b3d03cef14faf84d"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:660e2d9068d2bedc0912af508f30bbeb505bbbf9774d98def45f68278cea20d3"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1f0524f203e3bd35149f12157438f406eff2e4fb30f71221c8a5eceb3617b6b"}, - {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:def07915168ac8f7853812cc593c71185a16216e9e4fa886358a17ed0fd9fcf6"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b30c6590146e53149f04e85a6e4fcae068df4289e31e4aee1fdf56a0dead8f97"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:619d9f06372b3a42bc29d0cd0354c9bb9fb39c2cbc1a9c5025b4538738dbffaf"}, - {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:01f5567d9cf6f502d655151645d4e8b72b453413d3819d2b6f1185abc23e82dd"}, - {file = "websockets-11.0.3-cp311-cp311-win32.whl", hash = "sha256:e1459677e5d12be8bbc7584c35b992eea142911a6236a3278b9b5ce3326f282c"}, - {file = "websockets-11.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:e7837cb169eca3b3ae94cc5787c4fed99eef74c0ab9506756eea335e0d6f3ed8"}, - {file = "websockets-11.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9f59a3c656fef341a99e3d63189852be7084c0e54b75734cde571182c087b152"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2529338a6ff0eb0b50c7be33dc3d0e456381157a31eefc561771ee431134a97f"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34fd59a4ac42dff6d4681d8843217137f6bc85ed29722f2f7222bd619d15e95b"}, - {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:332d126167ddddec94597c2365537baf9ff62dfcc9db4266f263d455f2f031cb"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6505c1b31274723ccaf5f515c1824a4ad2f0d191cec942666b3d0f3aa4cb4007"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f467ba0050b7de85016b43f5a22b46383ef004c4f672148a8abf32bc999a87f0"}, - {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9d9acd80072abcc98bd2c86c3c9cd4ac2347b5a5a0cae7ed5c0ee5675f86d9af"}, - {file = "websockets-11.0.3-cp37-cp37m-win32.whl", hash = "sha256:e590228200fcfc7e9109509e4d9125eace2042fd52b595dd22bbc34bb282307f"}, - {file = "websockets-11.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:b16fff62b45eccb9c7abb18e60e7e446998093cdcb50fed33134b9b6878836de"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fb06eea71a00a7af0ae6aefbb932fb8a7df3cb390cc217d51a9ad7343de1b8d0"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8a34e13a62a59c871064dfd8ffb150867e54291e46d4a7cf11d02c94a5275bae"}, - {file = "websockets-11.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4841ed00f1026dfbced6fca7d963c4e7043aa832648671b5138008dc5a8f6d99"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a073fc9ab1c8aff37c99f11f1641e16da517770e31a37265d2755282a5d28aa"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68b977f21ce443d6d378dbd5ca38621755f2063d6fdb3335bda981d552cfff86"}, - {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a99a7a71631f0efe727c10edfba09ea6bee4166a6f9c19aafb6c0b5917d09c"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bee9fcb41db2a23bed96c6b6ead6489702c12334ea20a297aa095ce6d31370d0"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4b253869ea05a5a073ebfdcb5cb3b0266a57c3764cf6fe114e4cd90f4bfa5f5e"}, - {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1553cb82942b2a74dd9b15a018dce645d4e68674de2ca31ff13ebc2d9f283788"}, - {file = "websockets-11.0.3-cp38-cp38-win32.whl", hash = "sha256:f61bdb1df43dc9c131791fbc2355535f9024b9a04398d3bd0684fc16ab07df74"}, - {file = "websockets-11.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:03aae4edc0b1c68498f41a6772d80ac7c1e33c06c6ffa2ac1c27a07653e79d6f"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:777354ee16f02f643a4c7f2b3eff8027a33c9861edc691a2003531f5da4f6bc8"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8c82f11964f010053e13daafdc7154ce7385ecc538989a354ccc7067fd7028fd"}, - {file = "websockets-11.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3580dd9c1ad0701169e4d6fc41e878ffe05e6bdcaf3c412f9d559389d0c9e016"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f1a3f10f836fab6ca6efa97bb952300b20ae56b409414ca85bff2ad241d2a61"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df41b9bc27c2c25b486bae7cf42fccdc52ff181c8c387bfd026624a491c2671b"}, - {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279e5de4671e79a9ac877427f4ac4ce93751b8823f276b681d04b2156713b9dd"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1fdf26fa8a6a592f8f9235285b8affa72748dc12e964a5518c6c5e8f916716f7"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:69269f3a0b472e91125b503d3c0b3566bda26da0a3261c49f0027eb6075086d1"}, - {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:97b52894d948d2f6ea480171a27122d77af14ced35f62e5c892ca2fae9344311"}, - {file = "websockets-11.0.3-cp39-cp39-win32.whl", hash = "sha256:c7f3cb904cce8e1be667c7e6fef4516b98d1a6a0635a58a57528d577ac18a128"}, - {file = "websockets-11.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c792ea4eabc0159535608fc5658a74d1a81020eb35195dd63214dcf07556f67e"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f2e58f2c36cc52d41f2659e4c0cbf7353e28c8c9e63e30d8c6d3494dc9fdedcf"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de36fe9c02995c7e6ae6efe2e205816f5f00c22fd1fbf343d4d18c3d5ceac2f5"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ac56b661e60edd453585f4bd68eb6a29ae25b5184fd5ba51e97652580458998"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e052b8467dd07d4943936009f46ae5ce7b908ddcac3fda581656b1b19c083d9b"}, - {file = "websockets-11.0.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:42cc5452a54a8e46a032521d7365da775823e21bfba2895fb7b77633cce031bb"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e6316827e3e79b7b8e7d8e3b08f4e331af91a48e794d5d8b099928b6f0b85f20"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8531fdcad636d82c517b26a448dcfe62f720e1922b33c81ce695d0edb91eb931"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c114e8da9b475739dde229fd3bc6b05a6537a88a578358bc8eb29b4030fac9c9"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e063b1865974611313a3849d43f2c3f5368093691349cf3c7c8f8f75ad7cb280"}, - {file = "websockets-11.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:92b2065d642bf8c0a82d59e59053dd2fdde64d4ed44efe4870fa816c1232647b"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0ee68fe502f9031f19d495dae2c268830df2760c0524cbac5d759921ba8c8e82"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcacf2c7a6c3a84e720d1bb2b543c675bf6c40e460300b628bab1b1efc7c034c"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b67c6f5e5a401fc56394f191f00f9b3811fe843ee93f4a70df3c389d1adf857d"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d5023a4b6a5b183dc838808087033ec5df77580485fc533e7dab2567851b0a4"}, - {file = "websockets-11.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ed058398f55163a79bb9f06a90ef9ccc063b204bb346c4de78efc5d15abfe602"}, - {file = "websockets-11.0.3-py3-none-any.whl", hash = "sha256:6681ba9e7f8f3b19440921e99efbb40fc89f26cd71bf539e45d8c8a25c976dc6"}, - {file = "websockets-11.0.3.tar.gz", hash = "sha256:88fc51d9a26b10fc331be344f1781224a375b78488fc343620184e95a4b27016"}, + {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"}, + {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"}, ] +[package.extras] +dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] + [[package]] name = "wrapt" -version = "1.15.0" +version = "1.16.0" description = "Module for decorators, wrappers and monkey patching." optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -files = [ - {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, - {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, - {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, - {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, - {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, - {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, - {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, - {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, - {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, - {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, - {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, - {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, - {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, - {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, - {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, - {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, - {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, - {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, - {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, +python-versions = ">=3.6" +files = [ + {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, + {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, + {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, + {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, + {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, + {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, + {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, + {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, + {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, + {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, + {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, + {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, + {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, + {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, + {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, + {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, + {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, + {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, ] [[package]] name = "yarl" -version = "1.9.2" +version = "1.9.4" description = "Yet another URL library" optional = false python-versions = ">=3.7" files = [ - {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, - {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, - {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, - {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, - {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, - {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, - {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, - {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, - {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, - {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, - {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, - {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, - {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, - {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, - {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, + {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, + {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, + {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, + {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, + {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, + {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, + {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, + {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, + {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, + {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, + {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, + {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, + {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, + {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, + {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, ] [package.dependencies] @@ -3772,28 +4440,28 @@ multidict = ">=4.0" [[package]] name = "zipp" -version = "3.16.2" +version = "3.19.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.16.2-py3-none-any.whl", hash = "sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0"}, - {file = "zipp-3.16.2.tar.gz", hash = "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147"}, + {file = "zipp-3.19.0-py3-none-any.whl", hash = "sha256:96dc6ad62f1441bcaccef23b274ec471518daf4fbbc580341204936a5a3dddec"}, + {file = "zipp-3.19.0.tar.gz", hash = "sha256:952df858fb3164426c976d9338d3961e8e8b3758e2e059e0f754b8c4262625ee"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [extras] -actions = ["nylas"] -agents = ["google-cloud-aiplatform"] -all = ["elevenlabs", "google-cloud-aiplatform", "google-cloud-speech", "google-cloud-texttospeech", "gtts", "nylas", "redis", "twilio", "vonage"] -synthesizers = ["elevenlabs", "google-cloud-texttospeech", "gtts"] +agents = ["anthropic", "openai", "tiktoken"] +all = ["anthropic", "azure-cognitiveservices-speech", "elevenlabs", "google-cloud-speech", "google-cloud-texttospeech", "langchain", "langchain-community", "miniaudio", "nltk", "openai", "pvkoala", "pydub", "pyht", "redis", "sentry-sdk", "tiktoken", "twilio", "vonage"] +misc = ["langchain", "langchain-community", "sentry-sdk"] +synthesizers = ["azure-cognitiveservices-speech", "elevenlabs", "google-cloud-texttospeech", "miniaudio", "nltk", "pvkoala", "pydub", "pyht"] telephony = ["redis", "twilio", "vonage"] transcribers = ["google-cloud-speech"] [metadata] lock-version = "2.0" -python-versions = ">=3.8.1,<3.12" -content-hash = "69f7c4477423f9ac80c4ad74767eb35a1b001498da8d9b207c3d00f0cab832ff" +python-versions = ">=3.10,<4.0" +content-hash = "ee0e29c5a613ac943287786c64a591f516801fcada5aa7411d9f2d26ff2a7405" diff --git a/pyproject.toml b/pyproject.toml index e43119d8b..3df2cf670 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,85 +1,140 @@ [tool.poetry] name = "vocode" -version = "0.1.112a0" +version = "0.1.111" description = "The all-in-one voice SDK" authors = ["Ajay Raj "] license = "MIT License" readme = "README.md" homepage = "https://github.com/vocodedev/vocode-python" + [tool.poetry.dependencies] -python = ">=3.8.1,<3.12" -pydub = "^0.25.1" -nltk = "^3.8.1" -openai = "^0.27.8" -sounddevice = "^0.4.6" -azure-cognitiveservices-speech = "^1.27.0" -websockets = "^11.0.2" -requests = "^2.28.2" -uvicorn = "^0.21.1" -fastapi = "^0.100.1" -jinja2 = "^3.1.2" -python-multipart = "^0.0.6" -six = "^1.16.0" -opentelemetry-sdk = "^1.17.0" +python = ">=3.10,<4.0" +aiohttp = "^3.9.5" +fastapi = "^0.111.0" janus = "^1.0.0" -scipy = "^1.10.1" -anthropic = "^0.7.1" - -elevenlabs = {version = "^0.2.6", optional = true} -google-cloud-texttospeech = {version = "^2.16.1", optional = true} -gtts = {version = "^2.3.1", optional = true} - -google-cloud-speech = {version = "^2.19.0", optional = true} - -redis = {version = "^4.5.4", optional = true} -twilio = {version = "^8.1.0", optional = true} -vonage = {version = "^3.5.1", optional = true} -nylas = {version = "^5.14.0", optional = true} -speechrecognition = "^3.10.0" -aiohttp = "^3.8.4" -langchain = "^0.1.4" -google-cloud-aiplatform = {version = "^1.26.0", optional = true} -miniaudio = "^1.59" -boto3 = "^1.28.28" -pydantic = "^2.0" -langchain-community = "^0.0.16" - +jinja2 = "^3.1.4" +jsonschema = "^4.22.0" +loguru = "^0.7.2" +opentelemetry-sdk = "^1.24.0" +phonenumbers = "^8.13.37" +pydantic = "^2.7.2" +requests = "^2.32.3" +sounddevice = "^0.4.7" +uvicorn = "^0.30.0" +websockets = "^12.0" + +# Agents +anthropic = { version = "^0.28.0", optional = true } +openai = { version = "^1.30.5", optional = true } +tiktoken = { version = "0.7.0", optional = true } + +# Synthesizers +azure-cognitiveservices-speech = { version = "^1.37.0", optional = true } +elevenlabs = { version = "^1.2.2", optional = true } +google-cloud-texttospeech = { version = "^2.16.3", optional = true } +miniaudio = { version = "^1.59", optional = true } +nltk = { version = "^3.8.1", optional = true } +pvkoala = { version = "^2.0.1", optional = true } +pydub = { version = "^0.25.1", optional = true } +pyht = { version = "^0.0.28", optional = true } + +# Transcribers +google-cloud-speech = { version = "^2.26.0", optional = true } + +# Telephony +redis = { version = "^5.0.4", optional = true } +twilio = { version = "^9.1.0", optional = true } +vonage = { version = "^3.14.0", optional = true } + +# Misc +langchain = { version = "^0.2.1", optional = true } +langchain-community = { version = "^0.2.1", optional = true } +sentry-sdk = { extras = ["fastapi"], version = "^2.3.1", optional = true } [tool.poetry.group.lint.dependencies] black = "^24.4.2" +isort = "^5.13.2" +[tool.poetry.group.typing.dependencies] +mypy = "^1.10.0" +pydub-stubs = "^0.25.1.0" +types-redis = "^4.6.0" +types-regex = "^2024.5.15.20240519" +types-requests = "^2.32.0.20240523" [tool.poetry.group.dev.dependencies] -python-dotenv = "^1.0.0" -pytest = "^7.4.3" -pytest-asyncio = "^0.21.0" -aioresponses = "^0.7.4" -pre-commit = "^3.3.3" -pytest-mock = "^3.12.0" - +aioresponses = "^0.7.6" +coverage = "^7.5.3" +fakeredis = "^2.23.2" +pytest = "^8.2.1" +pytest-asyncio = "^0.23.7" +pytest-cov = "^5.0.0" +pytest-env = "^1.1.3" +pytest-httpx = "^0.30.0" +pytest-mock = "^3.14.0" -[tool.poetry.group.typing.dependencies] -mypy = "^1.8.0" -pydub-stubs = "^0.25.1.0" -types-requests = "^2.30.0.0" -types-regex = "^2023.5.5.0" -types-redis = "^4.5.5.2" +[tool.poetry.extras] +agents = ["anthropic", "openai", "tiktoken"] +synthesizers = [ + "azure-cognitiveservices-speech", + "elevenlabs", + "google-cloud-texttospeech", + "miniaudio", + "nltk", + "pvkoala", + "pydub", + "pyht", +] +transcribers = ["google-cloud-speech"] +telephony = ["twilio", "redis", "vonage"] +misc = ["langchain", "langchain-community", "sentry-sdk"] +all = [ + "anthropic", + "openai", + "tiktoken", + "azure-cognitiveservices-speech", + "elevenlabs", + "google-cloud-texttospeech", + "miniaudio", + "nltk", + "pvkoala", + "pydub", + "pyht", + "google-cloud-speech", + "twilio", + "redis", + "vonage", + "langchain", + "langchain-community", + "sentry-sdk", +] [tool.mypy] -ignore_missing_imports = "True" +ignore_missing_imports = true exclude = ["venv", ".venv"] -explicit_package_bases = "True" +explicit_package_bases = true -[tool.poetry.extras] -synthesizers = ["gtts", "google-cloud-texttospeech", "elevenlabs"] -transcribers = ["google-cloud-speech"] -telephony = ["twilio", "redis", "vonage"] -agents = ["google-cloud-aiplatform"] -actions = ["nylas"] -all = ["gtts", "google-cloud-texttospeech", "elevenlabs", "google-cloud-speech", "google-cloud-aiplatform", "twilio", "redis", "nylas", "vonage"] +[tool.pytest.ini_options] +addopts = "--basetemp=/tmp/pytest" +testpaths = ["tests"] + +[tool.pytest_env] +ENVIRONMENT = "test" +AZURE_OPENAI_API_BASE_EAST_US = "https://api.openai.com" +AZURE_OPENAI_API_KEY_EAST_US = "test" + +[tool.coverage.run] +omit = ["tests/*"] + +[tool.black] +line-length = 100 + +[tool.isort] +profile = "black" +line_length = 100 [build-system] diff --git a/quickstarts/streaming_conversation.py b/quickstarts/streaming_conversation.py index d02124a6b..4d22ec046 100644 --- a/quickstarts/streaming_conversation.py +++ b/quickstarts/streaming_conversation.py @@ -1,25 +1,26 @@ import asyncio -import logging import signal + from dotenv import load_dotenv +from vocode.logging import configure_pretty_logging +from vocode.streaming.agent.chat_gpt_agent import ChatGPTAgent +from vocode.streaming.models.agent import ChatGPTAgentConfig +from vocode.streaming.models.synthesizer import AzureSynthesizerConfig +from vocode.streaming.models.transcriber import ( + DeepgramTranscriberConfig, + PunctuationEndpointingConfig, +) +from vocode.streaming.synthesizer.azure_synthesizer import AzureSynthesizer +from vocode.streaming.transcriber.deepgram_transcriber import DeepgramTranscriber load_dotenv() -from vocode.streaming.streaming_conversation import StreamingConversation from vocode.helpers import create_streaming_microphone_input_and_speaker_output -from vocode.streaming.transcriber import * -from vocode.streaming.agent import * -from vocode.streaming.synthesizer import * -from vocode.streaming.models.transcriber import * -from vocode.streaming.models.agent import * -from vocode.streaming.models.synthesizer import * from vocode.streaming.models.message import BaseMessage +from vocode.streaming.streaming_conversation import StreamingConversation - -logging.basicConfig() -logger = logging.getLogger(__name__) -logger.setLevel(logging.DEBUG) +configure_pretty_logging() async def main(): @@ -28,7 +29,6 @@ async def main(): speaker_output, ) = create_streaming_microphone_input_and_speaker_output( use_default_devices=False, - logger=logger, use_blocking_speaker_output=True, # this moves the playback to a separate thread, set to False to use the main thread ) @@ -46,16 +46,11 @@ async def main(): prompt_preamble="""The AI is having a pleasant conversation about life""", ) ), - synthesizer=AzureSynthesizer( - AzureSynthesizerConfig.from_output_device(speaker_output) - ), - logger=logger, + synthesizer=AzureSynthesizer(AzureSynthesizerConfig.from_output_device(speaker_output)), ) await conversation.start() print("Conversation started, press Ctrl+C to end") - signal.signal( - signal.SIGINT, lambda _0, _1: asyncio.create_task(conversation.terminate()) - ) + signal.signal(signal.SIGINT, lambda _0, _1: asyncio.create_task(conversation.terminate())) while conversation.is_active(): chunk = await microphone_input.get_audio() conversation.receive_audio(chunk) diff --git a/quickstarts/turn_based_conversation.py b/quickstarts/turn_based_conversation.py index 4afaaeb9b..35eef61fe 100644 --- a/quickstarts/turn_based_conversation.py +++ b/quickstarts/turn_based_conversation.py @@ -1,17 +1,12 @@ -import logging from dotenv import load_dotenv + from vocode import getenv from vocode.helpers import create_turn_based_microphone_input_and_speaker_output from vocode.turn_based.agent.chat_gpt_agent import ChatGPTAgent from vocode.turn_based.synthesizer.azure_synthesizer import AzureSynthesizer -from vocode.turn_based.synthesizer.eleven_labs_synthesizer import ElevenLabsSynthesizer from vocode.turn_based.transcriber.whisper_transcriber import WhisperTranscriber from vocode.turn_based.turn_based_conversation import TurnBasedConversation -logging.basicConfig() -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) - load_dotenv() # See https://api.elevenlabs.io/v1/voices @@ -23,7 +18,6 @@ speaker_output, ) = create_turn_based_microphone_input_and_speaker_output( use_default_devices=False, - logger=logger, ) conversation = TurnBasedConversation( @@ -40,7 +34,6 @@ region=getenv("AZURE_SPEECH_REGION"), voice_name="en-US-SteffanNeural", ), - logger=logger, ) print("Starting conversation. Press Ctrl+C to exit.") while True: diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 000000000..59e0c4358 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,66 @@ +import os +from typing import Generator +from unittest import mock + +import pytest +from fakeredis import FakeAsyncRedis +from pytest import FixtureRequest, MonkeyPatch + + +@pytest.fixture(scope="session") +def default_env_vars() -> dict[str, str]: + """ + Defines default environment variables for the test session. + + This fixture provides a dictionary of default environment variables that are + commonly used across tests. It can be overridden in submodule scoped `conftest.py` + files or directly in tests. + + :return: A dictionary of default environment variables. + """ + return { + "ENVIRONMENT": "test", + "AZURE_OPENAI_API_BASE_EAST_US": "https://api.openai.com", + "AZURE_OPENAI_API_KEY_EAST_US": "test", + } + + +@pytest.fixture() +def mock_env( + monkeypatch: MonkeyPatch, request: pytest.FixtureRequest, default_env_vars: dict[str, str] +) -> Generator[None, None, None]: + """ + Temporarily sets environment variables for testing. + + This fixture allows tests to run with a modified set of environment variables, + either using the default set provided by `default_env_vars` or overridden by + test-specific parameters. It ensures that changes to environment variables do + not leak between tests. + + :param monkeypatch: The pytest monkeypatch fixture for modifying environment variables. + :param request: The pytest FixtureRequest object for accessing test-specific overrides. + :param default_env_vars: A dictionary of default environment variables. + :yield: None. This is a setup-teardown fixture that cleans up after itself. + """ + envvars = default_env_vars.copy() + if hasattr(request, "param") and isinstance(request.param, dict): + envvars.update(request.param) + + with mock.patch.dict(os.environ, envvars): + yield + + +@pytest.fixture +def redis_client(request: FixtureRequest) -> FakeAsyncRedis: + """ + Provides a fake Redis client for asynchronous operations. + + This fixture can be used in tests that require a Redis client but should not + interact with a real Redis instance. It leverages fakeredis to simulate Redis + operations in memory without any external dependencies. + + :param request: The pytest request object, used here for potential future extensions. + :return: An instance of a fake Redis client. + """ + redis_client = FakeAsyncRedis() + return redis_client diff --git a/tests/fakedata/conversation.py b/tests/fakedata/conversation.py new file mode 100644 index 000000000..c538b45ae --- /dev/null +++ b/tests/fakedata/conversation.py @@ -0,0 +1,85 @@ +from typing import Optional + +from pytest_mock import MockerFixture + +from vocode.streaming.agent.base_agent import BaseAgent +from vocode.streaming.models.agent import AgentConfig, ChatGPTAgentConfig +from vocode.streaming.models.audio import AudioEncoding +from vocode.streaming.models.message import BaseMessage +from vocode.streaming.models.synthesizer import PlayHtSynthesizerConfig, SynthesizerConfig +from vocode.streaming.models.transcriber import DeepgramTranscriberConfig, TranscriberConfig +from vocode.streaming.output_device.base_output_device import BaseOutputDevice +from vocode.streaming.streaming_conversation import StreamingConversation +from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer +from vocode.streaming.telephony.constants import DEFAULT_CHUNK_SIZE, DEFAULT_SAMPLING_RATE +from vocode.streaming.transcriber.base_transcriber import BaseTranscriber +from vocode.streaming.transcriber.deepgram_transcriber import DeepgramEndpointingConfig +from vocode.streaming.utils.events_manager import EventsManager + +DEFAULT_DEEPGRAM_TRANSCRIBER_CONFIG = DeepgramTranscriberConfig( + chunk_size=DEFAULT_CHUNK_SIZE, + sampling_rate=DEFAULT_SAMPLING_RATE, + audio_encoding=AudioEncoding.MULAW, + endpointing_config=DeepgramEndpointingConfig(), + model="2-phonecall", + tier="nova", +) + +DEFAULT_SYNTHESIZER_CONFIG = PlayHtSynthesizerConfig( + sampling_rate=DEFAULT_SAMPLING_RATE, + audio_encoding=AudioEncoding.MULAW, +) + +DEFAULT_CHAT_GPT_AGENT_CONFIG = ChatGPTAgentConfig( + prompt_preamble="You are an agent of chaos", initial_message=BaseMessage(text="Hi there!") +) + + +class DummyOutputDevice(BaseOutputDevice): + def consume_nonblocking(self, chunk: bytes): + pass + + +def create_fake_transcriber(mocker: MockerFixture, transcriber_config: TranscriberConfig): + transcriber = mocker.MagicMock() + transcriber.get_transcriber_config = mocker.MagicMock(return_value=transcriber_config) + return transcriber + + +def create_fake_agent(mocker: MockerFixture, agent_config: AgentConfig): + agent = mocker.MagicMock() + agent.get_agent_config = mocker.MagicMock(return_value=agent_config) + return agent + + +def create_fake_synthesizer(mocker: MockerFixture, synthesizer_config: SynthesizerConfig): + synthesizer = mocker.MagicMock() + synthesizer.get_synthesizer_config = mocker.MagicMock(return_value=synthesizer_config) + return synthesizer + + +def create_fake_streaming_conversation( + mocker: MockerFixture, + transcriber: Optional[BaseTranscriber[TranscriberConfig]] = None, + agent: Optional[BaseAgent] = None, + synthesizer: Optional[BaseSynthesizer] = None, + speed_coefficient: float = 1.0, + conversation_id: Optional[str] = None, + events_manager: Optional[EventsManager] = None, +): + transcriber = transcriber or create_fake_transcriber( + mocker, DEFAULT_DEEPGRAM_TRANSCRIBER_CONFIG + ) + agent = agent or create_fake_agent(mocker, DEFAULT_CHAT_GPT_AGENT_CONFIG) + synthesizer = synthesizer or create_fake_synthesizer(mocker, DEFAULT_SYNTHESIZER_CONFIG) + return StreamingConversation( + output_device=DummyOutputDevice( + sampling_rate=DEFAULT_SAMPLING_RATE, audio_encoding=AudioEncoding.MULAW + ), + transcriber=transcriber, + agent=agent, + synthesizer=synthesizer, + speed_coefficient=speed_coefficient, + conversation_id=conversation_id, + events_manager=events_manager, + ) diff --git a/tests/fakedata/id.py b/tests/fakedata/id.py new file mode 100644 index 000000000..7117ba458 --- /dev/null +++ b/tests/fakedata/id.py @@ -0,0 +1,5 @@ +import uuid + + +def generate_uuid() -> uuid.UUID: + return uuid.uuid4() diff --git a/tests/streaming/__init__.py b/tests/streaming/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/streaming/action/conftest.py b/tests/streaming/action/conftest.py new file mode 100644 index 000000000..622af9fa3 --- /dev/null +++ b/tests/streaming/action/conftest.py @@ -0,0 +1,31 @@ +import pytest + + +@pytest.fixture(scope="session") +def default_env_vars(default_env_vars: dict[str, str]) -> dict[str, str]: + """ + Extends the `default_env_vars` fixture specifically for the submodule. + + This fixture takes the session-scoped `default_env_vars` fixture from the parent conftest.py + and extends or overrides it with additional or modified environment variables specific to + the submodule. + + :param default_env_vars: The inherited `default_env_vars` fixture from the parent conftest. + :return: A modified dictionary of default environment variables for the submodule. + """ + submodule_env_vars = default_env_vars.copy() + + submodule_env_vars.update( + { + "VONAGE_API_KEY": "test", + "VONAGE_API_SECRET": "test", + "VONAGE_APPLICATION_ID": "test", + "VONAGE_PRIVATE_KEY": """-----BEGIN PRIVATE KEY----- +fake_key +-----END PRIVATE KEY-----""", + "BASE_URL": "test", + "CALL_SERVER_BASE_URL": "test2", + } + ) + + return submodule_env_vars diff --git a/tests/streaming/action/test_dtmf.py b/tests/streaming/action/test_dtmf.py new file mode 100644 index 000000000..1f7097086 --- /dev/null +++ b/tests/streaming/action/test_dtmf.py @@ -0,0 +1,77 @@ +import pytest +from aioresponses import aioresponses +from tests.fakedata.id import generate_uuid + +from vocode.streaming.action.dtmf import ( + DTMFParameters, + DTMFVocodeActionConfig, + TwilioDTMF, + VonageDTMF, +) +from vocode.streaming.models.actions import ( + TwilioPhoneConversationActionInput, + VonagePhoneConversationActionInput, +) +from vocode.streaming.models.telephony import VonageConfig +from vocode.streaming.utils import create_conversation_id +from vocode.streaming.utils.state_manager import VonagePhoneConversationStateManager + + +@pytest.mark.asyncio +async def test_vonage_dtmf_press_digits(mocker, mock_env): + action = VonageDTMF(action_config=DTMFVocodeActionConfig()) + vonage_uuid = generate_uuid() + digits = "1234" + + vonage_phone_conversation_mock = mocker.MagicMock() + vonage_config = VonageConfig( + api_key="api_key", + api_secret="api_secret", + application_id="application_id", + private_key="-----BEGIN PRIVATE KEY-----\nasdf\n-----END PRIVATE KEY-----", + ) + vonage_phone_conversation_mock.vonage_config = vonage_config + mocker.patch("vonage.Client._create_jwt_auth_string", return_value=b"asdf") + + action.attach_conversation_state_manager( + VonagePhoneConversationStateManager(vonage_phone_conversation_mock) + ) + + assert ( + action.conversation_state_manager.create_vonage_client().get_telephony_config() + == vonage_config + ) + + with aioresponses() as m: + m.put( + f"https://api.nexmo.com/v1/calls/{vonage_uuid}/dtmf", + status=200, + ) + action_output = await action.run( + action_input=VonagePhoneConversationActionInput( + action_config=DTMFVocodeActionConfig(), + conversation_id=create_conversation_id(), + params=DTMFParameters(buttons=digits), + vonage_uuid=str(vonage_uuid), + ) + ) + + assert action_output.response.success is True + + +@pytest.mark.asyncio +async def test_twilio_dtmf_press_digits(mocker, mock_env): + action = TwilioDTMF(action_config=DTMFVocodeActionConfig()) + digits = "1234" + twilio_sid = "twilio_sid" + + action_output = await action.run( + action_input=TwilioPhoneConversationActionInput( + action_config=DTMFVocodeActionConfig(), + conversation_id=create_conversation_id(), + params=DTMFParameters(buttons=digits), + twilio_sid=twilio_sid, + ) + ) + + assert action_output.response.success is False # Twilio does not support DTMF diff --git a/tests/streaming/action/test_end_conversation.py b/tests/streaming/action/test_end_conversation.py new file mode 100644 index 000000000..44cfb5109 --- /dev/null +++ b/tests/streaming/action/test_end_conversation.py @@ -0,0 +1,132 @@ +import asyncio +from typing import Generator, Type +from unittest.mock import MagicMock +from uuid import UUID + +import pytest +from pydantic.v1 import BaseModel +from pytest_mock import MockerFixture +from tests.fakedata.id import generate_uuid + +from vocode.streaming.action.end_conversation import ( + EndConversation, + EndConversationParameters, + EndConversationVocodeActionConfig, +) +from vocode.streaming.models.actions import ( + TwilioPhoneConversationActionInput, + VonagePhoneConversationActionInput, +) +from vocode.streaming.models.transcript import Transcript +from vocode.streaming.utils import create_conversation_id + + +class EndConversationActionTestCase(BaseModel): + class Config: + arbitrary_types_allowed = True + + action: EndConversation + vonage_uuid: UUID + twilio_sid: str + conversation_id: str + + +@pytest.fixture +def end_conversation_action_test_case(mocker: MockerFixture) -> EndConversationActionTestCase: + action = EndConversation(action_config=EndConversationVocodeActionConfig()) + return EndConversationActionTestCase( + action=action, + vonage_uuid=generate_uuid(), + twilio_sid="twilio_sid", + conversation_id=create_conversation_id(), + ) + + +@pytest.fixture +def conversation_state_manager_mock(mocker: MockerFixture) -> MagicMock: + mock = mocker.MagicMock() + mock.terminate_conversation = mocker.AsyncMock() + mock.transcript = Transcript() + return mock + + +@pytest.fixture +def user_message_tracker() -> asyncio.Event: + tracker = asyncio.Event() + tracker.set() + return tracker + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "action_input_class, identifier", + [ + (VonagePhoneConversationActionInput, "vonage_uuid"), + (TwilioPhoneConversationActionInput, "twilio_sid"), + ], +) +async def test_end_conversation_success( + mocker: MockerFixture, + mock_env: Generator, + end_conversation_action_test_case: EndConversationActionTestCase, + conversation_state_manager_mock: MagicMock, + user_message_tracker: asyncio.Event, + action_input_class: Type[BaseModel], + identifier: str, +): + end_conversation_action_test_case.action.attach_conversation_state_manager( + conversation_state_manager_mock + ) + + identifier_value = getattr(end_conversation_action_test_case, identifier) + action_input = action_input_class( + action_config=EndConversationVocodeActionConfig(), + conversation_id=end_conversation_action_test_case.conversation_id, + params=EndConversationParameters(), + **{identifier: str(identifier_value)}, + user_message_tracker=user_message_tracker, + ) + + response = await end_conversation_action_test_case.action.run(action_input=action_input) + + assert response.response.success + assert conversation_state_manager_mock.terminate_conversation.call_count == 1 + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "action_input_class, identifier", + [ + (VonagePhoneConversationActionInput, "vonage_uuid"), + (TwilioPhoneConversationActionInput, "twilio_sid"), + ], +) +async def test_end_conversation_fails_if_interrupted( + mocker: MockerFixture, + mock_env: Generator, + end_conversation_action_test_case: EndConversationActionTestCase, + conversation_state_manager_mock: MagicMock, + user_message_tracker: asyncio.Event, + action_input_class: Type[BaseModel], + identifier: str, +): + conversation_state_manager_mock.transcript.add_bot_message( + "Unfinished", conversation_id=end_conversation_action_test_case.conversation_id + ) + end_conversation_action_test_case.action.attach_conversation_state_manager( + conversation_state_manager_mock + ) + + identifier_value = getattr(end_conversation_action_test_case, identifier) + action_input = action_input_class( + action_config=EndConversationVocodeActionConfig(), + conversation_id=end_conversation_action_test_case.conversation_id, + params=EndConversationParameters(), + **{identifier: str(identifier_value)}, + user_message_tracker=user_message_tracker, + ) + + response = await end_conversation_action_test_case.action.run(action_input=action_input) + + assert not response.response.success + assert conversation_state_manager_mock.terminate_conversation.call_count == 0 diff --git a/tests/streaming/action/test_external_actions.py b/tests/streaming/action/test_external_actions.py new file mode 100644 index 000000000..53eb3a477 --- /dev/null +++ b/tests/streaming/action/test_external_actions.py @@ -0,0 +1,122 @@ +import base64 +import json +import os + +import pytest +from tests.fakedata.id import generate_uuid + +from vocode.streaming.action.execute_external_action import ( + ExecuteExternalAction, + ExecuteExternalActionParameters, + ExecuteExternalActionVocodeActionConfig, +) +from vocode.streaming.action.external_actions_requester import ExternalActionResponse +from vocode.streaming.models.actions import ( + TwilioPhoneConversationActionInput, + VonagePhoneConversationActionInput, +) +from vocode.streaming.utils import create_conversation_id +from vocode.streaming.utils.state_manager import ( + TwilioPhoneConversationStateManager, + VonagePhoneConversationStateManager, +) + +ACTION_INPUT_SCHEMA: dict = { + "type": "object", + "properties": { + "length": {"type": "string", "enum": ["30m", "1hr"]}, + "time": {"type": "string", "pattern": r"^\d{2}:\d0[ap]m$"}, + }, +} + + +@pytest.fixture +def action_config() -> dict: + """Provides a common action configuration for tests.""" + return { + "processing_mode": "muted", + "name": "name", + "description": "A description", + "url": "https://example.com", + "input_schema": json.dumps(ACTION_INPUT_SCHEMA), + "speak_on_send": True, + "speak_on_receive": True, + "signature_secret": base64.b64encode(os.urandom(32)).decode(), + } + + +@pytest.fixture +def execute_action_setup(mocker, action_config) -> ExecuteExternalAction: + """Common setup for creating an ExecuteExternalAction instance.""" + action = ExecuteExternalAction( + action_config=ExecuteExternalActionVocodeActionConfig(**action_config), + ) + mocked_requester = mocker.AsyncMock() + mocked_requester.send_request.return_value = ExternalActionResponse( + result={"test": "test"}, + agent_message="message!", + success=True, + ) + action.external_actions_requester = mocked_requester + return action + + +@pytest.fixture +def mock_twilio_conversation_state_manager(mocker) -> TwilioPhoneConversationStateManager: + """Fixture to mock TwilioPhoneConversationStateManager.""" + manager = mocker.MagicMock(spec=TwilioPhoneConversationStateManager) + manager.mute_agent = mocker.MagicMock() + # Add any other necessary mock setup here + return manager + + +@pytest.fixture +def mock_vonage_conversation_state_manager(mocker) -> VonagePhoneConversationStateManager: + """Fixture to mock VonagePhoneConversationStateManager.""" + manager = mocker.MagicMock(spec=VonagePhoneConversationStateManager) + manager.mute_agent = mocker.MagicMock() + # Add any other necessary mock setup here + return manager + + +@pytest.mark.asyncio +async def test_vonage_execute_external_action_success( + mocker, + mock_vonage_conversation_state_manager: VonagePhoneConversationStateManager, + execute_action_setup: ExecuteExternalAction, +): + execute_action_setup.attach_conversation_state_manager(mock_vonage_conversation_state_manager) + vonage_uuid = generate_uuid() + + response = await execute_action_setup.run( + action_input=VonagePhoneConversationActionInput( + action_config=execute_action_setup.action_config, + conversation_id=create_conversation_id(), + params=ExecuteExternalActionParameters(payload={}), + vonage_uuid=str(vonage_uuid), + ), + ) + + assert response.response.success + assert response.response.result == {"test": "test"} + + +@pytest.mark.asyncio +async def test_twilio_execute_external_action_success( + mocker, + mock_twilio_conversation_state_manager: TwilioPhoneConversationStateManager, + execute_action_setup: ExecuteExternalAction, +): + execute_action_setup.attach_conversation_state_manager(mock_twilio_conversation_state_manager) + + response = await execute_action_setup.run( + action_input=TwilioPhoneConversationActionInput( + action_config=execute_action_setup.action_config, + conversation_id=create_conversation_id(), + params=ExecuteExternalActionParameters(payload={}), + twilio_sid="twilio_sid", + ), + ) + + assert response.response.success + assert response.response.result == {"test": "test"} diff --git a/tests/streaming/action/test_external_actions_requester.py b/tests/streaming/action/test_external_actions_requester.py new file mode 100644 index 000000000..c9d2f8b35 --- /dev/null +++ b/tests/streaming/action/test_external_actions_requester.py @@ -0,0 +1,82 @@ +import base64 +import hashlib +import hmac +import json +import os +from typing import Any, Callable, Dict + +import pytest +from httpx import Request, Response +from pytest_httpx import HTTPXMock + +from vocode.streaming.action.external_actions_requester import ExternalActionsRequester + +JSON_SCHEMA = { + "type": "object", + "properties": { + "length": { + "type": "string", + "enum": ["30m", "1hr"], + }, + "time": { + "type": "string", + "pattern": r"^\d{2}:\d0[ap]m$", + }, + }, +} + + +@pytest.fixture +def mock_async_client_post(status_code: int, json_response: Dict[str, Any]) -> Callable: + async def mock_post(self, url: str, content: str, headers: Dict[str, str] = None) -> Response: + request = Request(method="POST", url=url, headers=headers, content=content) + return Response(status_code, json=json_response, request=request) + + return mock_post + + +@pytest.fixture +def requester() -> ExternalActionsRequester: + return ExternalActionsRequester("http://test.com") + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "status_code,json_response,expected_success", + [ + (200, {"result": {"key": "value"}, "agent_message": "Success", "success": True}, True), + (400, {"detail": "Bad Request"}, False), + (401, {"detail": "Unauthorized"}, False), + (403, {"detail": "Forbidden"}, False), + (500, {"detail": "Server Error"}, False), + ], +) +async def test_send_request_responses( + httpx_mock: HTTPXMock, + status_code: int, + json_response: Dict[str, Any], + expected_success: bool, +) -> None: + url = "http://test.com" + httpx_mock.add_response(status_code=status_code, json=json_response, method="POST", url=url) + + requester = ExternalActionsRequester(url) + response = await requester.send_request( + JSON_SCHEMA, + base64.b64encode(os.urandom(32)).decode(), + additional_payload_values={"call_id": "call_id"}, + ) + + assert response.success is expected_success + + +@pytest.mark.asyncio +async def test_requester_encodes_signature_correctly(requester: ExternalActionsRequester): + payload = json.dumps({"test": "test"}).encode("utf-8") + signature_as_bytes = os.urandom(32) + signature = base64.b64encode(signature_as_bytes).decode() + + encoded_payload = requester._encode_payload(payload, signature) + decoded_digest = base64.b64decode(encoded_payload) + calculated_digest = hmac.new(signature_as_bytes, payload, hashlib.sha256).digest() + assert hmac.compare_digest(decoded_digest, calculated_digest) diff --git a/tests/streaming/action/test_record_email.py b/tests/streaming/action/test_record_email.py new file mode 100644 index 000000000..1b66dc156 --- /dev/null +++ b/tests/streaming/action/test_record_email.py @@ -0,0 +1,77 @@ +import pytest +from tests.fakedata.id import generate_uuid + +from vocode.streaming.action.record_email import ( + RecordEmail, + RecordEmailParameters, + RecordEmailVocodeActionConfig, +) +from vocode.streaming.models.actions import ( + TwilioPhoneConversationActionInput, + VonagePhoneConversationActionInput, +) +from vocode.streaming.utils import create_conversation_id + +# id is just a description of the parameterized test case's input +EMAIL_TEST_CASES = [ + pytest.param("kian@vocode.dev", True, id="valid_email_with_dev"), + pytest.param("kian+tester@vocode.net", True, id="valid_email_with_plus_in_local_part"), + pytest.param("kian-tester@vocode.org", True, id="valid_email_with_dash_in_local_part"), + pytest.param("kian.vocode@dev.com", True, id="valid_email_with_dot_in_local_part"), + pytest.param("kian@vocode", False, id="missing_tld"), + pytest.param("kian", False, id="missing_at_and_tld"), + pytest.param("kian@", False, id="missing_domain"), + pytest.param("@vocode.dev", False, id="missing_local_part"), + pytest.param(".kian@vocode.dev", False, id="leading_dot_in_local_part"), + pytest.param("kian.@vocode.dev", False, id="trailing_dot_in_local_part"), + pytest.param("kian..tester@vocode.com", False, id="consecutive_dots_in_local_part"), + pytest.param("kian@vo..code.com", False, id="consecutive_dots_in_domain"), + pytest.param("kian@vocode.com.", False, id="trailing_dot_in_domain"), + pytest.param("ki'an@vocode.net", False, id="apostrophe_in_local_part"), + pytest.param("kian@vocode..org", False, id="consecutive_dots_in_tld"), + pytest.param("kian@.vocode.net", False, id="leading_dot_in_domain"), +] + + +@pytest.fixture +def record_email_action() -> RecordEmail: + return RecordEmail(action_config=RecordEmailVocodeActionConfig()) + + +@pytest.mark.asyncio +@pytest.mark.parametrize("email_input,expected_success", EMAIL_TEST_CASES) +async def test_vonage_email_validation( + record_email_action: RecordEmail, email_input: str, expected_success: bool +): + vonage_uuid = generate_uuid() + res = await record_email_action.run( + action_input=VonagePhoneConversationActionInput( + action_config=RecordEmailVocodeActionConfig(), + conversation_id=create_conversation_id(), + params=RecordEmailParameters( + raw_value="", + formatted_value=email_input, + ), + vonage_uuid=str(vonage_uuid), + ), + ) + assert res.response.success == expected_success + + +@pytest.mark.asyncio +@pytest.mark.parametrize("email_input,expected_success", EMAIL_TEST_CASES) +async def test_twilio_email_validation( + record_email_action: RecordEmail, email_input: str, expected_success: bool +): + res = await record_email_action.run( + action_input=TwilioPhoneConversationActionInput( + action_config=RecordEmailVocodeActionConfig(), + conversation_id=create_conversation_id(), + params=RecordEmailParameters( + raw_value="", + formatted_value=email_input, + ), + twilio_sid="twilio_sid", + ), + ) + assert res.response.success == expected_success diff --git a/tests/streaming/action/test_transfer_call.py b/tests/streaming/action/test_transfer_call.py new file mode 100644 index 000000000..59c6ea35c --- /dev/null +++ b/tests/streaming/action/test_transfer_call.py @@ -0,0 +1,222 @@ +import asyncio +from typing import Any +from unittest.mock import MagicMock + +import aiohttp +import pytest +from aioresponses import aioresponses +from pytest_mock import MockerFixture +from tests.fakedata.id import generate_uuid + +from vocode.streaming.action.transfer_call import ( + TransferCallParameters, + TransferCallVocodeActionConfig, + TwilioTransferCall, + VonageTransferCall, +) +from vocode.streaming.models.actions import ( + TwilioPhoneConversationActionInput, + VonagePhoneConversationActionInput, +) +from vocode.streaming.models.events import Sender +from vocode.streaming.models.telephony import TwilioConfig, VonageConfig +from vocode.streaming.models.transcript import Message, Transcript +from vocode.streaming.utils import create_conversation_id +from vocode.streaming.utils.state_manager import ( + TwilioPhoneConversationStateManager, + VonagePhoneConversationStateManager, +) + +TRANSFER_PHONE_NUMBER = "12345678920" + + +@pytest.fixture +def mock_twilio_config(): + return TwilioConfig( + account_sid="account_sid", + auth_token="auth_token", + ) + + +@pytest.fixture +def mock_vonage_config(): + return VonageConfig( + api_key="api_key", + api_secret="api_secret", + application_id="application_id", + private_key="-----BEGIN PRIVATE KEY-----\nasdf\n-----END PRIVATE KEY-----", + ) + + +@pytest.fixture +def mock_twilio_phone_conversation(mock_twilio_config) -> MagicMock: + twilio_phone_conversation = MagicMock() + twilio_phone_conversation.twilio_config = mock_twilio_config + return twilio_phone_conversation + + +@pytest.fixture +def mock_vonage_phone_conversation(mock_vonage_config) -> MagicMock: + vonage_phone_conversation = MagicMock() + vonage_phone_conversation.vonage_config = mock_vonage_config + return vonage_phone_conversation + + +@pytest.fixture +def mock_twilio_conversation_state_manager( + mocker: Any, mock_twilio_phone_conversation: MagicMock +) -> TwilioPhoneConversationStateManager: + return TwilioPhoneConversationStateManager(mock_twilio_phone_conversation) + + +@pytest.fixture +def mock_vonage_conversation_state_manager( + mocker: Any, mock_vonage_phone_conversation: MagicMock +) -> VonagePhoneConversationStateManager: + return VonagePhoneConversationStateManager(mock_vonage_phone_conversation) + + +@pytest.mark.asyncio +async def test_twilio_transfer_call_succeeds( + mocker: Any, + mock_twilio_conversation_state_manager: TwilioPhoneConversationStateManager, + mock_twilio_phone_conversation: MagicMock, + mock_twilio_config: TwilioConfig, +): + action = TwilioTransferCall( + action_config=TransferCallVocodeActionConfig(phone_number=TRANSFER_PHONE_NUMBER), + ) + user_message_tracker = asyncio.Event() + user_message_tracker.set() + action.attach_conversation_state_manager(mock_twilio_conversation_state_manager) + conversation_id = create_conversation_id() + + twilio_sid = "twilio_sid" + action_input = TwilioPhoneConversationActionInput( + action_config=TransferCallVocodeActionConfig(phone_number=TRANSFER_PHONE_NUMBER), + conversation_id=conversation_id, + params=TransferCallParameters(), + twilio_sid=twilio_sid, + user_message_tracker=user_message_tracker, + ) + + mock_twilio_phone_conversation.transcript = Transcript(event_logs=[]) + + with aioresponses() as m: + m.post( + "https://api.twilio.com/2010-04-01/Accounts/{twilio_account_sid}/Calls/{twilio_call_sid}.json".format( + twilio_account_sid=mock_twilio_config.account_sid, + twilio_call_sid=twilio_sid, + ), + status=200, + ) + action_output = await action.run(action_input=action_input) + assert action_output.response.success, "Expected action response to be successful" + m.assert_called_once_with( + f"https://api.twilio.com/2010-04-01/Accounts/{mock_twilio_config.account_sid}/Calls/{twilio_sid}.json", + method="POST", + auth=aiohttp.BasicAuth( + login=mock_twilio_config.account_sid, + password=mock_twilio_config.auth_token, + ), + data={"Twiml": f"{TRANSFER_PHONE_NUMBER}"}, + ) + + +@pytest.mark.asyncio +async def test_twilio_transfer_call_fails_if_interrupted( + mocker: Any, + mock_twilio_conversation_state_manager: TwilioPhoneConversationStateManager, + mock_twilio_phone_conversation: MagicMock, +) -> None: + action = TwilioTransferCall( + action_config=TransferCallVocodeActionConfig(phone_number=TRANSFER_PHONE_NUMBER), + ) + user_message_tracker = asyncio.Event() + user_message_tracker.set() + action.attach_conversation_state_manager(mock_twilio_conversation_state_manager) + conversation_id = create_conversation_id() + + inner_transfer_call_mock = mocker.patch( + "vocode.streaming.action.transfer_call.TwilioTransferCall.transfer_call", + autospec=True, + ) + + mock_twilio_phone_conversation.transcript = Transcript( + event_logs=[ + Message( + sender=Sender.BOT, + text="Please hold while I transfer you", + is_end_of_turn=False, + ) + ] + ) + + action_input = TwilioPhoneConversationActionInput( + action_config=TransferCallVocodeActionConfig(phone_number=TRANSFER_PHONE_NUMBER), + conversation_id=conversation_id, + params=TransferCallParameters(), + twilio_sid="twilio_sid", + user_message_tracker=user_message_tracker, + ) + + action_output = await action.run(action_input=action_input) + + assert inner_transfer_call_mock.call_count == 0, "Expected transfer_call to not be called" + assert not action_output.response.success, "Expected action response to be unsuccessful" + + +@pytest.mark.asyncio +async def test_vonage_transfer_call_inbound( + mocker: MockerFixture, + mock_env, + mock_vonage_conversation_state_manager: VonagePhoneConversationStateManager, +) -> None: + transfer_phone_number = "12345678920" + action = VonageTransferCall( + action_config=TransferCallVocodeActionConfig(phone_number=transfer_phone_number), + ) + + mocker.patch("vonage.Client._create_jwt_auth_string", return_value=b"asdf") + + vonage_uuid = generate_uuid() + + mock_vonage_conversation_state_manager._vonage_phone_conversation.direction = "inbound" + mock_vonage_conversation_state_manager._vonage_phone_conversation.to_phone = "1234567894" + mock_vonage_conversation_state_manager._vonage_phone_conversation.from_phone = "1234567895" + + conversation_id = create_conversation_id() + + action.attach_conversation_state_manager(mock_vonage_conversation_state_manager) + + user_message_tracker = asyncio.Event() + user_message_tracker.set() + + with aioresponses() as m: + m.put( + f"https://api.nexmo.com/v1/calls/{vonage_uuid}", + payload={}, + status=200, + ) + + action_input = VonagePhoneConversationActionInput( + action_config=TransferCallVocodeActionConfig(phone_number=transfer_phone_number), + conversation_id=conversation_id, + params=TransferCallParameters(), + vonage_uuid=str(vonage_uuid), + user_message_tracker=user_message_tracker, + ) + action_output = await action.run(action_input=action_input) + + assert action_output.response.success + assert action_output.action_type == "action_transfer_call" + + call = list(m.requests.values())[0][0] + + ncco = call.kwargs["json"]["destination"]["ncco"] + + assert ncco[0]["endpoint"][0]["number"] == transfer_phone_number + assert ( + ncco[0]["from"] + == mock_vonage_conversation_state_manager._vonage_phone_conversation.to_phone # if inbound, the agent number is the to_phone + ) diff --git a/tests/streaming/action/test_wait.py b/tests/streaming/action/test_wait.py new file mode 100644 index 000000000..bea3acc9a --- /dev/null +++ b/tests/streaming/action/test_wait.py @@ -0,0 +1,23 @@ +import pytest + +from vocode.streaming.action.wait import Wait, WaitParameters, WaitVocodeActionConfig +from vocode.streaming.models.actions import ActionInput +from vocode.streaming.utils import create_conversation_id + + +@pytest.mark.asyncio +async def test_wait_action_success_without_user_message_tracker(): + action_config = WaitVocodeActionConfig() + wait_action = Wait(action_config=action_config) + action_input = ActionInput[WaitParameters]( + action_config=action_config, + conversation_id=create_conversation_id(), + user_message_tracker=None, + params=WaitParameters(), + ) + + action_output = await wait_action.run(action_input) + + assert ( + action_output.response.success is True + ), "Expected the wait action to succeed without a user message tracker" diff --git a/tests/streaming/agent/test_base_agent.py b/tests/streaming/agent/test_base_agent.py new file mode 100644 index 000000000..c6a0adb95 --- /dev/null +++ b/tests/streaming/agent/test_base_agent.py @@ -0,0 +1,179 @@ +import asyncio +from typing import List, Optional + +import pytest +from pytest_mock import MockerFixture + +from vocode.streaming.action.abstract_factory import AbstractActionFactory +from vocode.streaming.agent.base_agent import ( + AgentResponse, + AgentResponseMessage, + BaseAgent, + GeneratedResponse, + TranscriptionAgentInput, +) +from vocode.streaming.agent.chat_gpt_agent import ChatGPTAgent +from vocode.streaming.models.actions import EndOfTurn +from vocode.streaming.models.agent import ChatGPTAgentConfig +from vocode.streaming.models.message import BaseMessage +from vocode.streaming.models.transcriber import Transcription +from vocode.streaming.models.transcript import Transcript +from vocode.streaming.utils.state_manager import ConversationStateManager +from vocode.streaming.utils.worker import InterruptibleEvent + + +@pytest.fixture(autouse=True) +def mock_env(mocker: MockerFixture): + mocker.patch.dict( + "os.environ", + { + "OPENAI_API_KEY": "openai_api_key", + }, + ) + + +def _create_agent( + mocker: MockerFixture, + agent_config: ChatGPTAgentConfig, + transcript: Optional[Transcript] = None, + action_factory: Optional[AbstractActionFactory] = None, + conversation_state_manager: Optional[ConversationStateManager] = None, +) -> ChatGPTAgent: + agent = ChatGPTAgent(agent_config, action_factory=action_factory) + if transcript: + agent.attach_transcript(transcript) + else: + agent.attach_transcript(Transcript()) + if conversation_state_manager: + agent.attach_conversation_state_manager(conversation_state_manager) + else: + agent.attach_conversation_state_manager(mocker.MagicMock()) + return agent + + +async def _consume_until_end_of_turn(agent: BaseAgent, timeout: float = 0.1) -> List[AgentResponse]: + agent_responses = [] + try: + while True: + agent_response = await asyncio.wait_for(agent.output_queue.get(), timeout=timeout) + agent_responses.append(agent_response.payload) + if isinstance(agent_response.payload, AgentResponseMessage) and isinstance( + agent_response.payload.message, EndOfTurn + ): + break + except asyncio.TimeoutError: + pass + return agent_responses + + +def _send_transcription( + agent: BaseAgent, + transcription: Transcription, + agent_response_tracker: Optional[asyncio.Event] = None, + is_interruptible: bool = False, +): + agent.consume_nonblocking( + InterruptibleEvent( + payload=TranscriptionAgentInput( + conversation_id="conversation_id", transcription=transcription + ), + is_interruptible=is_interruptible, + ) + ) + + +def _send_action_output( + agent: BaseAgent, + action_output: str, + agent_response_tracker: Optional[asyncio.Event] = None, + is_interruptible: bool = False, +): + agent.consume_nonblocking( + InterruptibleEvent( + payload=action_output, + is_interruptible=is_interruptible, + agent_response_tracker=agent_response_tracker, + ) + ) + + +def _mock_generate_response( + mocker: MockerFixture, agent: BaseAgent, generated_responses: List[GeneratedResponse] +): + async def mock_generate_response(*args, **kwargs): + for response in generated_responses: + yield response + + mocker.patch.object(agent, "generate_response", mock_generate_response) + + +@pytest.mark.asyncio +async def test_generate_responses(mocker: MockerFixture): + agent_config = ChatGPTAgentConfig( + prompt_preamble="Have a pleasant conversation about life", + generate_responses=True, + ) + agent = _create_agent(mocker, agent_config) + _mock_generate_response( + mocker, + agent, + [ + GeneratedResponse( + message=BaseMessage(text="Hi, how are you doing today?"), is_interruptible=True + ) + ], + ) + _send_transcription( + agent, + Transcription(message="Hello?", confidence=1.0, is_final=True), + ) + agent.start() + agent_responses = await _consume_until_end_of_turn(agent) + agent.terminate() + + messages = [response.message for response in agent_responses] + + assert messages == [BaseMessage(text="Hi, how are you doing today?"), EndOfTurn()] + + +@pytest.mark.asyncio +async def test_generate_response(mocker: MockerFixture): + agent_config = ChatGPTAgentConfig( + prompt_preamble="Have a pleasant conversation about life", + generate_responses=True, + ) + agent = _create_agent(mocker, agent_config) + _mock_generate_response( + mocker, + agent, + [ + GeneratedResponse( + message=BaseMessage(text="Hi, how are you doing today?"), is_interruptible=True + ) + ], + ) + _send_transcription( + agent, + Transcription(message="Hello?", confidence=1.0, is_final=True), + ) + agent.start() + agent_responses = await _consume_until_end_of_turn(agent) + agent.terminate() + + messages = [response.message for response in agent_responses] + + assert messages == [BaseMessage(text="Hi, how are you doing today?"), EndOfTurn()] + + +@pytest.mark.asyncio +async def test_function_call(mocker: MockerFixture): + # TODO: assert that when we return a function call with a user message, it sends out a message alongside + # an end of turn with the same agent response tracker + pass + + +@pytest.mark.asyncio +async def test_action_response_agent_input(mocker: MockerFixture): + # TODO: assert that the canned response is optionally sent if the action is not quiet + # and that it goes through the normal flow when the action is not quiet + pass diff --git a/tests/streaming/agent/test_openai_utils.py b/tests/streaming/agent/test_openai_utils.py new file mode 100644 index 000000000..4858c9294 --- /dev/null +++ b/tests/streaming/agent/test_openai_utils.py @@ -0,0 +1,303 @@ +from vocode.streaming.agent.openai_utils import format_openai_chat_messages_from_transcript +from vocode.streaming.models.actions import ( + ACTION_FINISHED_FORMAT_STRING, + ActionConfig, + ActionInput, + ActionOutput, + PhraseBasedActionTrigger, + PhraseBasedActionTriggerConfig, +) +from vocode.streaming.models.events import Sender +from vocode.streaming.models.transcript import ActionFinish, ActionStart, Message, Transcript + + +class WeatherActionConfig(ActionConfig, type="weather"): + pass + + +def create_fake_vocode_phrase_trigger(): + return PhraseBasedActionTrigger(config=PhraseBasedActionTriggerConfig(phrase_triggers=[])) + + +def test_format_openai_chat_messages_from_transcript(): + test_action_input_nophrase = ActionInput( + action_config=WeatherActionConfig(), + conversation_id="asdf", + params={}, + ) + test_action_input_phrase = ActionInput( + action_config=WeatherActionConfig(action_trigger=create_fake_vocode_phrase_trigger()), + conversation_id="asdf", + params={}, + ) + + test_cases = [ + ( + ( + Transcript( + event_logs=[ + Message(sender=Sender.BOT, text="Hello!", is_final=True), + Message( + sender=Sender.BOT, + text="How are you doing today?", + is_final=True, + ), + Message(sender=Sender.HUMAN, text="I'm doing well, thanks!"), + ] + ), + "gpt-3.5-turbo-0613", + None, + "prompt preamble", + ), + [ + {"role": "system", "content": "prompt preamble"}, + {"role": "assistant", "content": "Hello! How are you doing today?"}, + {"role": "user", "content": "I'm doing well, thanks!"}, + ], + ), + ( + ( + Transcript( + event_logs=[ + Message(sender=Sender.BOT, text="Hello!", is_final=True), + Message(sender=Sender.BOT, text="How are", is_final=False), + ] + ), + "gpt-3.5-turbo-0613", + None, + "prompt preamble", + ), + [ + {"role": "system", "content": "prompt preamble"}, + {"role": "assistant", "content": "Hello! How are-"}, + ], + ), + ( + ( + Transcript( + event_logs=[ + Message(sender=Sender.BOT, text="Hello!", is_final=True), + Message(sender=Sender.HUMAN, text="Hello, what's the weather like?"), + ActionStart( + action_type="weather", + action_input=test_action_input_nophrase, + ), + ActionFinish( + action_type="weather", + action_input=test_action_input_nophrase, + action_output=ActionOutput(action_type="weather", response={}), + ), + ] + ), + "gpt-3.5-turbo-0613", + None, + "some prompt", + ), + [ + {"role": "system", "content": "some prompt"}, + {"role": "assistant", "content": "Hello!"}, + { + "role": "user", + "content": "Hello, what's the weather like?", + }, + { + "role": "assistant", + "content": None, + "function_call": {"name": "weather", "arguments": "{}"}, + }, + { + "role": "function", + "name": "weather", + "content": ACTION_FINISHED_FORMAT_STRING.format( + action_name="weather", action_output="{}" + ), + }, + ], + ), + ( + ( + Transcript( + event_logs=[ + Message(sender=Sender.BOT, text="Hello!", is_final=True), + Message(sender=Sender.HUMAN, text="Hello, what's the weather like?"), + ActionStart( + action_type="weather", + action_input=test_action_input_phrase, + ), + ActionFinish( + action_type="weather", + action_input=test_action_input_phrase, + action_output=ActionOutput(action_type="weather", response={}), + ), + ] + ), + "gpt-3.5-turbo-0613", + None, + "some prompt", + ), + [ + {"role": "system", "content": "some prompt"}, + {"role": "assistant", "content": "Hello!"}, + { + "role": "user", + "content": "Hello, what's the weather like?", + }, + { + "role": "function", + "name": "weather", + "content": ACTION_FINISHED_FORMAT_STRING.format( + action_name="weather", action_output="{}" + ), + }, + ], + ), + ] + + for params, expected_output in test_cases: + assert format_openai_chat_messages_from_transcript(*params) == expected_output + + +def test_format_openai_chat_messages_from_transcript_context_limit(): + test_cases = [ + ( + ( + Transcript( + event_logs=[ + Message(sender=Sender.BOT, text="Hello!", is_final=True), + Message( + sender=Sender.BOT, + text="How are you doing today? I'm doing amazing thank you so much for asking!", + ), + Message(sender=Sender.HUMAN, text="I'm doing well, thanks!"), + ] + ), + "gpt-3.5-turbo-0613", + None, + "aaaa " * 1862, + ), + [ + {"role": "system", "content": "aaaa " * 1862}, + {"role": "user", "content": "I'm doing well, thanks!"}, + ], + ), + ( + ( + Transcript( + event_logs=[ + Message(sender=Sender.BOT, text="Hello!"), + Message( + sender=Sender.BOT, + text="How are you doing today? I'm doing amazing thank you so much for asking!", + is_final=True, + ), + Message(sender=Sender.HUMAN, text="I'm doing well, thanks!"), + Message(sender=Sender.BOT, text="aaaa " * 1862), + Message(sender=Sender.HUMAN, text="What? What did you just say???"), + Message( + sender=Sender.BOT, + text="My apologies, there was an error. Please ignore my previous message", + is_final=True, + ), + Message( + sender=Sender.HUMAN, + text="Don't worry I ignored all 1862 * 5 characters of it.", + ), + ] + ), + "gpt-3.5-turbo-0613", + None, + "prompt preamble", + ), + [ + {"role": "system", "content": "prompt preamble"}, + { + "content": "What? What did you just say???", + "role": "user", + }, + { + "role": "assistant", + "content": "My apologies, there was an error. Please ignore my previous message", + }, + { + "role": "user", + "content": "Don't worry I ignored all 1862 * 5 characters of it.", + }, + ], + ), + ] + + for params, expected_output in test_cases: + assert format_openai_chat_messages_from_transcript(*params) == expected_output + + +def test_format_openai_chat_messages_from_transcript_context_limit(): + test_cases = [ + ( + ( + Transcript( + event_logs=[ + Message(sender=Sender.BOT, text="Hello!", is_final=True), + Message( + sender=Sender.BOT, + text="How are you doing today? I'm doing amazing thank you so much for asking!", + ), + Message(sender=Sender.HUMAN, text="I'm doing well, thanks!"), + ] + ), + "gpt-3.5-turbo-0613", + None, + "aaaa " * 1862, + ), + [ + {"role": "system", "content": "aaaa " * 1862}, + {"role": "user", "content": "I'm doing well, thanks!"}, + ], + ), + ( + ( + Transcript( + event_logs=[ + Message(sender=Sender.BOT, text="Hello!"), + Message( + sender=Sender.BOT, + text="How are you doing today? I'm doing amazing thank you so much for asking!", + is_final=True, + ), + Message(sender=Sender.HUMAN, text="I'm doing well, thanks!"), + Message(sender=Sender.BOT, text="aaaa " * 1862), + Message(sender=Sender.HUMAN, text="What? What did you just say???"), + Message( + sender=Sender.BOT, + text="My apologies, there was an error. Please ignore my previous message", + is_final=True, + ), + Message( + sender=Sender.HUMAN, + text="Don't worry I ignored all 1862 * 5 characters of it.", + ), + ] + ), + "gpt-3.5-turbo-0613", + None, + "prompt preamble", + ), + [ + {"role": "system", "content": "prompt preamble"}, + { + "content": "What? What did you just say???", + "role": "user", + }, + { + "role": "assistant", + "content": "My apologies, there was an error. Please ignore my previous message", + }, + { + "role": "user", + "content": "Don't worry I ignored all 1862 * 5 characters of it.", + }, + ], + ), + ] + + for params, expected_output in test_cases: + assert format_openai_chat_messages_from_transcript(*params) == expected_output diff --git a/tests/streaming/agent/test_utils.py b/tests/streaming/agent/test_streaming_utils.py similarity index 71% rename from tests/streaming/agent/test_utils.py rename to tests/streaming/agent/test_streaming_utils.py index 1eb0f30e5..db46c4a2a 100644 --- a/tests/streaming/agent/test_utils.py +++ b/tests/streaming/agent/test_streaming_utils.py @@ -1,28 +1,17 @@ -from typing import Any, Dict, List, Optional, Union -from openai.openai_object import OpenAIObject -from pydantic.v1 import BaseModel -from vocode.streaming.models.actions import ( - ActionConfig, - ActionInput, - ActionOutput, - FunctionCall, -) +from typing import Any, AsyncGenerator, Dict, List, Optional, Union + import pytest -from vocode.streaming.agent.utils import ( - collate_response_async, - format_openai_chat_messages_from_transcript, - openai_get_tokens, -) -from vocode.streaming.models.events import Sender -from vocode.streaming.models.transcript import ( - ActionFinish, - ActionStart, - Message, - Transcript, -) +from openai.types.chat.chat_completion_chunk import ChatCompletionChunk +from pydantic.v1 import BaseModel + +from vocode.streaming.agent.openai_utils import openai_get_tokens +from vocode.streaming.agent.streaming_utils import collate_response_async +from vocode.streaming.models.actions import FunctionCall -async def _agen_from_list(l): +async def _agen_from_chunk_list( + l: List[ChatCompletionChunk], +) -> AsyncGenerator[ChatCompletionChunk, Any]: for item in l: yield item @@ -31,21 +20,30 @@ def create_chatgpt_openai_object( delta: Optional[Dict[str, str]] = None, finish_reason: Optional[Any] = None, prompt_annotations=None, -): - inner_obj = {} +) -> ChatCompletionChunk: + inner_obj = { + "id": "test_id", + "created": 1423143, + "model": "gpt-3.5-turbo-0613", + "object": "chat.completion.chunk", + "choices": [], + } if prompt_annotations: inner_obj["prompt_annotations"] = prompt_annotations inner_obj["choices"] = [] elif delta: - inner_obj["choices"] = [{"delta": delta, "finish_reason": finish_reason}] - return OpenAIObject.construct_from(inner_obj) + inner_obj["choices"] = [{"index": 0, "delta": delta, "finish_reason": finish_reason}] + return ChatCompletionChunk.parse_obj(inner_obj) class StreamOpenAIResponseTestCase(BaseModel): - openai_objects: List[OpenAIObject] + openai_objects: List[ChatCompletionChunk] expected_sentences: List[Union[str, FunctionCall]] get_functions: bool + class Config: + arbitrary_types_allowed = True + OPENAI_OBJECTS = [ [ @@ -233,11 +231,57 @@ class StreamOpenAIResponseTestCase(BaseModel): }, {"delta": {}, "finish_reason": "function_call"}, ], + [ + {"delta": {"role": "assistant"}, "finish_reason": None}, + {"delta": {"content": "Yes"}, "finish_reason": None}, + {"delta": {"content": "."}, "finish_reason": None}, + {"delta": {"content": " Hi"}, "finish_reason": None}, + {"delta": {"content": "."}, "finish_reason": None}, + {"delta": {"content": " Ok"}, "finish_reason": None}, + {"delta": {"content": "."}, "finish_reason": None}, + {"delta": {"content": " What"}, "finish_reason": None}, + {"delta": {"content": " is"}, "finish_reason": None}, + {"delta": {"content": " it"}, "finish_reason": None}, + {"delta": {"content": "?"}, "finish_reason": None}, + {"delta": {}, "finish_reason": "stop"}, + ], + [ + {"delta": {"role": "assistant"}, "finish_reason": None}, + {"delta": {"content": "Ok"}, "finish_reason": None}, + {"delta": {"content": " gotcha"}, "finish_reason": None}, + {"delta": {"content": "."}, "finish_reason": None}, + {"delta": {"content": " What"}, "finish_reason": None}, + {"delta": {"content": " is"}, "finish_reason": None}, + {"delta": {"content": " up"}, "finish_reason": None}, + {"delta": {"content": " man"}, "finish_reason": None}, + {"delta": {"content": "."}, "finish_reason": None}, + {"delta": {"content": " Nothing"}, "finish_reason": None}, + {"delta": {"content": " much"}, "finish_reason": None}, + {"delta": {"content": " how"}, "finish_reason": None}, + {"delta": {"content": " are"}, "finish_reason": None}, + {"delta": {"content": " you"}, "finish_reason": None}, + {"delta": {"content": "?"}, "finish_reason": None}, + {"delta": {}, "finish_reason": "stop"}, + ], + [ + {"delta": {"role": "assistant"}, "finish_reason": None}, + {"delta": {"content": "Hello"}, "finish_reason": None}, + {"delta": {"content": "?"}, "finish_reason": None}, + {"delta": {"content": " Yes"}, "finish_reason": None}, + {"delta": {"content": "?"}, "finish_reason": None}, + {"delta": {"content": " Hello"}, "finish_reason": None}, + {"delta": {"content": "?"}, "finish_reason": None}, + {"delta": {"content": "Is"}, "finish_reason": None}, + {"delta": {"content": " this"}, "finish_reason": None}, + {"delta": {"content": " Bob"}, "finish_reason": None}, + {"delta": {"content": "?"}, "finish_reason": None}, + {"delta": {}, "finish_reason": "stop"}, + ], ] EXPECTED_SENTENCES = [ - ["Hello!", "How are you doing today?"], - ["Hello.", "What do you want to talk about?"], + ["Hello! How are you doing today?"], + ["Hello. What do you want to talk about?"], ["This is a test sentence.", "Want to hear a joke?"], [ "Sure, here are three possible things we could talk about:", @@ -249,18 +293,15 @@ class StreamOpenAIResponseTestCase(BaseModel): "$1 + $3.20 is equal to $4.20.", "And $1.40 plus $2.80 is equal to $4.20 as well.", ], + ["$2 + $3.00 is equal to $5.", "$6 + $4 is equal to $10."], [ - "$2 + $3.00 is equal to $5.", - "$6 + $4 is equal to $10.", - ], - [ - "Hello.", - "What do you want to talk about", - FunctionCall(name="wave_hello", arguments='{\n "name": "user"\n}'), - ], - [ + "Hello. What do you want to talk about", FunctionCall(name="wave_hello", arguments='{\n "name": "user"\n}'), ], + [FunctionCall(name="wave_hello", arguments='{\n "name": "user"\n}')], + ["Yes. Hi. Ok. What is it?"], + ["Ok gotcha. What is up man.", "Nothing much how are you?"], + ["Hello? Yes? Hello?", "Is this Bob?"], ] FUNCTIONS_INPUT = [ @@ -313,130 +354,22 @@ class StreamOpenAIResponseTestCase(BaseModel): @pytest.mark.asyncio -async def test_collate_response_async(): +async def test_collate_response_async(mocker): test_cases = [ StreamOpenAIResponseTestCase( - openai_objects=[ - create_chatgpt_openai_object(**obj) for obj in openai_objects - ], + openai_objects=[create_chatgpt_openai_object(**obj) for obj in openai_objects], expected_sentences=expected_sentences, - get_functions=any( - isinstance(item, FunctionCall) for item in expected_sentences - ), - ) - for openai_objects, expected_sentences in zip( - OPENAI_OBJECTS, EXPECTED_SENTENCES + get_functions=any(isinstance(item, FunctionCall) for item in expected_sentences), ) + for openai_objects, expected_sentences in zip(OPENAI_OBJECTS, EXPECTED_SENTENCES) ] for test_case in test_cases: actual_sentences = [] async for sentence in collate_response_async( - openai_get_tokens(_agen_from_list(test_case.openai_objects)), + conversation_id="test", + gen=openai_get_tokens(_agen_from_chunk_list(test_case.openai_objects)), get_functions=test_case.get_functions, ): actual_sentences.append(sentence) assert actual_sentences == test_case.expected_sentences - - -def test_format_openai_chat_messages_from_transcript(): - test_cases = [ - ( - ( - Transcript( - event_logs=[ - Message(sender=Sender.BOT, text="Hello!"), - Message(sender=Sender.BOT, text="How are you doing today?"), - Message(sender=Sender.HUMAN, text="I'm doing well, thanks!"), - ] - ), - "prompt preamble", - ), - [ - {"role": "system", "content": "prompt preamble"}, - {"role": "assistant", "content": "Hello! How are you doing today?"}, - {"role": "user", "content": "I'm doing well, thanks!"}, - ], - ), - ( - ( - Transcript( - event_logs=[ - Message(sender=Sender.BOT, text="Hello!"), - Message(sender=Sender.BOT, text="How are you doing today?"), - Message(sender=Sender.HUMAN, text="I'm doing well, thanks!"), - ] - ), - None, - ), - [ - {"role": "assistant", "content": "Hello! How are you doing today?"}, - {"role": "user", "content": "I'm doing well, thanks!"}, - ], - ), - ( - ( - Transcript( - event_logs=[ - Message(sender=Sender.BOT, text="Hello!"), - Message(sender=Sender.BOT, text="How are you doing today?"), - ] - ), - "prompt preamble", - ), - [ - {"role": "system", "content": "prompt preamble"}, - {"role": "assistant", "content": "Hello! How are you doing today?"}, - ], - ), - ( - ( - Transcript( - event_logs=[ - Message(sender=Sender.BOT, text="Hello!"), - Message( - sender=Sender.HUMAN, text="Hello, what's the weather like?" - ), - ActionStart( - action_type="weather", - action_input=ActionInput( - action_config=ActionConfig(), - conversation_id="asdf", - params={}, - ), - ), - ActionFinish( - action_type="weather", - action_output=ActionOutput( - action_type="weather", response={} - ), - ), - ] - ), - None, - ), - [ - {"role": "assistant", "content": "Hello!"}, - { - "role": "user", - "content": "Hello, what's the weather like?", - }, - { - "role": "assistant", - "content": None, - "function_call": { - "name": "weather", - "arguments": "{}", - }, - }, - { - "role": "function", - "name": "weather", - "content": "{}", - }, - ], - ), - ] - - for params, expected_output in test_cases: - assert format_openai_chat_messages_from_transcript(*params) == expected_output diff --git a/tests/streaming/data/__init__.py b/tests/streaming/data/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/streaming/data/fake_audio.mp3 b/tests/streaming/data/fake_audio.mp3 deleted file mode 100644 index ecb1351d30c40a4c717aa6e52c19f18d6a20085b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11593 zcmeHt^;29y)9$jk1QuId77OmKi@Uo9CundD!Cito1b5dUNpN>}2pTkau&_70-}l}B z;8xvRb)O$*s%K8s>8E?9Pfwqbm*PSIynf9~%e{^9ZQ z@#*R5`T6fZyu7@?V6fMh|5MK5pK@G$ufqR;2I0T;WFa-brd#-*;s5lo>->HIh#wgL z4hjH76~~B-M*2DBLqYs%APfcgpVt>kFyy`m?~tqQdr^u9XaAS_fNfaHeeMei{OibH z(+AjNz}SzR2j`ElXZFlr;kG=9Sz4|wGyv?FumegYq;YxKKw=U@t5h6}cST5m976gK zCS^D(w9250;NMk;E2(TA}1b$bd=9I|&uKrbJ z?EQkY;HFXN@H(|8a7Ri&BDeO_IqY8W0^f%_Zv?oVK0{nfprmx?L`E9>+78WJZnc zx0@8Ve3FK2tY2i6{1#HyP*-#+n{U@RWZ+7Xbi3ic{N@ScI=nj&9C|g}iEQ6pGDTK5 zf^b7guf^dH@1^!No&&1CeO<7jgOkNX4PmwRc6R|G4wK2Y&(|4ql4@Co4T|~;c{%$N z$H@?&3k|WcS}b8@YlD&4q{hof)=fzpbt20Vg%aAbWGZrTB(&<2oK8`Zl{{ARqU5-m zYAjUs<|F3%uF4`|U-mAm)6VFF-U=u4+$^LRj~xBIw{grw;&r5&5Jov0ajxv22{6f| zQo-sfKK#?jkenAjRARz@2P(Pi+|1M@H1SEImjQ1M&xLBIrGEVkbJ48kZxtsx^x6U> z#W4@2IzS> zxIgv=h~q`W(0azZ@(9#_{Wa-WbB@uzl~A}zYCBr$)i|NRZSPUs)w(>#d& zt!fJQ=RTA<@@K?{rcMRL6qiYII3LDQH(DrwkY3^?k#2qR)+NtW=2IM@5rU=Npaf7n zD<&L-LcFX3M#5qj58cM@8Vv#Tp<(nQKs3FiZZ>dQ;jd5)STf%ruyh-%_+Gp>?M5mw zMHkcy8;n8miblmmV-AW1AbwO}p5EmPQvjCv-n}!I6AxYzs{L$#P=pvI1%DVZ}^e2`7)<}-no9RRWpJ+Uzws+Q^nWw{&Fa*ByFK-3ikMC zeLpA=-JBov!)57c*j|TH4_DOWoOGY-`v#u3J5ZLfI#>*I;6SY9&Q_Xb5xXN(EfAegUcR` z12$A-P*(#Zq8haEVP;5zD^>@SDx5N#Z|#hKWCp-GzikpOIArd+j!PTzt$yvMeNMJ| z*OKLbZa8r3(G~_~8mQ4Op1(dFa-0jWuDE&@LpFKAXHv}Obzfj8C>Jt3FELsQa3Rk0 zdh<6vAmC*A?~7K(i_j9!<2ljKTRywnc(aa0#t$r`0@7W_{io_)>GoH~YpE<6Af37?Bk3)cbb2%@zk~vW;k1}sG8}#Jvul{ z-O_}Pnp3JQNSAGdW#O2iVMO=b;~&8+DiB(omQGzznxh;a?RHTN$lKV)rD*gw`Hf2P zrB>?p(Q6!4^wy_p+?SQ?z(FVkn%q$P?xF-Fgi@&pddT z9h-A=j(z-R6@Z(KZzaTewF*z z`!~7_M3gT2Tx&1!T4{ST_UJCz{%mt2N|3vv5%{FGJu1$|bt7bKE&ebJ|H|i>V-IKW zWr9EsPLXb&e;SX8grVc5r3jEAaQ(#KzYRhu6@665_KRBIGXA|zi6P7?DQ_ds_?1aR zKdN4k^~AM}Rq}&qeQ8@JBf1Tz21WqGSz_sY>cP7vIxF)zzU>6yH^b3^mWM1_&&7p< z_)~{EZeMe&tEnwQ0A+xe3k!^EY2RZ2KVWh)4!Plm12gL@DT}>T4pU9q7}Y%4XIhEA z5Ma72AqUl)8CIs&;cW61m(PrbD&N0rcL!4?kLcPdoQj*{Q7gGVB5HEJ^4aIMm>naZ z!;Z6+${0DFg{%+X;Fvzi7ga|p;GPk5{p{R6oa}$$qX?}jEsKR>1Sy$CFM3x`I&$X` zo1(KL=Z4s`9mYv*e%EfGt# znPp+Qy`QxO6lfS zJdUU`c7QkchsfDYNaA^2cBojQ+#L zDDmjNWtsq53K3>D>z2hhhOVw2+O+zS4)4~e`bJkjq8@f^`MaV=*aqyaQ%&<04EA#V zg^R;Rf4+h4Ejp;bd5#1_3I&>BAWdb=V$WLVaXY2b-mbPXY!lxoBJgU2P5zk4(t|mI z3aqCO)0NQt1V){qxppUe0SH_X>(`kW6k8&dpG55SKlkWJxrwQODnCU^AKp7(Gbb1h z(pzD4yt#cI4Nb4AP?QD4Q`owx>-8A{!#@vKZWl!j=^XMl9)57TQ=}VMTQtpB!0R7m z7$4wzT);bT+xl*<&OwA|Q^E_JE*c+)8)a7SU24Bhq~1YJx0^w5sdt3zZ6+ze*B)5_ zlo{0z`JMy*CDQ+Jtu-jo>Ki}fiYhUYMgpZEe52SGHAB;Hro9vk%GNswDqn-^IYV~WPkXi1QW z<3a>?f^H&8G1p0jBK`*xXc%7i7v_EmQOtj_gdO;lDXmk;OHYhp6`FfG*^+EdRx;w^ zB3VjU_R$&mjzZEn7v3T!?d^s}gIDrwpW@j0h>K!D;qtFeUFD%(Y`q(uYq)=Lum3=0 zifo}ek#L|(tgRV}&|QFo`PnwjY|)4XK2G8SElM@2GQe3n^be+%USzsc+^*_1lKex= zXlWRHDBAZImfFms#>TFs^Ypl1J_>+cF`COD2g6eWu%n+ zMb)Di)lZfhxu>d+Za&ys;Qq#{ZudajQu#8FWxb@Zv3imu|E5x&`a{5flYH%7N|;h- zCulnPL&J(Wl8WEbRT)^>(@N~^W#JGOl(u9Cvo=BBYs^bYNm=V$&WrF!ppa3bc%8hQ z!tp8qtifSc;lhHHm@IOpro{E#P<&_#3Nsk;>eRnHC#!k9b94IQ>;;q{U=O4m1!Wj< zY|_w%EKszs|AUcea~eR4;VGe0LkIYoR@$OV0(C9ggDFx)xzEuqDga05aN6`+=FV-3 z>V}B?LI$kyjl{+W{EBsSYm9T%JYJg2x;GW|!}eCXm6-?D(T8%G={^fZJd5=lY0D|8 zBJZ2sV-zZ~^dLM5OK;mlqR#9!Ub0>?hPF!UV6d&v!y8%^Y2RpVt;b)T`b)@gGF)eEPGrkFgsHQVI+$Qd(`8mR zF|pu_(>5JkLLc=2$Qf_!SF$RywjKhUf%GjBvJwWS5?$81tc(mC95sop3 z;-B}uwJS+C`^S9>tDLF|ORU2h&{e*4QbSi1N#90I5;xja7HdVHnP2*u@O_S4>QHgf zWk4f5r*_MXrd39Z9gvQX8nCoU7i8cnp9h>Ob^PkG7c#8YqROi7q~*bLM<)?}rwCsQ zO;wuYtxAoTcQA2_da%4si!E$&b@#L}TDy8R!j;%M*zsU@j*tdFPJQdUg^<$ysL7)T zJQ4<6@b6E%Nq^qs_vCyLFy(`}rq&9*vv zs?H#5)QaMEVfOqMfg(xnX-D6J5Q1v{gCo3jb z5w=sTv6abXC{<+c7=KGw1>-&rI>sD&=Zsi@8w0};uT09rtsnU8k`y#*Z4~^*c z=hjClKKUdrTYXGF$@Pc#6YauqWQXDJQ_UZs>3sHMs_qIzoCS4%I9YMT)FBX9p(K4DI}^QtqsTkVF^1If;ds!G~24^PEid? zmGg+&qdp7V^&h7#t2Qej7xY*{}EXfEoPH4rP(ig`r61HaRn2(9iOz~6domFU(E*Q_YIibcjP8- zKphERKWY$A6^=`_Q^g_lX1Fm%Hw&Tv%YGC37x>-5KAyWXga`b82x-BQI(X&sLHM5x zC0V^S<>=`%<1jLP(GWw_0}I>;<)jD+jk1FO9rK`sq|_PaL_{DoqVMThd*+0um>DVn zLInJ5frucNT5ne>Tww%yP!%NBuN1j z^8hujtd(V@4HofQO9-ko%$NgrF(n(=%#uyfFfp|Rx)BW zedJ}g+A_?e(=VpFUlf(>;}}mU7U%qye{||LV>M!-jsLc(u3^R8_3RW6N-EHB$)O#Q ztJ255o^exRPbge9PFUciKVU6)-Ftrf@}IJenlRV_={#?}`h49?+B)+Yr6u&`k}!)} z;Y(0jivbI|jrZTjvsDPO-bhAJ1;O$zUG-wbfnczVWMU$?w#v0(uNrM&eDs!@@tE}Z z&qWTTRWkTs7gslWzvjTZp*ax1!Sn6Ks`lBchA^06Q3C-JT3N}DXF(etkm3lK$c)aX z_sBW*jnChXgp2DarSf)cK;jy8rJ6X{P!{@fpRHato)wpM}TbB^{D8t^D>wX`p zwvy7vmJAbP%#5AYJiNC_9kHUdtvFni_T?Z>tzXm%9fB;faLT|*yt7_J^3@*Rre-F7 zg9Io;(L%*t-SxxlYfWUomOI!uSul&wC|*DhS{3a-3u0vzpB7)$Ti{sPRLwBa%g)Rb zp$p4y^;Y+4nQV$PJ3Gnpw-K7K{~T-ZYPdy(VkH0bl`lOVm*irRcSQH|TD91f*NCJZ z7*=qDB_#Fh!XP%yA2C8jUd7tou z!00?n-$S_Dbw}`6?|>7itBBUwViTmO^h<2{{d9<1#I8om4k_APF}9wILU0gmzK=_GQ|_oAx)%2; zL#Il=E(56e+Ra1q7bg5NY8v~+x-YCU?InktJI*?z=^$&;W_j{8#mIx@N^YoEA?MxQ zWc5_8I1i-x)Tt7MvAqj&w^0#YwRqijO9FnA;k>IW;|%!+`Iz+%>#D{uVvs7WDGCMc z5M3_~YCHjkBqbtoCXKCE28hsN(7BtH&=UZ_>*44n+zxFPhW5{~gDAU8l5IN0Q3@m` z^6_o6QU4r0B?zR~0>U9J7uOw06-@C*>DI()j%%(*r8{jcp61lm?W%&Xl@`!9kfwBq zq*ZfxFk$(6tXu9>-3G^7p!L!HGP0h&1;i8w7>M7=&P$|whzXK0m`W` zJ1CB+A#Ge| zgZl71AK}fD$R@Y+5fuoVZ1#OZ34K0XG93wCP)tI6Fj$RM@I7PcsGvIyk~biPP9n{Y z{s8>!mbndecDF64$UL$uMIy<_Z%D)eHkORd*7h-w%_? zvC1;~yvr8Q&F~@_HkSmcNQX+z_nB&%Qp#w75yctj<#;~b6;Yk3t2y)A1q&jZWj>e!wFToyQS^GGz5pfAa*GI>`u4xX7F_ZBDv+on{nn~5s(j__zkjD=Y z9o##FBpBiqr{bA@EBYAk(PIC%yp1zw(0BN$942u_oV9}D#~e6)NCXnNDpAO_+{NHY$a7-rb&Xq4dkK-<#;FxOGV%%L(7~>&i)7~P)Ncgkr!w9nT-}F zM(jNkTSZDVlFE~jD4tG}8Tk_hWaeCeD&7?DOwV8wR8$aULzbu=OgP9W#ra7oo+ndW zTPo6?hdi;ynpK!|y&{dZ&n#)(1{BYYz$5&pIlc{xCka z`W4YKu)%V>?3q~W(~1$*Bd0@)DC0QW0^2%aqh9c?$&zrKJr()u=P9^(IMB!66jNdR(QqU3z0L}$m1&{*zaPmK5awa*#Aq?hI<1$O3qXk8e!)Yyq zqD{qif%l*LnKm6YK01`#LZPKT1mE$MC9TP%q4f0T9z6z19Y5lNMa>oh~rw=TFqEK)EC?-9<5K{)%?;7pKyfG~+ZBFE8(T1(`e4EBq ziq>{)2K>wWDe?ACYqtW=RU032VWaA6?zhYzI$sPouiMQ_zEnlP*v26DvEv8;dUiSS@kuLUCJT z`zy+SC-f$7t2+(#HSJrUZsxC6$~}2xF$ZX_&UL=*v&0|2ban~VdIi9y#xQOperJCh z%fSJFI^#O2EcJJs%)n%Hbui}w5f{TH9{XnyE+{aEqZDb5 z*j$P03d`+X<1U9BvISnSEl)Q#hqwago{~UY8;4I0Z_Nz1Wdv9G4m$!9M|l=|Xb{J? z7kiB(H*}DHGK4d7mvh;MQ!g7Czjy?shev~`ly5Q~tcnpLH$E*p&WRkGLaxM%q=X2R z$d9DaV$T7=!wmq+-F2*|hfSSvs1e|xsKFKj$pF;A0)42GDJ2LMusmB}HHaOG%7_6c z6WHy{y;<)D7r2We4g$d=GQqB=`+t7u0!vZk{Q{KA)t6hEQc@L*Qzm;!?E(Xv#gTzg z-#LM7eOS;PN=_bg#!+SfHTW70-1mAiN6B1f4H5fC z8sRP&ou{|(>6OF{4nNZ>ryvhFVw}A0oy*PGNJrL^s#VXm_MJD?J1Q&2Uj821YO*5b zEs^uU+m?Gq5hkk(2mMeX&hnG|3t{dFkcv~t6XKnVCtrR~0yD1@(465ml z85MRZky)OSbdR$+y8xU8ay|q5Fklx!%@855-ZX&F2NM!FolR&3R1cCf$UqGY3I>4) z=}_cD%9RK?f%Wy^CLKSmZaG3FguqPNKmdRgaS(3%#&jGgK}n?D4F#G_pY)fae(Hk{ zB<;okh5!)JBA|rqKnw&Zv&5@cPrPoxdK7sVG{ExJe)PNRHvD=JA}s(a3{B4=5Kh zCEuY3LKBct00I~|{N1Do5&$Y9cmQ#y&yo`Rilwrs%#SRl+J1}EobSelyO&qMKw33~6nA$KW{trxBZgYpPnj$r=!Mkc5ET44HjXDyv)vwMe>`o0J9 zl%D4LZ(m6wDD4dF3^f}cMz0fnNUgyeC2pY8s?Wt51T^7Iy%YCNPiJi3pyM>yddU3i zpPaG`eX`1@Dsi1HFPLw( zpnUXN?!w=FFTLyL2dgmsM^Pm^*oVXP8MD+iyri#w8A{*q2+hLi@M{l0C5zmZjHZg| z{u%$FNzmBm`KPPxGuz42Yml3lcm}_xSnUSj4l#R;HAFjENY)s&`3ZWf9PbOQc1#iR zog12S#3>y(THRW|Ej!Vzket|sg-$Wh-dYA2vTT%t4O_p@>)`>+cBG>M>%|kXu#Lmy z-Z*<8D*b!|jn(TXBnPI@;Obvl^dN_tBUwQVvlEF_Je_yHrVPN>rg%b8_-Us@TCn#z zIe8SC#i2FkKUwZ3nh{gKNq9Uv(;>zNatRc86r9(z(h8uT z^CINZ(wfE@HcDF1m{Zfj>fu!6+JZIK=65Bfy|ztszq;m3o`g=_AJP^qD?O|lS~{OJ zYeGQsjOLt|j$y=aXFale5fUbybu#qBz@f|=oO@42{C3k+Q+%1pf7>qNWUvgU_?DvO zGW_{y4|)0w0)b*@FPs0$776_~LQ+T$=U=WevutHoU-i1$P{Rd7{O6Rc7vYLX@eN@u<{_x#DYXFw#ImG$)v=>hlWti zrGhv^ab2(h>tpoFybDZ7o1;#)g)~P+EQMVXn&x{LA~k#j5=pwcQsZ=Y>S|*$Ajtgs z_|DfLEtw+Z^>>25%NaNsTK5R`|4bAYuCIPKJMKl6VZ*?%wUpmdpF%4AE(Tt$v?XAz|0gzct;Hrr!E<|4+a7f(uAlv`iCtF>5Ro zV+yp`@dsa}38QZzv3YVN6R))!7`Hp7_e-y`UaYLeZiT_6QK4jZMs{^bq)(+X*zYYK zehlWU(w|x8aRrCI_tv?oJ=fIW!?D)G*whGbfylq9?dBJ>lcsp2N!Yd-+~?6j=l9lh z>PUgE?+d&T3&Y`rx$XxQ)GA9X(vtSJpsG==r zwx}5KD1S3Hfwq7VkHflBgP+KouegcM2=?P|VIUpzZ9M+!zlQ{~wU;lB9f4B`H^W9* zVYA23XsF{a_-sXT&{2e)Fh``I2EvsmrVb&Mo!q?<7}2jLxS(L>%bzP|i8J}cG}Tt- z>f&iMH14vJ)>gljvghthU<_?w{J>FD@J4RaS-9?g-gWWedMm{boTpK{;y zletV?cjSn63l;fh7}H`3fuW9=g&N!N=fEllizp!3nodssl+K+z&VvzI6gT^kI@xi` zL$m0+f<1?6*+w?nl`nh~>xH^K6@)N1iyS5(%iq?A*;V zJK2)sR9HB|yA<~K)@^35q}|Y&%p6|$Y{Gw<5e1A%_l8-3#EQ*>*^5u$@l+lMSor=g z`n)ikpg!$-tsw(z!E^$DOhlNk+}vv{x{=j3DhYe6m0^LC}akP3wWy7iyJj=@6B;Z#x_FJ)~z6}nKlsEmoA`H!ucj+;XVOA9^BtcmTSUYH56)9+S@%gh{4JHRn2<0 z1zU5(X>J~L1;2$a-_&~DK}#IXm`Trl7=Lr7V|L}X-oWqU$T#CQs0~W4cWW?@F6U*s zkwy8qcxt0rY5gD*$NND=&aC2FM{&&5(AKR-Bi+1PixiC*>#e_7Kzm~ijhm8p;*bFA zxyi%l7K8_fRbtN;vC3PoYlQO5hjU0H`Yuxmn`T`thwcJ4dYIjqQ(DZL{)(w7{toRD zJUZheq${mnH80H$eyR&yjV(gJD$a5`JQNx*h+d2{Ou-woji89#B~_8H9u2G2ujFG6 zmVig)+-TOe+OmIkn|b9k$5{=IHu6b!Pyi*Xj4Be$UAZT%n+>LEOKFnD)BWs9;=?Yr zCt*C=X%FT+c>nvN#JFye>uz7t-Y!g~jvlqBxEV=y#-Va?cPRG7Mu}PVnGMU&1N;1^ zSrX#*Mh70t`JK5RVxG0n4D-lsc>~y#Z3(?BsW(VjF?QiOu6nj7M3hPQ+&2K3b7y&c zb?z93Mk@OSztrR8qtq4*mTms^M@f^?CT$hwXTA)a5dwjWD($DOuXd$5xA>mnWFSqI1eRrLnUP#+81k9~EMi9h@rtz@c+3@PPPcg@0(q6+MW zV8zx;1qtu0W5~qpAr;mDhk{Onm;hxFq#Pbf zVo`zzN}eHU-Ec`0cpG$t)Tg+zpmT}$ht!xP&Zyyq)y}RDS^(pz(C9mWittjl(s%y) zuDa>%(b$xz_^xgB*&CU~6H!lVN&c#Y2DKp|c+s^!iXox^KK)z`p5P{SLo}2e0pE&tN zBppz!0z`X%kphZ`W%CfgvV`5@vtbWrgx(1ff_gHluot`fD;#WDxzGPwN5BGmSw^z2WfL(+7 eum0V$m4oXB0RC&}zuW&k1NevkKlA^P4gMFh<1noN diff --git a/tests/streaming/data/fake_audio.wav b/tests/streaming/data/fake_audio.wav deleted file mode 100644 index 7104a18c4e2c021894240b328bbb8ca7ff3d2ea9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63564 zcmW(+1#}ci*R39xOgs}K?g>c<1PB&fg1b8`y12W$ySp#W;)}ZzJnk|X@0oV1zy9yc zffMO;Ke_k5S6#3A=5*@RfdODp+kqV?Oq(0&4FJHzxK^j;Eec&wUgucKHC&I>XEZhSx!b|WDq@f5O!WXbPI02S``rtOK559p6OojpQ z7AAx7ARZ{dPq-2OhpyD3yY~ZA0R|+y|#YIQRx{pieDqhkiF3tVYjJ zfO#+nPKAHNRq!g@3KL;C90qT}bzmVdqTgSK?cf~f0XR?xx`1EsCu|8kz!AtvFC`uL z0SZ7pFdl}2=HMp04wr!8*gUWZ9)yMP3}_5G!4J|FX+Hb`j$uv|y#{cFG!SkB)3Lc& zBA5#w!J{A;dk-dqbZ`N9ffTq1HUMfY9^8=bOABCMundUEsta%-cn$sr_hBsTfxa^! zUl^za(}4$e3VeX;;CSTme9#SqAlt6MMC9>Ca1AEFOn3lx0d2uC7>_)xkDfLLTMuw} z7Y+f7P-Mg4IhcU`jkN{c;7chJ?t-CkAOzqcXo775fp8D9Hv;Sc8DI#?=Kz%3EkFa# zLQk+3=s{bU0{g)_6!|g876^O8LvT7E!7HFe-gQUbU|ITHGV!5|w; z!rFre@GIN_Zi0cJ1Ne^YI0je1dI%r;K^AxdU%@^g3ABSdq^FVt+Q4<-2X;Y=^i7(K z?CXkry^ZYY06o!DCV}r@CYTL1@Gaa5J^~JUBfoEhDC_{r1|hA4i$Gh<0?H98r@^yO zj$(5Wt^)f&D^Q4{mkItu7Vm}2;7fQ9SU?rzrF7^(@%oMsA&04;CDsNz3ThGJ#zQmU zu{7*Biuq%B9JIjBfkS`=61amhyctDsFi>GS%mfTz1iXw;aS}yq3qoLX&X2*bDCdA5S);zw3^kIurg4oCsa*U>D@eHMkf3>kcZx9?%rA zt2erS1j2GQm<0=@AqcxeKo1ZKze|hZGN8vMgC;04Nx%!6g!y2P!EewAEQa?G)82#K zAOc>Ow!-lU)8ByvWhh74U^&zk~H$*7Hk03a1i_qZBPeRpsPKB9p!HYXpa30>X14-l5$YqcOx7=hdZTi z(p$J2;paEZf=5x5Lr|VyKqI&a{sJlBAJ_)QfMJN^9@r?jP-+5)gNxX2YzqiP3NsAg z;4?Un*j$XPy9htQ#$Y=PhVx-x_z|hlLWH*Outb7V7v!xDG(#-!gYG^YPJ%~Jyu6VW z3y^(J;0E{%jt2iCp4gEUTj6Nrp&Ue_r&J#c-auVr7AUJ@ynG1ixErGVq6Jaa39R2|-5L$o2X7D-m$LhcxI0MEbE)7Hs--SGF2@Zl)heT*Se~u)lOe z>J2_%@3A(Z5qd^7Qnw3;`!A#bkb{jty7Urh>0!_s+W{WKCCK7=NH5wUuH8jn$ASVB zcQfMIL6`y(5z~}l6N=<~@Dj+e4Txdqkm5#xc0hogkqtvpLiG4y$*CAa!jP&&(viA$ZaVYqOIJFCOfiAIHG=M8uFt!RBq--e^`XY}-$pv#T z8)y#aNxk4s5P)TX^HPRnk&b~g*ekFT?nAkF2Oc5y|AM?@AORub;C+K0CNDsgkYzHSLeIN3u&BkX9Iwu16!TE<|cD94HZg4#EIbIZdE5vZ)wdk%&C@ z$K3FnWRm<*tyqUF3WIKG1zdnwdk3lW0vG^9;De=r2}sdOVJFZ6oQF^0K=iy!r1RZT z=1ia-rUJ!M7*fU+SP+(skflQi*$0-xe90z#K`Ix6%?3via?;ROp@@GUkmkq$hHUx` zr=vRD6!io#@T1fjmcg|sGL;B>8&Ty02*vkMtzQn;quO9V8Gelrcpd5D3NRXkfihT* zv}6*z4FeHke?b66=^eU5b8HCkM&9m1)%OCbs$Zmc(rlzs`w-jbfml=@eNZ)giZYf8 zE`e0+H`3J22z}?_C8T(@z#lR41Y8JjB9BjjKZx08r1y8EB54ZJh9jUqXa!3pQlel3 ztQGY?1g%P3rK%(q&Ke- z{+}cL@IZC@86aSu)D`)x#&%;{5vx~9=zA33Cm1_%OOVI<1>FQk2*2&FebKC-+e`q^Xn2`RvI&;dS|zM-hBLJCt3XCiEO z1to}sj}h7g)bYe3lyj(V)xxGo#r_5~CAHwnbO%M`#&`I-NVP3aQX>q!Nk9pQ)%Pc?V~p zzt2UzmmS4!HR91#gol?%A?+wWhfuZaj@U)OLhuPGlLsUv67@qnK~L}p%1}M%3yQ!f zROcSSB7~43=<^cc`VuHa)y)?iN6I@9w8AC=J=7v^e`3?I=a7}AB7`SmSCO7|K^jyK zb%z>E4<4c?|34P3Pyx!3udfhdN1+}m8}%AB5J&ay4ARtaq_wwE*LoT~dk(_VBN&Kk z)?9=^JL-4JP)`wz?0$ey8HK8N8dwh>OKad4r1-tD2yg;tm)5~;odseUbR!3fmroJM+e z6(&iirL73Zdr%#}iqKGt`t4xY95MF^>Q<7mZrDROODdBVff3k3Fatd^9@Rw#q+mx- z4yA<0%eeoW@T)ZJu$k$*UK$@gS>jR|D zNOO+K?kgY`4Z=h(F&*Wx5vs&f#USj3>;RUIeHHa6P6g6&6emeSD-<{a12PxX0|H%N zAVtF#*l5`VYzbn+e26ubpbP*?dKY{vS@l4M=}hw@vf3+*lqKs~2FIE}fn=GYmu zTG|NLNgm=&aXoZ^^Ozo+g{o>6Qs1XQhINNVX|ogtte62CE$tOs!@J-ewiMed^_DuJ z_0b>91XoGpP^3G7)`(vg$$+{a8g;BYkuK|C9OA?&5P~&_22>^MuvmFN>;`0{erO$# z3acdztP*Ky8+d^*;sRY|Q)LrT2lE5wfnb?Y_6M7fu-OwNfZ13b))SkLszy18kR8JA zVmq0)dF!d_^5)2Ve?b*D@3=6x(G&7WGltN8Wrh7}2p;p`$s zPuT(0VSjU&BI#$Mx?Yg+jn^7|qCNnG(;W!~?n@r0Ub>pP4X)YFMNWe?)H=v{5`RD_ ziGwZ=Y9HO1Be@&&0ctv3!53k36fYIylrvRU)pljDEJiA2&yfaKO9$py?Ql9L;5(ch zo%5Y(_yxDaJ;POvcXOR2uh19R=A40iNt^&TLTlTf9I&_duC5C@p6=6R@SFDI8t{IF zRDIir(uzO+dD*$|e^*ovF1uWoS+=yg5C5NHx}vvgn=IMmdiY;)#>A)Ljl5cUZZh0b zuav3jv-lsE)!E;D-j(58>~7^=OH{dE*uFXD5I%H$ZWaBA_?tP;e5UfLVD}!v$Q>8< z037QtzpqKxOWK|4|780lEl;}>?5)i^Of${PEhDWN_F~&P`*x?y72%qSH^z%yC#c`- zasH_gPJbcNG`Hj0bx9dAxyQB6ZF;QgKWm`8b$rYw&qY*4ZHMB|xye5~^KKM9t=(FE zq-5w3`KaRSViomG$2omc;oYXB*F@o(KH zt*1=SYm4gYEOM*Dnrt0sKj7L#PA2n+QBn;#v=&> z>o-cqgByDtHH=W#$I^+81PvJKt8osZm& zDVF-1=!mS|$dceV)?%}O*C z38ufy%N%PcLU^jUCJ&GtJ~x; zNZVfV4rKCnlD7{v`Bf)Y->f-WN1M9Vb*&3?W|4l(FV0T?%Z%bXiL1nL_>VBiHNZ6_ zr1LyA}Va zEQ)HO9d!n$@w3DnGQ#~9KaUR~n~HNl7r8+>Q*G4u(SOqRR=ohp{0gG4wQ23O%0ZRc zRfDRh)GVs2wY+ua5KqWo%xCtQFh-J#?ZrgUUwqF&7KU!?OpIPX)zGJ12fyAaJ)+xn zjax*8l}^n~|9JYxluxct{qu6FG(-S%#Zf~%6TB1)3{{Hu%6#80k)^2x$+;me@3orO zDx<8Ab9}|&e7vAp)i(3L&ZYDr=^xb$?FaQt)dW?5YM(5OYvtT1K1m`D91j$ zj8>qPY&f=D@wZlM=;?J`SErBziOzK#s~K1}t)z3gZ`Bxtq}%4T78buiB~c6=LhYpA zaslEb$yd5SMe}>Tw=^F-eCpVzLs#UKbZ^){v}0=8VBN|ZpFI7SVV_=oljj=$Os|P? zv?A5yH`fjRv|^%KsT_qx>B{N_C3E#7Vy^`(@>=I%P|T+9*KE#D&OcRhx^|yqH~Ehk zr+A_Lt<6$3SAA4;luZ$3WLKAoh+nj?L-TcM%+iyDYgZH97W}ezv_V=Nn^iG zzCPelhc3N$b|2LWi+w`{6eND>_V)PK$3HjydQ&;nw$6Qme@8#%>Z{JGJ}DB=dyIL$ zx|k-(M-xYdtn#TdyjER-l>K^9Y~GFh`xVn|i||~g0p_Vr)2TGmRU1|5iuEvu`Rr;! zbfd;oB=rVA=ty*TAOrZv;u-0ke2He2A=!k(jM{S3B;D z^V^fpUq5>O>Yg{e`ltJfy`|ep?+}W0n-x7EE%!8NW6x$pr>%`!8BovTiLM1!>-tc3 z^@sTFQo-@+mbT_pE4V{7SbtJ~So@D^l~Rv+u}-2Ge~rH)-%&l>*YM`fkP_tvAHwt=cMn9a2!NXy3RWtC$py=%&9q}o-c&z1x3ukJ_WOgCZzvq~H)>o4yF zjC_%uQTk*S^yx5j*$A@J!M=-n<@P+@=7i5eXa1l4@93|AxhdbD75SHqbnIg$x;6Aa z++#_v3uw=2$Xb%vCM+;I&qD z8)Yv=lI#%o+-0+CoCAnH+&(6h+~kfTZXl%{Ev3PISWERqU4=GFeOu-sX_;h4=h~&^ zs&ZIvs9sd#sPQvBwSUIjyS3CV!pM|zqlID63#=EmbL-i0Q3raIPFOjc?4RAWb-yv) zZ+6It9pv0z81re*yFGb7zuSKQRhelz#Uu(#@G$x;YZWt8o8WWR2V?iRkVX$u4Pk?P zH)=-6BY98L$-IAZfBm>u(anx36;@w$)Fa5VMm0!zL6#*MgkslP`wyg|dxUPnTC#)t zyXzP;S~?`*(oN7y{Z4<=qgEH8><$;uhi#VX;0j&Y@$%#4QI&Y*k2>7i)-{9hbx)+X zQL}|kvQgLutW4No&%@HAJNLXl>B`V){rh!|>pgv7{nq-}#}F0;{qo6emwU2kYN21* zGy8GdHRoSW#xCch1yRb9r7FJ%XD4Mg7@pA~;-lAc4K0i&x0&w#ss0xH=VaLf8^^4K zjnvchL)(ydoL6awFN1zG{C@uThElFKe+v#>&w8#-Ihk z^Xm_9TAgl+qP+Vkrop+c%T+}F!|$&A*Hy@D)KyoZ zy9w6=CW@tAwJg>5CO|RO^ z=APCuco*F23?~f49&QzSXZ}MLEuJQDdB?~by*(!1A3JwwV9xQLEBn50F(B@>bfs{_ zkBgrl|NOVSRY_E(%N}a$<9upeZ|X!Y<{rT7N|kPC7@2-4D=I5B_M+De#dBt}v!ZI# zpOhc=e4;wf6)RTBs+5t+-B`6iGX}n+aFV@Ek0PE@^~7rFEO(xmYwzsrK~Lf~!Tz$7 zs=!t&iIg7QGGgho!BG2^MnqL_=e)=YU-Oc_g+CkUQK!X+Nai)w2ysHm8V%{ zU(cQbk3~+S3c8w{()?OxU<~i&2i4p{SDWe^Mbd9=vDR{xC=|}ij>x}bC439ArF$W{ zh1(-cV4BnY*aqTiSvk+TaNA^St~-K#Cg#ZRY0#?0d!(U<`USkpE+O_?=2dkpzf>Ws z{bhMz6)cxcS1taw#rAj3J&wl219lO%O1DbiPuEx0mw9H@sa|v@;!VSWaY@9n50w9cQri_bHMkS z%*H3tqs`&v&5QR{d~&$yNupAA1r8G*FlQaO{X71E`YJr-PH{3Z3gpY{i6!n@TdC!Q zt2HC>9p&DdP*1&g4}F|61-@Y45Z!I#tG`#?sG3$+ZFy-OZ|+~$vPLj%wNzW?;!WKG ztCa0l)z=j2Cu@|l65x{@)?Ybw)~v-j!P(n89d2ejYv$UX z)hsnVDL4NyRWHT8#hvOA+8!b2)9N?Fv!|yG3K*as$&Gfeag3-QQ+B$htNl6EQpo0R zFb1-%bBXn2-Au#P=^SZg_EW6SkZ@XjiuZpU=RB_F8-@Mkbmyq#im2C_g_3!lmN{RGe>cGT`VJD~d z8@IL3g0_h{Uph_5NDAJ;WL7Vz2q^7RJIeOVvjl><-F~Lj z>{g1Fu)Y)!s?o{_=7Rg6z1R{*RysSfQM?#Nw;tafw9mn(H zPqwM+CPK89$pC`tqAt$E*HEsVARo@(B8QSIX+JUozhG0^M%v5m!z`bx?v?Z@4z74q zThDHDrV?w}$JjMZKh19Ca%q|M8<0}l47#!S%fxTJTlXE^C96~0#{OPiV4*dnqN8Q4 zX}qn*m2bUZ+g0-E^}2Thf03r~d@`>=LG-Wxs%4`VSK|Ni8?3frMX(#&h*UCBl1X+8 zq_GzWm3@rqN0qzyRB5x?J5EoL6Rd1A?kaa!=uPi-UbIKJEPQjt4sBzD(_^`ZLGuV0 zxg2sY9mG|#>#3)%T}};t%DS+oeo6CuI{#RSrS7BS8vTUbDlV7bQG08;DHe$DnEk|l zqoGIlskKYLjhfhDXUB^zCuRN@xdf;Q56g_&+wMG~#NmsVR|Nh3@4fNy+>hqchR*fE zYRv9^C;n`s6-^E&{P6Fi&6Yor_f>wx&R~J6O^SxHdi>w^MRiZB|E>65o>!(dDT&tN zFmWGs)!EEB*VWQh;*7^%Qp16tHrA`T_i965U8N#Y%4Yf!jp>*CS)noamb5rS?2}F3 z%Cm|u7py3XDsN_8=c;6eqqiyH7*sBo|BW3MQrHr9i*G{rF;jai`taAW*5g`FZnZXT zU0kYXCuujYaSx>a@DRUhUs^7H?(i!3LG8<)#c8&0Y>tfa7#|(bV1C+|xJ^d0{)s+a zcT3;FW2o*wPfT|byU27kZ>t_#dB3!xbbpzlrXOx&kJ2^HJo6i~5pP3GBQxnV@EfDIn(H%sLw9FxuCH@TbGa|%0t zAMteQ_2FA>m}XoZ?D8p8YN<%miK^tv zvP#eDJr)1d(Dq~Gemco-MD?D6V2Kubqk>kPXvFc5*^k-HBWaLJVMb6+P?E3KKR>ujiYK7t!)=Efsp_R9}xK3%CU=1?wGG8>6);6dsGJP>8J9gk&YAm^u zXv$c`C+JP?EAqM5xmIzbTFnU@5Y=o}!?|SnQG>s)&2xb7&EUd_xk(F>v*MS;j4_VU92G7(DaQg= zccPqn=IB%Ry*9JFL-D{o^Y7l}|5_fqJ91mZezJ1)YAsZ;*gcpf7c`wcmg&E#XQ^gk zyZHy?8`}u8yl$68Z}YS^uf1K}uDX8R*E&m`-1f(Q-gU(tK(1geaXW+x&ggV_4QpuX z*KcCG&c>|onJY7TwH}iFpwZ<9tD|azx&(Ytbz|!}T9uakE`I*_ZsM!PKU-BxCa=np zs(R)R_zEyYYw>*Rx7ZjNek*!k7SVf}s{9Mg)m9OF&e99eguXnC@{IYpC588WL zE9-a@WjbdaXr*lj9V$HE)!Eg_ox$8@UeF(GXPw0Xe>KeqAws&PXE?fIp0&Dx!J~d@q#@RT>OPe?T zz%|AFhx|$_*caj^>LGE6Tcms2tVPd*eGYZJow6ifu1zOS^& zOnu9a>S4cje@T3^?|o{);qvztbE*jE*@Vz&lsbF=Y=eZkVT}&6h!eM z?*nyyRWu>*M8R^_geqIyqP`A%RrbO7 zy{_nW`Ie$ph3!k~%9}a{b6Frp)7tBA|0zKSg1UsYjAVv1Nnw zN-vu);M0Uhiv7AeZ(rXyqY!>7rYz=MSYCw^^Q>)rMJ{=e55tG*2|=* zt*BU1zPjX9xu$N7EzI5DZFcphe+h|-R+??9sVZ9Kp`51B${L{k#%WT4_?vq|%P0cx z={)IJZQW)~vgbG}T;b03_7rQWd5A67{=oJWe{21q7?hCKLe=eLlYgRmMt6-{nI4us zwZ+?}gBvLm)1vAHiOP|13gxs!RVCzQ<&Q4$Ejd)YGOvB^f8SpI`nz@RbqG!-TN)QNa;@ArHOZtE#X_e!EL$+gRJjG_&q^<(dk6d1Zy$ z)W|Z)8e^B7ZrTU_C2yj*Eq|=EYw|R`H1(A?W$!ULye^RJGdhRNarbb{wJtI1tXCW- zT}N=rzTEuEtg)xLKDwv6O6!VEos`!@y|YHPYMAsswjg#%+?hsIjSZQ(O_dEy$)DqQ z2Fg6&YtITK6;yfp*UrNCC3h-*RbI*S_;upXuDrU+#&*fILOdZKt&;2P+Ap4-K~Z5L zVM!sUjLm{pg@%WZ3FZ8z8|G<}WIcpR^d>saN}29fO|P0zQBrfy8f*=*d0Qr#C*a5F zNO75Lpkk3W!Aol}Y9)Ciw3};^vV<#K2WA=hjqt)R*+@&3WwayMZE^L%Z`hkUVqGrR zA6FXQ&2p?-j~^C;BSvR_$oQ6C5j`j@H2!e>kJOdTjZOb}9S{ds^D{z?c0qk!$1XC+oDSs+s z)K`_!a+Qpc7Dyk3boLYVlbBDmqP9~0gv{-5Zoxm}Bb?oBR$B+#5ywy5iFS8Z+XmG5 zv!OwG_0wCoN}C@3BWhTTfAWLILmK2|9LxxhZxS66`om+SzFPU3dx`%nd0Ei4Ybh%nTdghJEYn(u0sqOmD>thKsc>bQ>Wp%v(kNdiHRUE! z4XFT1pt_MQh`p|Ru5-?-cC{tkdegSoQ6GQjTH_L2eoj5r&-f#GZnmPCIhKnu#%Css zY_zHIf`&UAElc!^h!1Y3w_shsA=1OyymaNS>-h^y@QNOl#f9(lR~B3;oLR%$F#;D; zWS^88gUv85AT+!z{8jjq&@TbDz?;D_p%cQLL8R|9j}p+DIpgH4h0e{+W%WXVw?7=3Y@aNf>PDEe&9tS3ZHaAV-5c9|m!S1dUefqevpH$$QOn~NrhG}h);KG(Yx=Xa zf|#Gdq%jQD<;U1pXK+oQ!shw=Djrn#sZ>?&D%@Cbv1D>tx_O^_B{Nx;gx(!L*5CCS z99SE+Ff1^%W$@G>UFf0Eh>+4i(UV3M@d>aINV*R4j9X{N+CG9O9^TEOw;YI@=yt z+t{j5-`vR2%WkP%VL2&J4IbI>L}o?&_=G13kK<1@h)qA1{#VnubY)6lJRi`}%is|! z`%4&LYLef(;AYX{%BD48WwT4W7fS{46^5E&mXSm;!+~w;8Jf}FoAJ{%SCoro(f?|?xg5jG_TFB^nP3j3D;{qD{k$y=5hk{xM zI(*M~&Q|$~vGhZ?-Tlnf-nt8Qu+3_=n1|VJTK8E~tvwwR$OlY){)Ti6JEt%xU!eJ< z9ngS%kojTj#h%Q|Za46 z{lt03{>U0^2{83E9W&Rn^>ex%YwdDJzVj#1i*a#J;3RpZDoC|a{t+99=6JHvo9DM| z0N0Uw$KPRTBFQOO2V3XbvTcKGfez9>$NAeyJDNF;+eTad75DjHO9m}wH7ZIgYVaZ{ zJ_S#19_N?(Gi68ot(b{{SstylufSNgqt(BN&Kpp~RhUenrkI-enqk$QOb&Cbt+V?b z59BSiPxOU`Q~s9VFQLyviu_X1UiCV|QE$7?cdreeXSM%fpScuwh;yOivvs*eFol~Q zSY9}^M1K;;yEr#EE8WeQ0KP5ksMx5UsYz6}l&uBPXu>N%;Fv{}f;vnuVRuk2*Kd2K zeW^X$-of_57UW><-yPfWfq1FY)1K&5=^91e$=uSyH~nkB#DLmSAf>QjfAaZ~Jce~c=&n!@XZSP z85ADeEAXOEu;&z=q&ci3H2K=gx)2o)cTjtsFLBz*JN)fA<{_3twq&OoO*+IA8_7`W zDt&>8;^N_ag<5S?TTq4kB3|Mlw~h6pQ|K6GExm)fjQ_TkSjX6a|R=sMx(Z+l=D?5!Njk&Ye5Kf4|fGI|%)2F={=Wi3zdln&!x#5If`5SbU18KDc!2>Rg@p~0~h+&2ea**xF!+fn3GGuqzX?MrA0 zi@P5gKzC!}c?=6yebmh`qx6=EkdK{XK4#O_0ermI|<(dJCJ0i;fqJ_&B zFSI?fp0ZA|v#v*!CwGyXMb99OL=1V5UdA3nYv0ML7wTEcRkA3_$PGmM18s0Mo{7te z*JK!Vg1ClDjyn4|jG;k{9L7G9)YT02&>&wG~Fr(|@E+n(f_LS&J8XUTwU&#i%Ar(l4e@Ncr{HB_L$=u@s%3Obl^;41F1xa5EGz5zFl3ZKkhx&e`NsfyWFr9?Iezu zWM_KEOVLpQ20b4i90qN|SDw*HfPpKAzs~^hXr;;W%-W)DP_#u9M{`DrAG;V?K&& z!N$|)-DB_sJjP`qT`bPuLTtFj#&P9rOKvNFO7KOKkI$t((iUMVTSk3$-*a;I3)TU) zopz`Fle4+AyEEGP);`Huj=y&eb3Y^6b1C8#5F=Z!QH0$~dD0}K`RfLS>334wB;HNh z8U0^~Z{RPV20r(_Zfl<@hJaee-_fS3e)0LD`sF@#znvwdj9tvvfMVrJRh05S>@IkL z4Uikvoc6W8%CN)GM6Xf}25+P!*b`2WmWVOpbg{d*RXif*@VDsW#NVhs@3y~nWRqI% zz2Fi*3CDy$(Nh@Bw`beY96g);mv1Ew5q`2YA2)z66ciP|3O<^RMt+*jfKw?}u) zBEL)SV}(!V3<`SqC7Y`F z<+(FFGr4Uhp7}N7S4Qvp*Aq9zCWTJ&-{6_-aZhj8JXTOxPq2}{;XY}3QcYI5YO2jw z93k!@l$;-rEmK|BEJL#%J(d5+$I1H2Y*?hMv%FG%S+)pP2t5$?hKP508MldT&4u%I z!r!8cD`Fbbd&wEZYFCNtEcJvvEa)Xqajl>gF7dg1A=`$oq;T57X7TGdCA)@Rg|s?= z*yVgqQqeYhxf~K;ksEhn|hXp0Bu0J(3D}7h0cj|%q z!xJ_{>@d#rsX_CDAJso)V=*mM@-t9vQrd&92^OWby)DB&#yOFk&nrQ-%tKMC=%w^j z{!lzo$Q5hklq^QJADy7mfq$?7c?*g4{)xDnGEBq^61aq+)*jj8UI;Hjqn6TaQtMW-Q57`{q z9(jW|(e-X}5U7t?~> z!)9>D_@BZN;R*Mij;3Z&ar9*RCYm0(LD#V3g@@uf@tdF$e1&-eDMSh#g%@zVYLi!Y zBMcr8Ruj=H=3$&RZd!Ck*qoph#^Qio{%-Fj9+A3p+9uld>OP47v&1Oj3%`vkqiS7! z@wq5MJV}wwsK)dGM#IhHF0p`hF!$I9J_hZ77o$&a@vf8zCSu2BgXHJrcVz>BQc4!C zb44t}tYxk;OBfeZ!T!xn<;Jj(-c2v17t?2H6TP14igsya+${DW1L+>jG_;Eq!xLyG zHbP27Gv7VXx_Op#Mr>WJJ4;$ftO3&H#v)}LudN7KcWlQL67 zC@uYlzE01jFQI7qqn>J(AeZimgfLAQDtL+G#BQRuxKdazoEJt2e!^ltmm9%dXGgO0 z**olb&dGJ=$MGC@lAFfW=UQ_c&`#W7zJ<_0Opy9YSyCJ6A5lQ_%5Qil|CQgxXYd$T z#W-j+vw*$BofiV3h#gmA+ASVuyr%kO`0n+2=57Yej`IVAPp7c@1%q2)ausCI$rdqe&Q0C?Kj_}#xeah>Xm%-<*Z-D<~|B?QC z{D1g=@n7nH!taHz*7u|L8PBi!&zjXLtuhW_O$$$nX<{?+j_{i==9+PbIE){{pXa@W zbHW!PN0`X>;u^DknJ4rtTBHtA{isaJN=A}Rh!yVRu5b8E{4qY$72)3M4kmsQ`^dS} zI@+II#f1vT#9ip@LPvBqrUq)jCv>(-33H_W;#gr5KZ%o=OY{gThkS$Hd*320R1!0i zn3y`5#+Y7o zL#hpVmIx#Ex;MK9;}e{|&Rfo-_ySi8_aFB%Vm3LA8bdc=FxJez;9~g%#D|UiH6cI> zL}zZC(m?5&ND8xr6Z{i|=;IB&&7%r=mzf&|*Jy);SjM6+&KUKRm$925E+9Sa;+PmC$ zW`M)EAn;~jn;>UUWzfmMeF4|~cKTXSVOj<_EXKNOJqD*LhK+I^cH^;njk-n7vZ~H^W6T#0RkuNLM5Fynh?!b^*T+6ZmWKv$9|9FhI-yh{puN?83!BVjQ<%| z2GT~W|5)FX-g56(UXMM`didyy)st0ClzZh@F$vb8liqhEtyCkN=f7~F9M9~f!zdkj znz%>g5pRhZL?V$ugb?r1u0$!W#m_iDIA`OlTo2thh?Qh1`GNdIc0}{3$?P6(5ATo8 zmTVO;Cfj$3?Q6nFr_$Kx^`gd!1_?p6eWp zrXlV)AL7puYg)L=T~l47T*2-I#7~l^9Q1z1%IH~<(Xf5lrR+KO7W)yM`q;<)#U}_W zgkHiUK8WATjpU|tE4XeP!~S4RtOpm%4dw20^LU+bL1-xIBo@w--BCPO{-v}i7AXH! zjZ(W*p(;!jrM78ebyIZvbQATf44b`{d%yM;yn|4sjSh$ph(r3&+mG{0_Yd=n^#NX6 z4Tn5N>#t}ZsB@JK6encc&^oaXpTWMQNoqJnlTXNlWHAZJD`XA9yT`icxy|luVi-ZV zo4NO*S?%>MZ}(z%g?m0>M4W3yJ)>IFr)WE^VhFmNuE%_3O4w@dFs~6BqH{byQLk}P zJc0UwXTp4;l|b+p__h2q{ssS*f5gAyHzOU%0V%RKvWK#E@`s8Qs!a7>)kCF4d0zcm zE9u(lC+eSh4D|xObNx2>ZSgzizs*<}m>4Jv$o0j2{7|)>=Cj=EykUulMenVT)S6X+ z$_w)4vKt^;dd+v_{$oe63z&F1ol;T#sU_5B@*{x}4tFNOxo5ezyI$kd@fi?Lk%f^dN`d)2cT88m0rL|%vE*)7r`Ik1BGisXYrlrA#vhj@r3~S z1-v(3z-^0_-b0DX)<8@{fwKst4*i^)B^R^)qyWsjbIij|m>*46nQ% z`kwIr=s({7v44v3L}1Ur#sT|$Lwr7afAn^FC3)`fc%na`m+2><>AX%#jlv=8gsI_U z!JBW)y+JD-86&5UQU|C>sFD^DgNV_@4Z=*^Ax!RQ_aN669K#EpQ}B_lk?zLCCSn<} z1!=_`G5~ejhp7^3Bpr!51|4VP=A%Bt%7+Lm1t_c+NfC<2M5Q=Rc+0oradg&V9Lkor z&|64C^T9{3MvBAA=gPOrjj9s$J6>}9_1x)A`V9A-;@iy6 z;@{TT-uTVG*tb8b#eUw+yv`cl>F4S$YpXTK)xVTZc|VyRI|~03asB`o!gc0)b8gni zDwsv|Ksu2=h|qYRtRQDlFQ~QDRdPSE&uw?jcE!0kJjr#~Wpqz;Z*xC#hoBBzNhXmw zRG*a?|8ADG)Qi$WGWTZY-O;rLOv{Ih_%Ikg^yS% zS|mh994*d~>M9Au6>=lBhc2%1Y8&V`=zHtO=r0+DnXZ{@So&BxTPxX4h};C%3ur1tx>&xy7#e|jzjlorcFivik_}+Q{@J{j`^X7Pq_*(mx_^kei{uhCQ zppJELbeIjl(aymcrIiR zJxUWf(b3Lc(mvPT%ii9$+hQ=Mm>wH{83yR*XrCjp>qn7fvYIIG$9iS+DSXv%9M^_j zkDh?B!I^={{wKbjzV*HpzC_V7f~R+rE{(w@|g z&>hpaHhk9?)<4xf)6X$xnpT-Vn?sg=Z7bl%_Kiq))QA`nxh-mU)U?Pl;$#lTj#IRELuciU>fa*kUR}ahI#hF;6pJ6YT%jSoE3)KvDfPeQ_Pz?;i zN&X8&b-(*`UeSHUExQMM)_Qh$ay{$4`+cYV)8W6ifd95VG=w#CC%8!%S2v-C_*hJq zCQEKEXShL%P&2j~at zFX+!0RvX_Ke;AjU5-nwI%iz-vatw%|qGm`=BYn-!`PsvR5>s2=DZm=~xVXyb3^ zJLFyNWxZ*>`o5;VO}@qcZGn}+s-cD0eQnr}Y=4dj{|qa9A(4`1NT(%U+9D58qT$J2 zS3~Iku7a-kChBq}T3IVc$^$UIuF@+xmZ(Kdr?t!}=AovuZm7P!{-SP&t~W+F!uSEU z>Z17%YfpPEM@2_dhu_gMa(YyqsIL*S-Dx{#+i#<7y(}$Fn+#X4 zrxMAVYO-=cS|t7@+~;3}{agyC;r#4Xwmv&Lv?7=hSP&>2Sc>|#N#1{PdN#>3-_yr4 z!1K{_)$8|_2$T;}q5Glvtcg3vjSZ*35Ap~LMZefaIw!@+>*bsBefSzH5k)4*I{7*x z=EG99^in#C2)?QuP+F5a=u{1(eW0zTe{FbXykxv>h&8k|R5AvPX{M>Bc=J(97u#&u z;D`2Uj;j$xqK-#JM;Rk65sw_(9D;qLZKh?LX^QcaA<0lqe^i^O@zE3=N!=hSt4HLi z(l~LLkjCr7My?|p3{44T1X~0P0uKXs1J45O0;~LYd<}gOKGu62eT5^u3%xGyOka%u zrhjrEE$D%UzZR;=K4wR95#a^!Ij-`Hgn7_|U!)|tk33l(C6|@AOR12-`qEO2Xqj|P zx+T9<2UC|BJI*y5>ALH$8TuKcj3W%BVHier(U@oKVVY*HjtJzLy|&}9<8nl|s6)}u zqJKtBiJTgd=UD8RWj|`&ZvJKbVED~&L_bGYMthOjM?auK(}{T`%3!T`DI@rUnTD)&ks*IZ&Pnk?@v#(cb9jxuY~`Ce`26>uuG@` zTLOCUd3YvYSvU@_b*%VJY=SuRF8YW+Nl&DIr8Ck7X|?nKe&TrfnCz0*DxcMo)Ga1j zw^rZP5P&BU53Bpolxdu0JY`HZ9XCC}N)@xLwu-h7_Eg7y$A*Ydq$esj>T2Ywh_jBa zj_>xXwp`0`Q#oS|!!bRld!p^Dc};JiW{`D=7fQ0cOe`X>@OfUaBSWQvRRYKSzxlQP z!@lXhdpK$N?!V(N?H}QDdBfgDs1bO8)mr7P;8T4o{dxWtfnXp%s9_220XHzL;n(v9 zcz-LQ13QS1#CU0e^iXOeKZnQr5Z&9~)ycp($prRN1xmw|)E>~K>bvXz($6;xH7+q; zG91v?)SuArHWW6tHD()gOyez?)?KzwwlelO$L5Irky|6LM}!~(n-c&dB0xKFu?x~jM$-7P$=yfMBjzNP+ofwjRsp@nQa#D3BIV}7`x3iHJ{X)pS@ zPs@drKb1F17NUcXz^vJ%v{Q=1qt8?QWEp0KrkU2I{a0r*6g3tz&NDpLi~5g-bH=Ks z-X^2DpT%LDWlw{y6C5=oFGL-WUKHIsYHFl6;z2}@2%kOEdeU6l)XBKV@DiSd8PQb+ ztx~VZ*2GFBS`LV2v5X*vFLUSFqHK0(M(81I?~K68z@fl!Xo_+^jdzeI*7Ly4xMN&v z3eFVFbhUIBxTkueydkg0=k#9+tP2ha^=F52ox@ScVxAO6iPf=2{bf#Gsr&#YL3JSG z?1Mf`1Nw&^xEB?f_SzG=zWNr1<;D-Df#z(J-ZaYiw{g5F+w{P6&9ulYTK3w`*!7Nn z(CER)+1O9^=#0pgk;#$%hzE{ywyBo0rai`hA=+?AS4-<-1UjC!P@9057AOBL?n1t$ ze%Q(th4qaK?F@zjEd%NPkA9c`w7;ak7*4ASdFHvz?jEjv1+@wq6OU z9_oFDv&P#dvqfulT7H^;nMRsEBS!3FZeSi~o^H|DX4tDc`a51Z)QDx!5!0f(Mnyyp zji?*(&9TAW)0$x_Zj3gh=yke|n!|Jo)qoriRGTYuSR5qO;+usNx!UZsPdzZq8@1+M<}6c^>6tOn#G59WFPL5C{+9XH z9ncFE?PmK?d!FM*M4`yUi1Lm#_Ez=^_7S!x7PI-8ku+X6bTJIpm(g9xG|$%nJJ7;YGw8=4c! z4OR`V2=orL3B(0@`b+uT9;@e}d%L@sd%WvMK~}*o*K&6Q&rwghrcFUcPpxDn_O z^ame@4zW|YnDC}>W4@4ZOXw+n7Dr=0{gC%6Yk{S6j~cG2q90?ln@d@&)*n`z?GNh) z%SH1v^HFoQ*>5&kK3R0O3U-gZvZI~jwZj$RjjR=QBl19m+p)!Aa{RQ#SxcGM8UHk> z`tkbVx<=Y^n(9mo#7|M=HehaCm#&G=aK4fo{)cIH8nPUFdj2*gD;eaZmej~QrdrCx`$jVXeqO4JuB4}%uc-9sg9^4l==x^yu^^W(H^4xI0bk!{QGyg?iG3Q*@PmjS@-}@Wn zY_NZK!0nsu>E`O|y6hS4d+JN|iC)RqHK@WXAH*(UBl$AYQTdUQrS7I8buUc$)--!b z$BT%g(TRl`6uw_*ORO`7j(rjPEVe;RLR8g=pZ0h5Irf>h#ny+Giq;fcZF>WIUt3k{ z4ohoGqPekgs?N$ZCm+M_-6JjFhq2d#uY(l(hNZZf$PRbop7Hm@9pVxJRUcd|=LlB{ zQ{1soey~UAANDiXkh>b%7>vX!(E-~3(JOfBduUHjkJDY*-M}>&wFo z_Pp{=^v}WWxfmi5HND{%i@g*poo;CD_*&>giA&`NRJ&5sRBvd*iH)KfmP#v@+9r8P z)um+Lfn4RLuKwLq$EaOl6x8`3ff2;jt*{@(`_q?aBkN){w4RMR2rG{zF=_S;K zj5MQv+4kAq)=}NQz`Ddd&eYo&(j_uI)onsFHz{cKH}jM%c#tl(fWo~*-cFx({fAaLsVFg#*vHpXh&b&?f zDjy&!Yd=|=7j9KrU-4#@Ce??frZ#%stWC4+4W86`m^dlkRjz5=1AAL46nf)Qa}8Oa zeoXp2^uwPY|NT}s^H$z_)FcO4zkHjSVt8U&Y<_ELW^WwPE5dA7&8em{#xI7lIwKV! z&EXydlLLy^?y}@{&N-YLc2@N?^lkE=2o4L+l#h^$=s|P`DwC{8og){k{lpx0Zy?pT z+*8MOK7U5;z3k)J-kiw%dIi6`wz{`@_Xk2ae=R4i12Rw|!7zEI?a^wSz3hkzhvMlP zhB~|Ix2b=sR?CEx3P(#$FKUjOq*nyNJujzj*2~N;8O*O9KU-&%&%f(GB%~09n5VjJ z<^v8-RMlu(Nfx+%8`GfKrwT_qJpN(1tP-dSG*^{> zc=qRP&$y7j|5y7T6@J*!``6RoS?oY<*OfBew=vOO3n_)B#q5tT+HIBu!+55b@;iSr z)ZPEUGqB)wZm*mUIVbXZ7W8%9ap!vzLhVI@XhQF0hH9Q_=j(YxXG2@<5mJ;KLO!=L zwB1J(MCLxtdY)B2r(W)wyu0}`3$i?(K#&^*%Qr^Ui1l&j9r&`MLmi<#X`L7uQ@BOR zN|l}`cdvIQtzq4r$tl&MD|ackG;W}yA2}m1*?A`?HQSQ8`Df<$SHC9Z68>#s6m>_N zXDnh{9MvwCj{O`p)4szzPS2nsHZOcTknSDgs_Oia`y(qOYg|s1{97){bJ-ggoD*K8 zq|q-m$8}qE={l{UoT06L1ye@#3TL_Np~OI0Pjtb_yvcdz@@)ls-QT>T|7GYocNeE0 z59AElClS(i;Q&q_3uJ?Kuz5>FbZqrv%_`hTG}m5UcW$kg)#p|@RsL1!qeXLU<;Yio z!p@#Kd$K(l(|&#a*+2bc-a~&Eu`7L4d&7`qbwnJBt`gnUL0OjSmQ!}c6W$dZTpTK8Q$}Kq#Vr*cR6mgV zFtu-OcT(9ZgDSQyomKd$xvo;(U)hTkPSuDM6`pfLKuDM)sqKl@aF~VYV1fqIJ z(GfE(LET)YlDdL-1si&j3U20)%hTuA$=i(j#RINI{!%zIs}F3My=ou2k*1U8GnEM> z+s=p+?hF0dNj|f?i@UFTFR*|{7d&*CP!l|luO;1=bLC<{2J}-wYOFe2+{=~@CUd=| zb@X(@0dsQ1}g)X~YCs_v}Zp?v$eRSqlJBj9(&nKsnp^chD?jsW@ zf)dGx|p?wWNn^GMdKyjp>Z@+IwPi_7*n!WdmB#v5JCQOz`5Q%jvC90+~)u5$gz z=knzI4bCIZea?ji1H9uy7s6wN&O*ANNN<6U7OxHxkF#x2|6Rhn$vw)c&AFNxk@Z(j zTjzb3-?Pk5vjapkkxAdttke*i19W`~2x>w`XjCAQ+bK6>+L`v-;$w%F-cWUQ>h=a7 z>ldk8B3Y;wA1}cEB%2nC?>zPLvvXc$vsvdeeOcw4@Jf_y-BZgDM|9-rs2(vVqAU)@ z^hI--s4Lpp^ZwnQ((VLzma77)xE~ixcHi_J4XqBZ2y1{{v`SbFq>u;ldchyM;=khS z?Hk}_3vT4r%^sRvB+u*2K~KRb21{jxX4^?Tlc>`B?rb9?7cC}`?>@2=q2v!XBq)j6Ah{-vVbyTv?n zo}A;%3THOWUQ=+MT}|#ZzPB}vm>U&{@fVT{t&2Wjn{RkR?^TyeW%=1`bg;2M*Vos# z5@-;9?;8JXM7VuI$3k1#1z{b|1E!$bD;PS7bAza0bN>dHHSgc-_t|%H)AFC^k8no2 z9(hNE`U}0}a=@oMBsY~4q~77_sDLTTzLW0JA9NkeQzD)gy-{&-D>kLjAkkqx> zxcGS$mKHy0BZxbJ*9FV-3vyd#SIf-K*qp<8-Uzicr7TSy|3*HI8Cm#Hk;KAFqf%_F zVG2`?ST3#Rzj3ER7XxSg*@yyLdLw;H0>^QN_;+A);C$#y_>nL{e8gM1o}p|1WtfAj zd|W}PyxbgfUZk^8!AIboz3|urYq??2Z}pV^(mg@T?_*a6^8yReA#bI2XnUJ<5ze9? zE4)oQRBLDLnl-;Cey&);T#?R-dAGCYWHOn5q(+GacIMEnymDPp!G#x~P5UgxFy zsj>1Hcq~?)4$tSVu?s>Ska_wRyca6Z?haiJCgUW$aA-AKh}*%k!KHyCIBBgL+#Kld zUyknVfG;NSB{-0s%QeKQYByoC*c5pzNBCaoX<(B7RN!_vk>~?^VUMU)D7Pe4`At%C zO4piO5?@tnUM8pbZ$&;t{H2>GEcQ&!^W@aZGdXjd`wM=#y9DE8D>PtZ`x*Nm_I~yR zoCs5|Ykxf1L* zzs6g|6YqK9`Q&-wt_Yi~0Mo`2;!u%)i!UrRL>25a>8H4cU%)O2S_01CMd3Kv-N0Ji z5p?0=B`a1Okg&6QIH^n3ymF;W3@_3v=9PWFP8I#W%g)mI`Ody>-t*o2hrbTjQSGna zXzLoOjam`;A>ydxsBNaXoW3T#NvR-qM}68p_CTmRDx>~Eu5x~GP^dOH7)GRe?!M*u;2GqJ!MVT^pE-0UyhH2{WVVjtaFM{dMFxL?ofAm( zc5)Z?O{vp7;Km>;bVXbJik9v9Z--zeG)pC~6;Ld2g_4x~nQbh0P953Em4-!fAT1pczr( z_qZoB`0Yii!z?26eP@;ZCB2t%~x9oizrOMj^3PnwuIHLX#-+BMHq%8Z*A z)xwgmU7{ohUHLaM-5HU&gWS7=34ENSsz$BR5)a+5JNjtETx%_(Pg{dYC4b0ufV)?~ z4(1+(`w5bGMBbsiP);gym1D@MEmLMAN*NvA1V86EDmmJDce$43pUyp++drRlUGv=Y ztqq(GnfMWM6JQLEq*?N?+C<(XR6%c}#-HH+ls_Q%dyXx?nrBgX8tu2tiY-)PU3n&< zbIQTG8TIbes#k4$=@qd{ZK;Mlay{R~n~*y;Gn5&XKi)T;+b9lH&X8?%rz{gAmPXZ% zd|}&bGU$@%cIXZlg>~Uq>}+JAfqNpxC!BF+4lGJB+hBAx1th-w9ua|3qjz zzfCR=RQ*EaIN;98_MzrJ_@RQgE&cbp^MQosA}YQB~Bd5F7{XT1fA~O zk=c8*He@fz{py_P9UM9%PNJ7s3`M?`+gB~8#`~HxQZ}bNNj{mlq+-ir1FcQSx7--N z;NIn|nfoB?Y8IVW%yW{hr(B?y==K@oEpKd>?6qxE&76L%MkGCQNg==v3D!Wh;fLT> zppt&(-iLn*+vTdnck(Xfqv}yL$ur=_xK3PBhs*y0CoP9{hK7gch8~6(R8vs!Kn6%> z<)MlQ1nnm3aqOCn+$m_j9j+|rq5QPGe{!1V49IQc9O@YwFmNj0Lu#h3Wm;KatjZRx zHmSz&nu#@MB)6>bD{)(Vi&9CE$;?(R-Lu0<H8}f!`%!I7uHKN)!Wny&10QWAEzs%y`Z_E z@iQV-ks#&Id;{*E(0GiYN9bZGf*ZmYlNKri2qTqEeL^I)i0A+`tjnR@-X#S~@=|~} z`Y2P*B(wYFE-eW9j&K8|kjhe>G(WWl-78Hmrhs0gZDom#eOPi!g>jW{Ri@$>#IKE? zQ0aB)5wXn;pT+I|$H-l^$QzYYE}PA+pFh!iEKHDYT^UOyN7JZabZoRH;)$iXVKcKq zy(F||xA>2EHoIfI%>rXt2T&w#^OwZI$`F!Z&Y@yvKC^+A>7tqinvTrBBoI@?t>KTX znLUJRzu#~k5N40@)upaLxNl7UO-?5_5tQ0p>J$DIuz8bR2lJ=rirELV+vS|ht>Sce z9tEm~onmWsGF3$LKs#8sMmJQqSC?rRYU@#GXzBBnS0_k`^AZcH9jUUU(yKC6ihMTr zRrdRLJ16B<$?2PY_dleHoNvyr{#xQrDn`$kE7&eN_C+jrJg`1BvYJiAVR19pBlw%o z>iHA>b41{1XcqT2{E`1lI3kvpBf-!UAhN-c;GnA05zItp3}a{9)GV?V@l%BC{}R>zgYUoruf>wh*yLXR`EkoJ5UZiO9#c2gX87nhf7CSkt%K?Jsb- zn)|MXP6!(HEIE~GN3BI>J5KYH(bHRq=}KdHl6(Zx)sW=CL$ZPxLQbO^(ckG|%z9=o zqtUF@q-#cK<}hdIU(_* z>X<2YmAp^9%lAO9-zD}dB-w#ljJu&_>{sq*xH`X|Un(qc^5o(&Z4I2@+^}g21jp*X%O=((r8Q9 z_oNb}GMo??jWebOz9-%%=w;~?HUh(^6?urV(~Ie;%t7?G-_dMl?$BH5Y4jHQ2K@&e zqI9UR;K1>b35JBTL~-&qP|X>72Ys6UOw}OYEAPaX;nd(F?-^Ho!6heA(7;vTj`9@* zMstHiMjb~UrM^;0R4kdTeo?;3yQS{%S>J_Mb3NJZs4T3)mg3rm)A+G`CH{Wc!jBbR zi;tw`@+_qpSy{K+?utvPa;nzy`imQMuh$`EM%7tm+7_~#MoL#*fB%a4lKZj9=j89_ zGG^s_d_(zoGD^SBOxix%j@tUz8d+iuTIM%p1#f2up?>cqdzGt;s^w<_EVyz+6~T3~ zPg#%7m!9%f`Ih_+&qjbTWCNKBbo!n^v!5f+l6`UmrJte&-hDPXj{eS&+Eu_Ut)SUY zS0jJPj8Kft_TPjRc;vb7?dsndJjSgO@2H3A)!L%^X?mZ|rhBL<%cN1o2}Vhkz6me* zJz)noIHU<40pfBB?&(+fHUE!rSG*!^kPXTgbSgA}-}yt#5)-6vayGTi94!30VnoX4 z`gsle*V|sBY^7qwbrD50F7A!<?%S3Z^ z(JA@Q;CIi7i}@a zSW{JVHPc)DSIrt~rP@L+f_!BSDNEX*$v6}6u3o+^l?GR=*WhMTVr0}{B75L(F z`Lg_h_8D1U^T1DU@T(xIMj zJeL}7#77F(1xhrCQ*idzNm?g0l4S9!cm}-?ZmFhxM((8^WDZ*I6g^z&x0=cIy!Ecs z+FosR*;j?*tt6GenhTa?j`{J&w-4X1{JNL5FF)5?hfg4P>kgW}nU|a28kg$Rf!@%W zCWv*?E@6()4QJeW@=N6=`Ur*r!|a*#OBfxtvmb(yp*`$C{<`!+T~4t~5#27-K&#rh z%q~)^+U3ePjmniY;G()q0(BUDqG4Tp@@Kr&55i|CA^IyUlTG0ey>JM!TtKN<;2apUa!XE_^pGJ5(xkHaI zh_7TT*uQ3g6Tv3GlrE#XMJLadWuTibSB5Ey+yzyPZ^e_sm+&{XEZZXdN_k<}9y_W0 z`Wlz(zDvtW{gu?J!k{9oxg*guG_l}L)~;Wpep-I{)9Yndb8^1(yhQL?o5^Y^VM#Y7 z8sF>3>b7Zk`Wv;2no4P?Jzzdqscx0qi+%ZdoHaDp-_Tpw6XogX4fq8%LtI6?W%lZ) zm`>u{&u2)|DfCmKxAG0WCShreJWnBrALKIB#^2S{(9YI8py!h3mGz>)oea+MpZ6vE zzXmR{WrV-wn?wovC*#yq*M8AV(bU(J)%*gU^JV%v@J!!7Tvu*bNb{4#ML*dhiHk>p}<6RaTX%RaU&scjUkFMa1pW7oY`~0%OT&@)Gqo z9mTX^e$u-riFl_RkRA!c5wXq_R!J|Ee#Cf^BcFqj;S|_UE)mJ(RUlj4rJ~_++UPp; zT-ryEWbQE^m@Z5_-JPtimX~LUolzltg?FM;D+5(H&rn@-3o&M<%&HH_j`Uon40h)l z<^bJ?{=C$gUK;``78C!oG|90TplJ6~k9>{o~``9ypE3Y)9 zyJ}bJ7U;6HeY7*Q8QL^mw(f^sG*mIV^|Q5yC}`qvk>Gvr4EOzlPfn-P;Tqw&;(yDw z7Kf@|sY9Ckx-9)keHUGE%~Hyx{wrTW&Du11hO$Y0MSLaaP%|hyHHl0m_9y{qq*%Z& z3UA^bbItjGM6g7aQ*CXzhHaB3+(pPwoL9%S7-VI#A)V7c4A! z;Of$X3u>y&N$(-gGvtOqJtx3JGYGLsCCWyfAWMT6BSS5uwt$~=Pb!P9s`IE;oeoBe zXV|F|rKjlZ%H<35-NQRMJNJnF$-ZS*vsF+}dKj=`rxd513F=z zlV0jO6VSCX?Xh&QqL)TL2gs#=hvK}$oK?Xsp=MRetz7Wd_lWB+ub{4LV~pF(PSpKw zH}5kv(WXE>v1sR_hz<)(BOr*h}TRuU(jk`usp;*+P!!QnTGwKr`NOREr_zd;Z4aD-ubWIm; ziEX8HsXeL|k!6eLYLh!jJ$0G-ot{nW=n~XtqN3VKz9K#pHVC|6lD5gC)nsxf zb&(#$oM47BFX%?}9_k0U6;}`%@FJ}MKcD75emiirtOIw^3^04ufKH5;J*aS;A-7fL zsHcf(vq8Ko{&IZ<;-oe6cUH5gbPyUx|1;CR6*_fp@z;4Mxs3=m66pQUTykNJS=nD^lAf#zolG?ebLuC{)NekN*u zcj^XdH#4Is9r0Wi&_|>bcB7+k1b>9j;YSD>F)UV=S1Tom%cM&EqMI_wjE#8-zc!hs zaSHc=dQbg8WcVlbhCB-fpeo8&>6~~+h!ZY@(WSD`OnfP&fer2j@qnB}y{0Hspq!!< zaPJg>FBni>D(`?~lcD6`VMKLbPxS8vz*6%_ZY~$X&ocR!+*~=Rkf@I<2}ZL{)H>P& zW{xb~3WLow$UNBc)AGR5+%n(X+w{P2UpGlZ(qKtcCP?qVJ5f8#qj#`LNWq!QM8x8R zP)cf|*og(?0je`(rVPEG(o((1YeWYiLbg>8DnatG*1-$eTb-SIU%2>@t(r;3G zsi9O)>WtNWF4dMd;JjIe-rAx>f*Yy;JXDEzB%ngO2H2n`f!XRjSQx!TS#TM7h!f!Z z8UjAArC=aT0=H3LDuJ%gtkNjj9r_gG-=+X+nIECrCC=R0n4(81H`AQT0H~k60e_H=ODCnD==WSG*93>%8MQAMk%p1;$OT}*Y(>^WCeBL!13sz% zn795$AEgM!%J<;qngY(S72x=)4GzL`=-_(?cE#!#=U(C#7&0G%Uuhk(V#UD^HUdmo zCBXRh8$7G`n6X#lWypROI((<04(uU1n%8kGyN5lFe%gfaApWwDE?$?M(rD=-bb3WW z3nb!n>6!YJjy42s9STh@^}4d7#`)S8>&&b@tU6nfsEcc{x9FpDq9rn=L{36K)Kb&s`+ZM&_w?SMsV+OAtlr>S zAeXCJ<&N}Gj74W@QS@VW6>Oph7y|d@PRdz@0RP&5e0mp1k{-(3LAT2V-4|V7T^;S8 z%s?uZ$d~iQzCs=TAWmAV^34UWm@DU?>*q7IpMFG_r739rD@p=7B^ro*5VKs6{*nKN zUz`PwrZTXmEZFt_1sO&QVl_CXdXRsSS!5aN4=SH(N>8BY(T!=2T1YX}8L(BFz?qqX zb!iOF&%uf$-$qAO9k5gtA)1rP)JL4$zCspjJ9!7!g?9m#J(85jTjr)a>2S{|~!RAH2Da({T;Pvlx)^G#GoqPn*gI4l+P@s3h+!Ib-$ z$N^K}Nn#*)PfMfk{SR;=SB0dO1*cXuFn~5kFKJ!%2$;z}5v$0$)Dx-`?WK<}eKd`= zm2_tPBYii+eFI_S4bKb<3@`M*bceN+rW#$ABvnU_LDyI>1eUK}oI(q_`8g=A%as$>O zl_uzs)IKnr@nGSM0cYU^)d!}||JY*ZsP~j~?BJc!AaqKk$$gQ*dPTmVe`)IIE0|7O ze??4;O)vVk#PHIwWnPr(Qyhgz4vTRtby+;jP6#MIr>~g5j{l6WueU$2COhT#$vc`i z*=g|n6G-CsDsAYS+8g?@hBAig`e)jP=mKt!&c0IW1o<)SohMu*d>4J6N5f;$#W715 zEXe#CehmML{~_FzCaQO-hT5qHjd?7h<8J2a#(BEOOebI+d{#u%*7I^ZWu3AIUFG#4 zeS}g$X|3#p&NrwjU}_!=F3WRZQ+$l>+a(L-*hN+ajel*waWYwl{DI?REwlrCDxaxfQ_>PSPm5;fou#9zF?xM8t>qOmX{Um*HeLr10Z5d5zrUG3Y_2RW; zq%ax%Xtl&kVv4j!DuUW-9{p#Fl?z~cwPU@9fLHWi#08bWhdmS)T1U)RpDGq*6Kq*2 zxq@6DR+xiyZ3O@IedRs)1Lr|M(xj6-NL7G!KS^Js572Yy0d!}&9WrnK(rL_nrnTlV z?(?wLid^nu-D+J=onCiZTUUEt6R8=_e8xLJP(!HCWIb{WxIO>F511l-7f*`M#0F9U za!Dm2L5FacHR171M`idl`HCEn>q5FqD(~eX|KFo&5`}Kn3h)-jN^_;zz#54_hhn~1 z5nXD2X|)_i_5VMp^|h$Q)M{#9$bFvL1k9dyz$JMNEUNp!^!X0b5JNV_edx&J(4l(b z2|6Egz{dKK*hZ!xHtj&Kr=Qc&%n~L^lcD*d{h+&}Uu1Y`_}h?bXs(yFyAe6RpwvPJ*Rh z0bbFy=s3FxpP`{#1+v#k9w+YuH)A!}lQH0`j!-h?pXkzUgN#pW_y~Uy^~h!96fk@b zfJM2WL@7UkFEJjx#M{BL*%SPn4G3v8%TX5aES(S>$q*4#C}GP zQKWyd_p-<0z2RFNOb$1dqKFiFqGqgikanHM%q*emkYLY6-$oQziN`BcVX`_^hmyfbc>?UHWz?3)rbZ(QULp;EJWY{S0$HZL{865*w1nMDhAbq} z#Th>{OB2wv)wb8BYBP{C|G`vbR?}K~JJl4(M}Lt6$tdz1w8$#;4X{_PBf9AV=^c#@ zy!(*HR?2bQ$$s#s2Z+7oFv@`JOBPKr7DmRtxk{gbj@%C~peB8Xs!v@2pXp@W+Y%LB zs?ZOWVAsAX=asQa3Uqf_r7b*mzfug=xewN;GWd%>VprdUuC4gQ$VweF9?fB#^;Fj1)T{b{{-8cWUsD&Uz0S0wUy%*K{oM)r{Gc!f zot~$-Hoz#MxE9(Xx#D{1x_k@Fs5gmuq>n5M`~MGkO9z8pek*d{%Mr`- z=tBF!FXemismMU}=T`xVptvwicrH{HPoX1sp_C)_gkIt0UO-~-f^EDl*wuG{@0A4u zyBl1_*=h#3asz4%(G9vH2Q0A7z)Y42f4n$kt+~pv zMt3YE74A@^W?^s4=}3otm3g~im@Z2bWKx;FbRso^_#meXGS@lOIZ)1j)feF}8Q30d z!v5l_@Fj&KLP?+sIM54tRlW-89tm#dYw%B2sNMXaqQSEyP5e zvtI=}_-y!ocOgkKcFbWs?qY0NU}+z#_|a{73z3;e%oY=|FaC>lU#Wi*CBZtonf#Mn ziSL_E?j=8yvD6f5FV_DJIP~sQ*YR_QI!bM&`cPJQwGPBh{jgX61Xu2Latc+9zC;Is z6`Kv&KS1wAPC1V*&x}Uyv>|h!cF^UhlE{SZP`kpDZ3QOshggjaL|t{&`;hJSZ z=KD|isT`v$P#*sum!=1zDDb+gKnO+VnN;6F1GI%V_)wlFx5jyi6+bQIt#T&x!zXzy zY}_%a1xB`494Y>e$13FP-J%S%r1r>HPmqTxoxw+KK|EQ38bPh2UQ%^w15;jePCHs( z)95x8Mr8cjGSsr$Ji-)hU6;2-C$cL0ph;vF4#lUpj z74gM5rLs~5Uj7N_`eclDy?P&v%X?s#Q`B_q@yf7}8^LG$Cs=12DUZMd{0tGM6}Ih; zx()2wV=$9%!I3}OX*#+ozP4M|1h>8hhCkoMr>C((VW-c?5Nni@&XB-$s2~Af`GsymM z<|?hBQ>ocFkz0irUP46C5wi;TctJ_5V59+*6>;R$TU zZ<`>;HDJ+JVg+r$$-62YkcIhFQjQClvMu49jPf`71C3P|(h zs>l!ij+jmhw)bd4R9~nU(Gj=>bMhxxo__~7d@pFtE2^Z9A&lf|vM4p1+Ce?T<3Cx> zq-xMd>5hz(S*t6(8>XYLd=y5G{0ep$)-Y^j+c1k1^>iu{~H(q$>?9cCwZi@a(j6Ucz6%Vf5392 zAyar8=uwlTff&tc;9C3+i>?CQtB=wH=)_}y0=NfU+5s>@*9Hb+UyNchEJ7{#JbF~$ z-bc*07QXl`c;oFb+FWqRuOXfgfJX;6^bu5Sm!~FD2eD&+P+#B&Z=i-zO{iol71Dl# za#BU;9*A{!;<1h1h+X=CcG7mHK2~`ePPKKKk(xJ}PTD)#fVQqKRhOadr0t_=$+V>F zQuWCZSivZD3+&Yw@FG`}U!xbe5D@OxfEPIzdTx+V4_Ia+(FGkNb{8+APPZfGWFoRZ zQ-Lhd9v)p9v`#CaXKg}{U>IG*r{P0wRTyZgHQ?NS0!HyiVDfaSt)Rp5i4tUak|N*X zgu66+nQ35WzYZ-v6%6galjq2EXs4=_9{kWYsw{f%t5GfB0hFiGF$>KR5B`ZAF@hKb zPVszbwz}j@aw~ZSIiDxcRTp68T9L&N504}&gRA_NdKKTyf&sh|nA8)%nH~#12p_oS z1?<%B#3E#-a)}_~u$%4#XBv=$b8H9YxP zu)0qK|M>}I!EO@=Q8V+F$Rn&|8SK+Y@*AG(PLw1V;sPW+1NYkunqQB7z7}J=f>~NX z)+7U%%{hqY;*hVq3+wh7?~5dAA?G#{kKc$cL`5*F|H2jaqQd(>Z!sSpsRHx_kNOGs za9&*tDXfb)voh>Y4#s)_;~E8d9f|>8A90+8 zx=Z#W&Ezilz+W-LJBKfPXXt5pz4d`@bvhQb~>YdSU`*w;SfXBxcJ&lqJl#MhIhggnQkM*&3#H zhMcU2h5ifI7BS0ZphJ?0>bTnquta8PkAJWi^VE-O9B~YlHLu|9q{8F>2FZD>Jca%E zuILb>bi-?JG1J8f1Cb9q^$jEYrS5_>O;X1}&bwpO!!X`C_||<`t@W6PwV1iN&@qqT zJyn60s)&(R#oE-ter}7uQxN$@;eLt|B=+<-?Dx~^A~{BA{D*n${EjKi**0m)o| z=y^0gKM>;`iRU{)BMirE>?3BOu4p2j9fQ}}Vjde24RFoQkf%m?E}j@nw8yC1;@it( zh0EcuL`Y|E$oXx2ehhw$Sp8&tCJAfM1#>bSx%|4w<(DCvVV)w1bX2^|$H{qY-fBb_WXPwjpJmRtUhG3^pRF|uN;Pumx zzX$M|K4QLKs!_yWxKjH6HMj~1izF!AqZwXTVPt1Y5V!D-|77C7nRpLbxP{EY1>{N3 z5L+=T>meEKAxATaB18`&0=dOh!Vi6whig{B8rO#|EsIxdn0ere5-lMq<1wz%xb}6d z=@s=9qi4(h{6uh=Kh{SI~vswra_fQ7+QwLYGL2q%8feh$S6_Nc1 z{B{hV`5WuK43AzwJ*bBr&=|554}CUO9gTgo1akQk@A!iM3vjjCkixPUV->7QJ&cyb zZyd5837GZXnE&qht18yagl9B(%>dc?@6{1_Ee(6FE>f`G0~L`y1m`A!Uhpe>1FJ zOX!!LkbvfxwMO`sSm@(sn8Swn)->#yV)!xPxze~sE95}NVCCyTcNE1w?hOsw7Sd4) zI%puIq6MD218e&MT9+W^Vm8uoV)71q<}$3qC3tcZ;KhAY?Ra*GYQ#)P%6Q~d>Ofsy8h!$)XEjKX{`$Ncpn{(xRM0DapD&;3qJg9WdKyC@BrgRW4A6H74{1Z*U- z8rZ)!Ld7=@K|J#Xuhmmo;t)QunmB~Y^hwYh3kX6zK}6uXZ?NxfVzfExFXDl6k!+5+ zxKA8cIU+$lfK$v8(DqxES!4%zFH6Yc$`9n#*}#@_l$%u;V*O-`x}$P9HCV%KqMH*yu$_ABJD754XEuuu`0t3#N#bOt%s3$)%3 zSi8T~NrV;t`E5j|@X(3JM~O zeEna0_x|o6 zB_$=)NNFc(C2hncB#Er&p3i#!iuZ?Sj-%rkYkj}p=f2PDy3X^wuIFCQS4I5hj!n&U zO*|gQ*7B{vzstZz+~y1EOY0j?x%;GDVXax`5#a%>I6FlXi=#qOXiZPMz;|32<5~0{ zr6G1+#V${cv(x=?4i7gZc1oY9$qPbxpWj}dH!rzzY7?7_Wtq@7wUH&2V~aFg9yO4| zBdz#%z1vu?TAOVT|09NLOuz7Xsz!|(aS9!A+VNpSRw=e}%HRVmeWNF(Tn3NBRL!qy zc5-Nzc7&l>jWEH#HmczMp_k056#v)j#)QLD#n?}leVXQCi%ITux0gS!gzvK<@?&T= zA(j=>uV`Zx5gi^Tiu^a&uM;h~O{IK}Q^$snx$}Cu%!TUao=_*<5Kj&(u-z^*mXA}2 zm!v1mQs<|7ad&o8td99Q$F;b1eCUuG;ru#jcKAUYj&o0=6b86hwJnY(r0VentaDa) zT19Ni3Ncat^srZ7uXZO;->1TK5nU_4=9?^a3+HD0<8RqWcQ8g5*NOYHv!OO8yEfES z^WDQw*@|mtI|Jkd^dkLvOKFB7hCPmVNiBm!KADl{<|){Y*iQN4BCZ*p|S}{L70#o zpi9j#^WQ1VM3^6oPreoVhVf8#8{U{#{8e0-c4Srj6-XcIx(6CpsFL%-c&D&;X5X2O zf9g9C-$=!@qfhFs7wDXJs=yz!p0Nf#nkQZh)N^UMJ&k94KJ?>_`^f4p6z&#xT&UkOuF%Ao_7T+2lqF#?U$!6x9 z))wG~8%obp$ za+JT9&l&1di_(&81YEwSlGRo4UT0tSa^+d*?a8j2eILUop%oXh%5@rxNS}Bb*1AoU zhK1|Xv2lF%B?sFptrYLsv2kk4JMK*T)zB3xY_w2BEKM5;7TJ&fiYZcbg}3R?14Onjay?#qAgrnl2f zLe|UpN3n)KqIFWS3J$GB&&Ox4#*`f%ALABUbj$pM>L5=k%4R^rrk%OU~cWo;{x5RLgqz z((UQAqZ_yXdT5F>tArl>_ejb%kSi=qrN!_YZhkZmGFCpfpnivis_J5dsqpHwCEVwE zYWIdB_k@Dys@-HaMezh05o0B165g`UVc8z}Uq98sR#&D|;!UPtO=H(=xqLq=4-r@K{Pw*JI$?_BF*y$Lg4#5y>4gs&YKjoaRHd&@^7k(|jLJ zNbmZb3cme!E@wMaWgUrk{^^v%oG??~wbAdYb$;YcEIS!3X#k|nFTuNao6PIR_H6N=#*w}s-pzi)qD|9Z zVg)+6nG2hk)`TCjHMI8{9DICOk#&zl-AlMF?8N|=dw#)Cc{V-0NMm<-&k_nYK0B#k zWh(E}JF21WX&p@aV)~Qyq4mS$)IT1@7qz79b4;-Y@Y@Mn6^3zfguZtugcj<-&JImX z#Hxr~z3^PxlHIJT&d{+e$i{G}S720=55A!Z_tH-u{vtmMG0r`(yo~;@$Mxy3KLuJ$;E2dJy^Uli9(>UW)-Kfr~>cpld5z?BU2jwjON;bl)?d(v-Kx%$a;;RsCn z8c+YU{5eTnuMIa_W2tz7J(!)T_w`g|4*cGh8=FP?XmhFSxyxQoux)m7W1W>0$fUPS zq?gjI(G>eGvFNM&-AsY@Wb5s_k?Ox(^h?giZV>m1?!Rs0e7o?!(W)+?c0cKL2UFci zG_?(1HAZzcOy4;xJC^U6Eq}UVu&J`QAC2hAeU?lpF2P4;*tmETzp|KOj)?v$Gxg8` zJcVPfn_qxjP$MM!9 z)>)nM91y1};fQ!0Z(r9cqK>awI0g?@q`*UPOUG=OZeSGe+K~5B3p$}oDZ(Qvsqg>w z3HQQ$IPPjdGj7zu?o&}cp}Q0#9cdo0pWo?ZWd$6`cmDrc5j~4)_M}+5Jaen99_T`^ zJ&Yr56mE+pjP_`_FO`pF!X0|GTh!y@cz74??W~GAIo;RRE(-DFnP%1t?WG92Jj|J& z%Bj!fFkXRf7rw^Wi?Bn_)GuV&pZI4dUFmN&(pulu11CH$>ciyP>hzBDtf#v- zHy?YP60efmW%PdKV?C8VEOmhYH?F)+J`bTKg;2T`bS`YPBnA<)hY4r^y?$p_nHXSr;)dYf0;3llz;E(UIw{B z6@TINg`C)<^LUsKo2$R8Ym&7yP35R6!ef)3Zm6D;v&FyHa8hN||A;ih>K=6;=?1-C zX^}X9b=rlm-3gr~<1U76Ra3V*;xir}47Aqns%@Sr|HWL%0Iu*2sK2Q*_?ryCSn!K-*RfLf1i}5>0?J>*K;_&Cay3^rS4SwC#$at z*ze@{j=L#O$`?}(tTqL!Z!^KUkUmvSFWKoms&lRN6w|sNIyA6O^H+LbbxpzB{Cwms+&%(N^4F3qeCDVp|cDqHl z*N8TIE`W~w$MB@d#UiomDehh9S~V>FWwwTLHpQ6h)9bqC(qiy-I%xKAM(Rr^TBzTy z-03e^YmqteR?iu_H@s_Ck72UOW*xQc`hBiqicfeEmn=6~YQrV3Hy?VMk{?JPhUQMc z9dyt1Y7VQM?{*oeYPREr0+sR}?Or8&rkNUDje%~)pr4rGZc|A`)MAz_e1ZbBRhN@Z zC7+Vvb-b>JPbv%NA#l4Wb`$abu5$w)SlTzsn@5H7RmXSMSSrloC#uH&s%9|P@m$<0 z=L_-kb28}xj5-r$t9adIcHR%a)!_ol`uP*-r4qM|^PW~c2dGj_`|J#dJv{6dd8Tj0 z@L#K*ftdDo41KxP?(nn2%nx z_mOyaxR^GU7du36mYB`Nhs82;p(*VU8B{VmSzt0(froicmM?f<)xYC)T*&b+V@_wC!H3* zvc?wlDxJ(lKZktImcPy zKX~LEXQiItf-2}WSLi_6$fwi7=UHoW%azn@wdkD3MU}G3Qu21EdHAA|X*)mCPKWcY z6@97yx)bAlCj(xyt_6Cr{uE*Z%qfz-u?E#X2=#|`rKjNd71+Mytm8;=St2)wV((V6 zrKQLhn09|m`{v7{&LX&8pRieX@{>C-&a85h_v6ibu)+{k{E+;ehS|#UH2=mjL?vedQ)T$iO)w|!ZGnk)l=D3t`B#{Gq}Y89N}cwzZl<*#L}H`^`o5K94px5 zuIofIf%3fLFz#fwIbmBIxl}d1q`O_=<#&q=45MR$+6hwO0&fx9r^-wJIXA*gL&c+qS3`Co{sw( z;MKZtz21I4p_^NwKG?dtiqg4qWS37}fqzSMvsOIY6mYPsKJLFsW}h$k>^tn|4_(Ge zNQ_oFqhxxa^R%Da!R36!<@)I0_07C%6~|p98onw)*LtC9?P8BJc=J!iy}i?e?_q>R zvZE?gFQE(npf7)lWp}={si< zDs40_c!y%@W!*biX+Aqyo_3^~rD@3u*Dmn-yDwBgp>o6lH+{VT(%MCC7)&)49meKc`{x&D0=f41FkH;Y|LvByDu zOKJ#co|oIq$`@DFX?6)X2bVx6?ZoUTI@7%GyLSC z8h&3|w$;M5_v SynthesisResult: - return self.create_synthesis_result_from_wav( - message=message, - chunk_size=chunk_size, - file=get_audio_path("fake_audio.wav"), - ) diff --git a/tests/streaming/fixtures/transcriber.py b/tests/streaming/fixtures/transcriber.py deleted file mode 100644 index a78e3de26..000000000 --- a/tests/streaming/fixtures/transcriber.py +++ /dev/null @@ -1,26 +0,0 @@ -import asyncio - -import pytest -from vocode.streaming.models.transcriber import TranscriberConfig -from vocode.streaming.transcriber.base_transcriber import ( - BaseAsyncTranscriber, - Transcription, -) - - -class TestTranscriberConfig(TranscriberConfig, type="transcriber_test"): - __test__ = False - - -class TestAsyncTranscriber(BaseAsyncTranscriber): - __test__ = False - - async def _run_loop(self): - while True: - try: - self.output_queue.put_nowait( - Transcription(message="test", confidence=1, is_final=True) - ) - await asyncio.sleep(1) - except asyncio.CancelledError: - return diff --git a/tests/streaming/models/test_transcript.py b/tests/streaming/models/test_transcript.py deleted file mode 100644 index 39b1ae669..000000000 --- a/tests/streaming/models/test_transcript.py +++ /dev/null @@ -1,96 +0,0 @@ -import asyncio -from vocode.streaming.models.actions import ( - ActionInput, - ActionOutput, - TwilioPhoneCallActionInput, -) -from vocode.streaming.models.transcript import ActionStart, ActionFinish -from vocode.streaming.models.events import Sender -from vocode.streaming.models.transcript import Message -from vocode.streaming.models.transcript import Transcript -from vocode.streaming.action.nylas_send_email import ( - NylasSendEmailActionConfig, - NylasSendEmailParameters, - NylasSendEmailResponse, -) - - -def test_transcript_to_string(): - transcript = Transcript( - event_logs=[ - Message(sender=Sender.BOT, text="What up"), - Message( - sender=Sender.HUMAN, - text="Send me an email you bot. My email is du@de.com", - ), - ActionStart( - action_type="action_nylas_send_email", - action_input=TwilioPhoneCallActionInput( - action_config=NylasSendEmailActionConfig(), - conversation_id="123", - params=NylasSendEmailParameters( - recipient_email="du@de.com", - body="What up", - subject="This is the bot", - ), - _user_message_tracker=asyncio.Event(), - twilio_sid="123", - ), - ), - ActionFinish( - action_type="action_nylas_send_email", - action_output=ActionOutput( - action_type="action_nylas_send_email", - response=NylasSendEmailResponse(success=True), - ), - ), - ] - ) - - assert ( - transcript.to_string() - == """BOT: What up -HUMAN: Send me an email you bot. My email is du@de.com -ACTION_WORKER: params={'recipient_email': 'du@de.com', 'body': 'What up', 'subject': 'This is the bot'} -ACTION_WORKER: action_type='action_nylas_send_email' response={'success': True}""" - ) - - -def test_transcript_to_string_no_phone_input(): - transcript = Transcript( - event_logs=[ - Message(sender=Sender.BOT, text="What up"), - Message( - sender=Sender.HUMAN, - text="Send me an email you bot. My email is du@de.com", - ), - ActionStart( - action_type="action_nylas_send_email", - action_input=ActionInput( - action_config=NylasSendEmailActionConfig(), - conversation_id="123", - params=NylasSendEmailParameters( - recipient_email="du@de.com", - body="What up", - subject="This is the bot", - ), - _user_message_tracker=asyncio.Event(), - ), - ), - ActionFinish( - action_type="action_nylas_send_email", - action_output=ActionOutput( - action_type="action_nylas_send_email", - response=NylasSendEmailResponse(success=True), - ), - ), - ] - ) - - assert ( - transcript.to_string() - == """BOT: What up -HUMAN: Send me an email you bot. My email is du@de.com -ACTION_WORKER: params={'recipient_email': 'du@de.com', 'body': 'What up', 'subject': 'This is the bot'} -ACTION_WORKER: action_type='action_nylas_send_email' response={'success': True}""" - ) diff --git a/tests/streaming/synthesizer/conftest.py b/tests/streaming/synthesizer/conftest.py new file mode 100644 index 000000000..01a42f63d --- /dev/null +++ b/tests/streaming/synthesizer/conftest.py @@ -0,0 +1,26 @@ +import pytest + + +@pytest.fixture(scope="session") +def default_env_vars(default_env_vars: dict[str, str]) -> dict[str, str]: + """ + Extends the `default_env_vars` fixture specifically for the submodule. + + This fixture takes the session-scoped `default_env_vars` fixture from the parent conftest.py + and extends or overrides it with additional or modified environment variables specific to + the submodule. + + :param default_env_vars: The inherited `default_env_vars` fixture from the parent conftest. + :return: A modified dictionary of default environment variables for the submodule. + """ + submodule_env_vars = default_env_vars.copy() + + submodule_env_vars.update( + { + "VOCODE_PLAYHT_ON_PREM_ADDR": "test", + "BASE_URL": "test", + "CALL_SERVER_BASE_URL": "test2", + } + ) + + return submodule_env_vars diff --git a/tests/streaming/synthesizer/test_audio_cache.py b/tests/streaming/synthesizer/test_audio_cache.py new file mode 100644 index 000000000..5bc9efc7c --- /dev/null +++ b/tests/streaming/synthesizer/test_audio_cache.py @@ -0,0 +1,61 @@ +import pytest +from fakeredis import FakeAsyncRedis, FakeServer +from pytest_mock import MockerFixture + +from vocode.streaming.utils.singleton import Singleton + + +@pytest.fixture(autouse=True) +def cleanup_singleton_audio_cache(): + from vocode.streaming.synthesizer.audio_cache import AudioCache + + if AudioCache in Singleton._instances: + del Singleton._instances[AudioCache] + yield + + +@pytest.mark.asyncio +async def test_set_and_get(mocker: MockerFixture): + from vocode.streaming.synthesizer.audio_cache import AudioCache + + fake_redis = FakeAsyncRedis() + + mocker.patch( + "vocode.streaming.synthesizer.audio_cache.initialize_redis_bytes", return_value=fake_redis + ) + + cache = await AudioCache.safe_create() + voice_identifier = "voice_id" + text = "text" + audio_data = b"chunk" + + assert await cache.get_audio(voice_identifier, text) is None + + await cache.set_audio(voice_identifier, text, audio_data) + assert await cache.get_audio(voice_identifier, text) == b"chunk" + + +@pytest.mark.asyncio +async def test_safe_create_set_and_get_disabled(mocker: MockerFixture): + from vocode.streaming.synthesizer.audio_cache import AudioCache + + # will fail the ping + server = FakeServer() + server.connected = False + + fake_redis = FakeAsyncRedis(server=server) + + mocker.patch( + "vocode.streaming.synthesizer.audio_cache.initialize_redis_bytes", return_value=fake_redis + ) + + cache = await AudioCache.safe_create() + voice_identifier = "voice_id" + text = "text" + audio_data = b"chunk" + + assert await cache.get_audio(voice_identifier, text) is None + + await cache.set_audio(voice_identifier, text, audio_data) + + assert await cache.get_audio(voice_identifier, text) is None diff --git a/tests/streaming/synthesizer/test_factory.py b/tests/streaming/synthesizer/test_factory.py new file mode 100644 index 000000000..9ee262a16 --- /dev/null +++ b/tests/streaming/synthesizer/test_factory.py @@ -0,0 +1,87 @@ +from unittest.mock import MagicMock, patch + +from pyht import AsyncClient +from pyht.client import CongestionCtrl +from pytest_mock import MockerFixture + +from vocode.streaming.models.audio import AudioEncoding +from vocode.streaming.models.synthesizer import PlayHtSynthesizerConfig +from vocode.streaming.synthesizer.default_factory import DefaultSynthesizerFactory + +DEFAULT_PARAMS = { + "sampling_rate": 16000, + "audio_encoding": AudioEncoding.LINEAR16, + "voice_id": "s3://manifest.json", +} + + +def test_get_play_ht_synthesizer_v2_or_v1(mocker: MockerFixture): + factory = DefaultSynthesizerFactory() + + v1_constructor = mocker.patch("vocode.streaming.synthesizer.default_factory.PlayHtSynthesizer") + v2_constructor = mocker.patch( + "vocode.streaming.synthesizer.default_factory.PlayHtSynthesizerV2" + ) + + factory.create_synthesizer( + PlayHtSynthesizerConfig(version="2", **DEFAULT_PARAMS.copy()), + ), + v2_constructor.assert_called_once() + v2_constructor.reset_mock() + + factory.create_synthesizer( + PlayHtSynthesizerConfig(version="1", **DEFAULT_PARAMS.copy()), + ) + v1_constructor.assert_called_once() + v1_constructor.reset_mock() + + factory.create_synthesizer( + PlayHtSynthesizerConfig(**DEFAULT_PARAMS.copy()), + ) + v2_constructor.assert_called_once() + + +def test_create_play_ht_synthesizer_on_prem(mocker: MockerFixture): + with patch( + "vocode.streaming.synthesizer.play_ht_synthesizer_v2.AsyncClient", + new_callable=MagicMock, + ) as MockOSClient: + MockOSClient.AdvancedOptions = AsyncClient.AdvancedOptions + + user_id = "user_id" + api_key = "api_key" + factory = DefaultSynthesizerFactory() + + factory.create_synthesizer( + PlayHtSynthesizerConfig( + version="2", **DEFAULT_PARAMS.copy(), user_id=user_id, api_key=api_key + ), + ) + + MockOSClient.assert_called_once_with(user_id=user_id, api_key=api_key) + + MockOSClient.reset_mock() + + factory.create_synthesizer( + PlayHtSynthesizerConfig( + version="2", + on_prem=True, + on_prem_provider="aws", + **DEFAULT_PARAMS.copy(), + user_id=user_id, + api_key=api_key + ), + ) + + advanced_options = AsyncClient.AdvancedOptions( + grpc_addr=None, + fallback_enabled=True, + congestion_ctrl=CongestionCtrl.STATIC_MAR_2023, + ) + + MockOSClient.assert_called_with( + user_id=user_id, + api_key=api_key, + advanced=advanced_options, + ) + MockOSClient.reset_mock() diff --git a/tests/streaming/test_streaming_conversation.py b/tests/streaming/test_streaming_conversation.py index bfc8ee25a..e38b6efad 100644 --- a/tests/streaming/test_streaming_conversation.py +++ b/tests/streaming/test_streaming_conversation.py @@ -1,51 +1,453 @@ import asyncio -import logging +from typing import List +from unittest.mock import MagicMock + import pytest -from tests.streaming.fixtures.output_device import SilentOutputDevice -from tests.streaming.fixtures.synthesizer import TestSynthesizer, TestSynthesizerConfig -from tests.streaming.fixtures.transcriber import ( - TestAsyncTranscriber, - TestTranscriberConfig, +from pydantic.v1 import BaseModel +from pytest_mock import MockerFixture +from tests.fakedata.conversation import ( + DEFAULT_CHAT_GPT_AGENT_CONFIG, + create_fake_agent, + create_fake_streaming_conversation, +) + +from vocode.streaming.models.actions import ActionInput +from vocode.streaming.models.agent import InterruptSensitivity +from vocode.streaming.models.events import Sender +from vocode.streaming.models.transcriber import Transcription +from vocode.streaming.models.transcript import ActionStart, Message, Transcript +from vocode.streaming.utils.worker import AsyncWorker + + +class ShouldIgnoreUtteranceTestCase(BaseModel): + transcript: Transcript + human_transcription: str + expected: bool + + +async def _consume_worker_output(worker: AsyncWorker, timeout: float = 0.1): + try: + return await asyncio.wait_for(worker.output_queue.get(), timeout=timeout) + except asyncio.TimeoutError: + return None + + +def test_interrupt_sensitivity(mocker: MockerFixture): + from vocode.streaming.streaming_conversation import StreamingConversation + + mock_instance = mocker.MagicMock(spec=StreamingConversation.TranscriptionsWorker) + mocker.patch.object( + mock_instance, + "is_transcription_backchannel", + wraps=StreamingConversation.TranscriptionsWorker.is_transcription_backchannel, + ) + mock_instance.conversation = mocker.MagicMock() + mock_instance.conversation.agent = mocker.MagicMock() + + mock_instance.conversation.agent.get_agent_config = mocker.MagicMock( + return_value=mocker.MagicMock(interrupt_sensitivity="high") + ) + + test_transcription = Transcription(message="test", confidence=1.0, is_final=True) + assert mock_instance.is_transcription_backchannel(mock_instance, test_transcription) is False + + mock_instance.conversation.agent.get_agent_config = mocker.MagicMock( + return_value=mocker.MagicMock(interrupt_sensitivity="low") + ) + assert mock_instance.is_transcription_backchannel(mock_instance, test_transcription) is True + + +@pytest.mark.parametrize( + "test_case", + [ + ShouldIgnoreUtteranceTestCase( + transcript=Transcript( + event_logs=[], + ), + human_transcription="hi", + expected=False, + ), + ShouldIgnoreUtteranceTestCase( + transcript=Transcript( + event_logs=[ + Message( + sender=Sender.BOT, + text="hi there", + is_final=True, + is_end_of_turn=True, + ), + ], + ), + human_transcription="hi", + expected=False, + ), + ShouldIgnoreUtteranceTestCase( + transcript=Transcript( + event_logs=[ + Message( + sender=Sender.BOT, + text="hi there", + is_final=False, + is_end_of_turn=False, + ), + ], + ), + human_transcription="one two three four", + expected=False, + ), + ShouldIgnoreUtteranceTestCase( + transcript=Transcript( + event_logs=[ + Message( + sender=Sender.BOT, + text="hi there", + is_final=False, + is_end_of_turn=False, + ), + ], + ), + human_transcription="hello?", + expected=True, + ), + ShouldIgnoreUtteranceTestCase( + transcript=Transcript( + event_logs=[ + Message( + sender=Sender.BOT, + text="hi there", + is_final=True, + is_end_of_turn=True, + ), + Message( + sender=Sender.HUMAN, + text="hi there", + ), + ], + ), + human_transcription="hello?", + expected=False, + ), + ShouldIgnoreUtteranceTestCase( + transcript=Transcript( + event_logs=[ + Message( + sender=Sender.BOT, + text="hi there", + is_final=False, + ), + ActionStart( + action_type="action", + action_input=MagicMock(spec=ActionInput), + ), + ], + ), + human_transcription="hello?", + expected=True, + ), + ShouldIgnoreUtteranceTestCase( + transcript=Transcript( + event_logs=[ + Message( + sender=Sender.BOT, + text="hi there", + is_final=True, + is_end_of_turn=True, + ), + ActionStart( + action_type="action", + action_input=MagicMock(spec=ActionInput), + ), + ], + ), + human_transcription="hello?", + expected=False, + ), + ], ) -from vocode.streaming.agent.echo_agent import EchoAgent -from vocode.streaming.models.agent import EchoAgentConfig -from vocode.streaming.models.audio_encoding import AudioEncoding -from vocode.streaming.models.message import BaseMessage -from vocode.streaming.streaming_conversation import StreamingConversation +def test_should_ignore_utterance( + mocker: MockerFixture, + test_case: ShouldIgnoreUtteranceTestCase, +): + from vocode.streaming.streaming_conversation import StreamingConversation + + conversation = mocker.MagicMock() + transcriptions_worker = StreamingConversation.TranscriptionsWorker( + input_queue=mocker.MagicMock(), + output_queue=mocker.MagicMock(), + conversation=conversation, + interruptible_event_factory=mocker.MagicMock(), + ) + conversation = mocker.MagicMock() + conversation.interrupt_sensitivity = "low" + transcriptions_worker.has_associated_ignored_utterance = False + + transcriptions_worker.conversation.transcript = test_case.transcript + assert ( + transcriptions_worker.should_ignore_utterance( + Transcription(message=test_case.human_transcription, confidence=1.0, is_final=True), + ) + == test_case.expected + ) + + +class TranscriptionsWorkerTestCase(BaseModel): + transcriptions: List[Transcription] + transcript: Transcript + should_broadcast_interrupt: bool + initial_message_ongoing: bool + should_kick_off_pipeline: bool + interrupt_sensitivity: InterruptSensitivity + + +async def _mock_streaming_conversation_constructor( + mocker: MockerFixture, + interrupt_sensitivity: InterruptSensitivity = "low", +): + + streaming_conversation = create_fake_streaming_conversation( + mocker, + agent=create_fake_agent( + mocker, + DEFAULT_CHAT_GPT_AGENT_CONFIG.copy( + update={"interrupt_sensitivity": interrupt_sensitivity} + ), + ), + ) + streaming_conversation.broadcast_interrupt = mocker.MagicMock( + wraps=streaming_conversation.broadcast_interrupt + ) + return streaming_conversation + + +@pytest.mark.asyncio +async def test_transcriptions_worker_ignores_utterances_before_initial_message( + mocker: MockerFixture, +): + streaming_conversation = await _mock_streaming_conversation_constructor( + mocker, + ) + + streaming_conversation.transcriptions_worker.input_queue = asyncio.Queue() + streaming_conversation.transcriptions_worker.output_queue = asyncio.Queue() + streaming_conversation.transcriptions_worker.start() + streaming_conversation.transcriptions_worker.consume_nonblocking( + Transcription( + message="sup", + confidence=1.0, + is_final=True, + ), + ) + streaming_conversation.transcriptions_worker.consume_nonblocking( + Transcription( + message="hi, who is", + confidence=1.0, + is_final=False, + ), + ) + streaming_conversation.transcriptions_worker.consume_nonblocking( + Transcription( + message="hi, who is calling?", + confidence=1.0, + is_final=True, + ), + ) + assert await _consume_worker_output(streaming_conversation.transcriptions_worker) is None + assert not streaming_conversation.broadcast_interrupt.called + + streaming_conversation.transcript.add_bot_message( + text="hi there", is_final=True, conversation_id="test" + ) + streaming_conversation.initial_message_tracker.set() + + streaming_conversation.transcriptions_worker.consume_nonblocking( + Transcription( + message="hi, who is this?", + confidence=1.0, + is_final=True, + ), + ) + + transcription_agent_input = await _consume_worker_output( + streaming_conversation.transcriptions_worker + ) + assert transcription_agent_input.payload.transcription.message == "hi, who is this?" + assert streaming_conversation.broadcast_interrupt.called -logging.basicConfig() -logger = logging.getLogger(__name__) -logger.setLevel(logging.DEBUG) + assert streaming_conversation.transcript.event_logs[0].sender == Sender.BOT + + human_backchannels = streaming_conversation.transcript.event_logs[1:] + assert all( + backchannel.sender == Sender.HUMAN and backchannel.is_backchannel + for backchannel in human_backchannels + ) + streaming_conversation.transcriptions_worker.terminate() + + +@pytest.mark.asyncio +async def test_transcriptions_worker_ignores_associated_ignored_utterance( + mocker: MockerFixture, +): + streaming_conversation = await _mock_streaming_conversation_constructor( + mocker, + ) + + streaming_conversation.transcriptions_worker.input_queue = asyncio.Queue() + streaming_conversation.transcriptions_worker.output_queue = asyncio.Queue() + streaming_conversation.transcriptions_worker.start() + streaming_conversation.initial_message_tracker.set() + streaming_conversation.transcript.add_bot_message( + text="Hi, I was wondering", + is_final=False, + conversation_id="test", + ) + + streaming_conversation.transcriptions_worker.consume_nonblocking( + Transcription( + message="i'm listening", + confidence=1.0, + is_final=False, + ), + ) + assert await _consume_worker_output(streaming_conversation.transcriptions_worker) is None + assert not streaming_conversation.broadcast_interrupt.called # ignored for length of response + + streaming_conversation.transcript.event_logs[-1].text = ( + "Hi, I was wondering if you had a chance to look at my email?" + ) + streaming_conversation.transcript.event_logs[-1].is_final = True + streaming_conversation.transcriptions_worker.consume_nonblocking( + Transcription( + message="I'm listening.", + confidence=1.0, + is_final=True, + ), + ) + + assert await _consume_worker_output(streaming_conversation.transcriptions_worker) is None + assert not streaming_conversation.broadcast_interrupt.called # ignored for length of response + + streaming_conversation.transcriptions_worker.consume_nonblocking( + Transcription( + message="I have not yet gotten a chance.", + confidence=1.0, + is_final=True, + ), + ) + + transcription_agent_input = await _consume_worker_output( + streaming_conversation.transcriptions_worker + ) + assert ( + transcription_agent_input.payload.transcription.message == "I have not yet gotten a chance." + ) + assert streaming_conversation.broadcast_interrupt.called + assert [message.text for message in streaming_conversation.transcript.event_logs] == [ + "Hi, I was wondering if you had a chance to look at my email?", + "I'm listening.", + ] + assert streaming_conversation.transcript.event_logs[-1].is_backchannel + streaming_conversation.transcriptions_worker.terminate() @pytest.mark.asyncio -async def test_streaming_conversation(): - sampling_rate = 16000 - audio_encoding = AudioEncoding.LINEAR16 - chunk_size = 2048 - silent_output_device = SilentOutputDevice( - sampling_rate=sampling_rate, audio_encoding=audio_encoding - ) - - conversation = StreamingConversation( - output_device=silent_output_device, - transcriber=TestAsyncTranscriber( - TestTranscriberConfig( - sampling_rate=sampling_rate, - audio_encoding=audio_encoding, - chunk_size=chunk_size, - ) - ), - agent=EchoAgent( - EchoAgentConfig( - initial_message=BaseMessage(text="test"), - ) - ), - synthesizer=TestSynthesizer( - TestSynthesizerConfig.from_output_device(silent_output_device) - ), - logger=logger, - ) - await conversation.start() - await asyncio.sleep(1) - await conversation.terminate() +async def test_transcriptions_worker_interrupts_on_interim_transcripts( + mocker: MockerFixture, +): + streaming_conversation = await _mock_streaming_conversation_constructor( + mocker, + ) + + streaming_conversation.transcriptions_worker.input_queue = asyncio.Queue() + streaming_conversation.transcriptions_worker.output_queue = asyncio.Queue() + streaming_conversation.transcriptions_worker.start() + streaming_conversation.initial_message_tracker.set() + streaming_conversation.transcript.add_bot_message( + text="Hi, I was wondering", + is_final=False, + conversation_id="test", + ) + + streaming_conversation.transcriptions_worker.consume_nonblocking( + Transcription( + message="Sorry, could you stop", + confidence=1.0, + is_final=False, + ), + ) + + assert await _consume_worker_output(streaming_conversation.transcriptions_worker) is None + assert streaming_conversation.broadcast_interrupt.called + + streaming_conversation.transcriptions_worker.consume_nonblocking( + Transcription( + message="Sorry, could you stop talking please?", + confidence=1.0, + is_final=True, + ), + ) + + transcription_agent_input = await _consume_worker_output( + streaming_conversation.transcriptions_worker + ) + assert ( + transcription_agent_input.payload.transcription.message + == "Sorry, could you stop talking please?" + ) + + assert streaming_conversation.transcript.event_logs[-1].sender == Sender.BOT + assert streaming_conversation.transcript.event_logs[-1].text == "Hi, I was wondering" + streaming_conversation.transcriptions_worker.terminate() + + +@pytest.mark.asyncio +async def test_transcriptions_worker_interrupts_immediately_before_bot_has_begun_turn( + mocker: MockerFixture, +): + streaming_conversation = await _mock_streaming_conversation_constructor( + mocker, + ) + + streaming_conversation.transcriptions_worker.input_queue = asyncio.Queue() + streaming_conversation.transcriptions_worker.output_queue = asyncio.Queue() + streaming_conversation.transcriptions_worker.start() + streaming_conversation.initial_message_tracker.set() + + streaming_conversation.transcriptions_worker.consume_nonblocking( + Transcription( + message="Sorry,", + confidence=1.0, + is_final=False, + ), + ) + assert await _consume_worker_output(streaming_conversation.transcriptions_worker) is None + assert streaming_conversation.broadcast_interrupt.called + + streaming_conversation.transcriptions_worker.consume_nonblocking( + Transcription( + message="Sorry, what?", + confidence=1.0, + is_final=True, + ), + ) + transcription_agent_input = await _consume_worker_output( + streaming_conversation.transcriptions_worker + ) + assert transcription_agent_input.payload.transcription.message == "Sorry, what?" + assert streaming_conversation.broadcast_interrupt.called + + streaming_conversation.transcript.add_bot_message( + text="", is_final=False, conversation_id="test" + ) + + streaming_conversation.transcriptions_worker.consume_nonblocking( + Transcription( + message="Couldn't", + confidence=1.0, + is_final=False, + ), + ) + + assert await _consume_worker_output(streaming_conversation.transcriptions_worker) is None + assert streaming_conversation.broadcast_interrupt.called + + streaming_conversation.transcriptions_worker.terminate() diff --git a/tests/streaming/utils/test_events_manager.py b/tests/streaming/utils/test_events_manager.py index d6bfaf4ab..75cb02f32 100644 --- a/tests/streaming/utils/test_events_manager.py +++ b/tests/streaming/utils/test_events_manager.py @@ -1,7 +1,8 @@ -import pytest import asyncio -from vocode.streaming.models.events import PhoneCallEndedEvent, EventType +import pytest + +from vocode.streaming.models.events import EventType, PhoneCallEndedEvent from vocode.streaming.utils.events_manager import EventsManager CONVERSATION_ID = "1" @@ -34,6 +35,21 @@ async def test_handle_event_default_implementation(): await manager.handle_event(event) +@pytest.mark.asyncio +async def test_handle_event_non_async_override(mocker): + event = PhoneCallEndedEvent(conversation_id=CONVERSATION_ID, type=EventType.PHONE_CALL_ENDED) + manager = EventsManager([EventType.PHONE_CALL_ENDED]) + manager.publish_event(event) + + error_logger_mock = mocker.patch("vocode.streaming.utils.events_manager.logger.error") + manager.handle_event = lambda event: None + await manager.flush() + assert manager.queue.empty() + error_logger_mock.assert_called_once_with( + "Handle event was overridden with non-async function. Please override with async function." + ) + + @pytest.mark.asyncio async def test_start_and_active_loop(): event = PhoneCallEndedEvent( @@ -48,18 +64,16 @@ async def test_start_and_active_loop(): @pytest.mark.asyncio async def test_flush_method(): - event = PhoneCallEndedEvent( - conversation_id=CONVERSATION_ID, type=EventType.PHONE_CALL_ENDED - ) + event = PhoneCallEndedEvent(conversation_id=CONVERSATION_ID, type=EventType.PHONE_CALL_ENDED) manager = EventsManager([EventType.PHONE_CALL_ENDED]) for _ in range(5): manager.publish_event(event) - await manager.flush(timeout=2) + await manager.flush() assert manager.queue.empty() @pytest.mark.asyncio async def test_queue_empty_and_timeout(): manager = EventsManager([EventType.TRANSCRIPT]) - await manager.flush(timeout=0) + await manager.flush() assert manager.queue.empty() diff --git a/tests/streaming/utils/test_phone_numbers.py b/tests/streaming/utils/test_phone_numbers.py new file mode 100644 index 000000000..3edfdd9fc --- /dev/null +++ b/tests/streaming/utils/test_phone_numbers.py @@ -0,0 +1,49 @@ +import re + +import pytest + +from vocode.streaming.utils.phone_numbers import NUMBER_PARSE_ERROR, sanitize_phone_number + + +def test_sanitize_phone_number_valid_number_without_region(): + phone = "14155552671" # This is a valid US number + expected_result = "14155552671" + result = sanitize_phone_number(phone) + assert result == expected_result + + +def test_sanitize_phone_number_valid_number_with_plus(): + phone = "+14155552671" + expected_result = "14155552671" + result = sanitize_phone_number(phone) + assert result == expected_result + + +def test_sanitize_phone_number_invalid_number_without_region(): + phone = "gibberish" + with pytest.raises(ValueError, match=re.escape(NUMBER_PARSE_ERROR)): + sanitize_phone_number(phone) + + +def test_sanitize_phone_number_invalid_number_with_region(): + phone = "+1911" + with pytest.raises(ValueError, match=re.escape(NUMBER_PARSE_ERROR)): + sanitize_phone_number(phone) + + +def test_sanitize_phone_number_valid_number_with_non_us_region(): + phone = "+443031237301" # This is a valid GB number for Buckingham Palace + expected_result = "443031237301" + result = sanitize_phone_number(phone) + assert result == expected_result + + # test same number with no + + result = sanitize_phone_number(phone[1:]) + assert result == expected_result + + +def test_sanitize_phone_number_adds_country_code(): + phone = "4155552222" + expected_result = "14155552222" + result = sanitize_phone_number(phone) + assert result == expected_result diff --git a/tests/streaming/utils/test_utils.py b/tests/streaming/utils/test_utils.py new file mode 100644 index 000000000..04c7575df --- /dev/null +++ b/tests/streaming/utils/test_utils.py @@ -0,0 +1,54 @@ +import pytest + +from vocode.streaming.utils import generate_from_async_iter_with_lookahead, generate_with_is_last + + +@pytest.mark.asyncio +async def test_generate_with_is_last(): + async def async_gen(): + yield 1 + yield 2 + yield 3 + + async_iter = generate_with_is_last(async_gen()).__aiter__() + + assert await async_iter.__anext__() == (1, False) + assert await async_iter.__anext__() == (2, False) + assert await async_iter.__anext__() == (3, True) + + +@pytest.mark.asyncio +async def test_generate_with_lookahead_long(): + async def async_gen(): + yield 1 + yield 2 + yield 3 + yield 4 + yield 5 + + async_iter = generate_from_async_iter_with_lookahead(async_gen(), 2).__aiter__() + + expected_gen = [ + [1, 2, 3], + [2, 3, 4], + [3, 4, 5], + ] + idx = 0 + async for buffer in async_iter: + assert buffer == expected_gen[idx] + idx += 1 + + +@pytest.mark.asyncio +async def test_generate_with_lookahead_short(): + async def async_gen(): + yield 1 + yield 2 + + async_iter = generate_from_async_iter_with_lookahead(async_gen(), 2).__aiter__() + + expected_gen = [[1, 2]] + idx = 0 + async for buffer in async_iter: + assert buffer == expected_gen[idx] + idx += 1 diff --git a/tests/synthesizer/conftest.py b/tests/synthesizer/conftest.py deleted file mode 100644 index 2a09b36d2..000000000 --- a/tests/synthesizer/conftest.py +++ /dev/null @@ -1,128 +0,0 @@ -import pytest -from aioresponses import aioresponses, CallbackResult -from vocode.streaming.models.audio_encoding import AudioEncoding -from vocode.streaming.models.synthesizer import ( - ElevenLabsSynthesizerConfig, - PlayHtSynthesizerConfig, -) -import re -from vocode.streaming.synthesizer.eleven_labs_synthesizer import ( - ElevenLabsSynthesizer, - ELEVEN_LABS_BASE_URL, -) -from vocode.streaming.synthesizer.play_ht_synthesizer import ( - PlayHtSynthesizer, - TTS_ENDPOINT, -) - -import re -from tests.streaming.data.loader import get_audio_path - -import asyncio -import pytest - -DEFAULT_PARAMS = {"sampling_rate": 16000, "audio_encoding": AudioEncoding.LINEAR16} - -MOCK_API_KEY = "my_api_key" -MOCK_USER_ID = "my_user_id" - - -def create_eleven_labs_request_handler(optimize_streaming_latency=False): - def request_handler(url, headers, **kwargs): - if optimize_streaming_latency and not re.search( - r"optimize_streaming_latency=\d", url - ): - raise Exception("optimize_streaming_latency not found in url") - if headers["xi-api-key"] != MOCK_API_KEY: - return CallbackResult(status=401) - with open(get_audio_path("fake_audio.mp3"), "rb") as audio_file: - return CallbackResult(content_type="audio/mpeg", body=audio_file.read()) - - return request_handler - - -@pytest.fixture -def mock_eleven_labs_api(): - with aioresponses() as m: - pattern = re.compile(rf"{re.escape(ELEVEN_LABS_BASE_URL)}text-to-speech/\w+") - m.post(pattern, callback=create_eleven_labs_request_handler()) - yield m - - -@pytest.fixture(scope="module") -async def fixture_eleven_labs_synthesizer_with_api_key(): - params = DEFAULT_PARAMS.copy() - params["api_key"] = MOCK_API_KEY - return ElevenLabsSynthesizer(ElevenLabsSynthesizerConfig(**params)) - - -@pytest.fixture(scope="module") -async def fixture_eleven_labs_synthesizer_wrong_api_key(): - params = DEFAULT_PARAMS.copy() - params["api_key"] = "wrong_api_key" - return ElevenLabsSynthesizer(ElevenLabsSynthesizerConfig(**params)) - - -@pytest.fixture(scope="module") -async def fixture_eleven_labs_synthesizer_env_api_key(): - params = DEFAULT_PARAMS.copy() - import os - - os.environ["ELEVEN_LABS_API_KEY"] = MOCK_API_KEY - return ElevenLabsSynthesizer(ElevenLabsSynthesizerConfig(**params)) - - -# PlayHT Setup - - -def create_play_ht_request_handler(): - def request_handler(url, headers, **kwargs): - if headers["AUTHORIZATION"] != f"Bearer {MOCK_API_KEY}": - return CallbackResult(status=401) - if headers["X-USER-ID"] != MOCK_USER_ID: - return CallbackResult(status=401) - with open(get_audio_path("fake_audio.mp3"), "rb") as audio_file: - return CallbackResult(content_type="audio/mpeg", body=audio_file.read()) - - return request_handler - - -@pytest.fixture -def mock_play_ht_api(): - with aioresponses() as m: - m.post(TTS_ENDPOINT, callback=create_play_ht_request_handler()) - yield m - - -@pytest.fixture(scope="module") -async def fixture_play_ht_synthesizer_with_api_key(): - params = DEFAULT_PARAMS.copy() - params["api_key"] = MOCK_API_KEY - params["user_id"] = MOCK_USER_ID - return PlayHtSynthesizer(PlayHtSynthesizerConfig(**params)) - - -@pytest.fixture(scope="module") -async def fixture_play_ht_synthesizer_wrong_api_key(): - params = DEFAULT_PARAMS.copy() - params["api_key"] = "wrong_api_key" - params["user_id"] = MOCK_USER_ID - return PlayHtSynthesizer(PlayHtSynthesizerConfig(**params)) - - -@pytest.fixture(scope="module") -async def fixture_play_ht_synthesizer_wrong_user_id(): - params = DEFAULT_PARAMS.copy() - params["api_key"] = MOCK_API_KEY - params["user_id"] = "wrong_api_key" - return PlayHtSynthesizer(PlayHtSynthesizerConfig(**params)) - - -@pytest.fixture(scope="module") -async def fixture_play_ht_synthesizer_env_api_key(): - params = DEFAULT_PARAMS.copy() - import os - - os.environ["PLAY_HT_API_KEY"] = MOCK_API_KEY - os.environ["PLAY_HT_USER_ID"] = MOCK_USER_ID - return PlayHtSynthesizer(PlayHtSynthesizerConfig(**params)) diff --git a/tests/synthesizer/test_eleven_labs.py b/tests/synthesizer/test_eleven_labs.py deleted file mode 100644 index 24304d19b..000000000 --- a/tests/synthesizer/test_eleven_labs.py +++ /dev/null @@ -1,51 +0,0 @@ -import asyncio -from pydantic import ValidationError -import pytest -from vocode.streaming.synthesizer.base_synthesizer import SynthesisResult -from vocode.streaming.synthesizer.eleven_labs_synthesizer import ElevenLabsSynthesizer -from vocode.streaming.models.synthesizer import ElevenLabsSynthesizerConfig -from aioresponses import aioresponses -from vocode.streaming.models.message import BaseMessage -from vocode.streaming.models.audio_encoding import AudioEncoding -from pydub import AudioSegment - - -async def assert_synthesis_result_valid(synthesizer: ElevenLabsSynthesizer): - response = await synthesizer.create_speech(BaseMessage(text="Hello, world!"), 1024) - assert isinstance(response, SynthesisResult) - assert response.chunk_generator is not None - audio = AudioSegment.empty() - async for chunk in response.chunk_generator: - audio += AudioSegment( - chunk.chunk, - frame_rate=synthesizer.synthesizer_config.sampling_rate, - sample_width=2, - channels=1, - ) - - -@pytest.mark.asyncio -async def test_with_api_key( - fixture_eleven_labs_synthesizer_with_api_key: ElevenLabsSynthesizer, - mock_eleven_labs_api: aioresponses, -): - await assert_synthesis_result_valid(await fixture_eleven_labs_synthesizer_with_api_key) - - -@pytest.mark.asyncio -async def test_with_wrong_api_key( - fixture_eleven_labs_synthesizer_wrong_api_key: ElevenLabsSynthesizer, - mock_eleven_labs_api: aioresponses, -): - with pytest.raises(Exception, match="ElevenLabs API returned 401 status code"): - await (await fixture_eleven_labs_synthesizer_wrong_api_key).create_speech( - BaseMessage(text="Hello, world!"), 1024 - ) - - -@pytest.mark.asyncio -async def test_with_env_api_key( - fixture_eleven_labs_synthesizer_env_api_key: ElevenLabsSynthesizer, - mock_eleven_labs_api: aioresponses, -): - await assert_synthesis_result_valid(await fixture_eleven_labs_synthesizer_env_api_key) diff --git a/tests/synthesizer/test_play_ht.py b/tests/synthesizer/test_play_ht.py deleted file mode 100644 index 59b78cfeb..000000000 --- a/tests/synthesizer/test_play_ht.py +++ /dev/null @@ -1,61 +0,0 @@ -import asyncio - -from aioresponses import aioresponses -from pydub import AudioSegment -import pytest - -from vocode.streaming.models.message import BaseMessage -from vocode.streaming.synthesizer.base_synthesizer import SynthesisResult -from vocode.streaming.synthesizer.play_ht_synthesizer import PlayHtSynthesizer - - -async def assert_synthesis_result_valid(synthesizer: PlayHtSynthesizer): - response = await synthesizer.create_speech(BaseMessage(text="Hello, world!"), 1024) - assert isinstance(response, SynthesisResult) - assert response.chunk_generator is not None - audio = AudioSegment.empty() - async for chunk in response.chunk_generator: - audio += AudioSegment( - chunk.chunk, - frame_rate=synthesizer.synthesizer_config.sampling_rate, - sample_width=2, - channels=1, - ) - - -@pytest.mark.asyncio -async def test_with_api_key( - fixture_play_ht_synthesizer_with_api_key: PlayHtSynthesizer, - mock_play_ht_api: aioresponses, -): - await assert_synthesis_result_valid(await fixture_play_ht_synthesizer_with_api_key) - - -@pytest.mark.asyncio -async def test_with_wrong_api_key( - fixture_play_ht_synthesizer_wrong_api_key: PlayHtSynthesizer, - mock_play_ht_api: aioresponses, -): - with pytest.raises(Exception, match="Play.ht API error status code 401"): - await (await fixture_play_ht_synthesizer_wrong_api_key).create_speech( - BaseMessage(text="Hello, world!"), 1024 - ) - -@pytest.mark.asyncio -async def test_with_wrong_user_id( - fixture_play_ht_synthesizer_wrong_user_id: PlayHtSynthesizer, - mock_play_ht_api: aioresponses, -): - with pytest.raises(Exception, match="Play.ht API error status code 401"): - await (await fixture_play_ht_synthesizer_wrong_user_id).create_speech( - BaseMessage(text="Hello, world!"), 1024 - ) - - - -@pytest.mark.asyncio -async def test_with_env_api_key( - fixture_play_ht_synthesizer_env_api_key: PlayHtSynthesizer, - mock_play_ht_api: aioresponses, -): - await assert_synthesis_result_valid(await fixture_play_ht_synthesizer_env_api_key) diff --git a/vocode/__init__.py b/vocode/__init__.py index b2c8af7b0..eca391cb8 100644 --- a/vocode/__init__.py +++ b/vocode/__init__.py @@ -1,7 +1,65 @@ import os +from contextvars import ContextVar, Token +from typing import Any +from uuid import UUID +import sentry_sdk +from loguru import logger environment = {} +logger.disable("vocode") + + +class ContextWrapper: + """Context Variable Wrapper.""" + + _instances: list = [] + + def __init__(self, value: ContextVar) -> None: + self.__value: ContextVar = value + self.__token: Token + ContextWrapper._instances.append(self) + + def set(self, value: Any) -> Token: + """Set a context variable.""" + self.__token = self.__value.set(value) + if isinstance(value, str): + sentry_sdk.set_tag(self.__value.name, value) + if isinstance(value, UUID): + sentry_sdk.set_tag(self.__value.name, str(value)) + + return self.__token + + def reset(self, token: Token | None = None) -> None: + """Reset a context variable.""" + if not hasattr(self, "__token"): + return + + if not token: + token = self.__token + self.__value.reset(token) + return + + def __module__(self) -> Any: # type: ignore + return self.__value.get() + + @property + def value(self) -> Any: + """Gets the value of a context variable.""" + return self.__value.get() + + @classmethod + def serialize_instances(cls) -> dict: + """Gathers all instances of ContextWrapper.""" + instances = {} + for instance in cls._instances: + value = instance.__value.get() + if isinstance(value, UUID): + value = str(value) + + if isinstance(value, str): + instances[instance.__value.name] = value + return instances def setenv(**kwargs): @@ -15,3 +73,10 @@ def getenv(key, default=None): api_key = getenv("VOCODE_API_KEY") base_url = getenv("VOCODE_BASE_URL", "api.vocode.dev") + + +conversation_id: ContextWrapper = ContextWrapper( + ContextVar("conversation_id", default=None), +) +sentry_span_tags: ContextWrapper = ContextWrapper(ContextVar("sentry_span_tags", default=None)) +get_serialized_ctx_wrappers = ContextWrapper.serialize_instances diff --git a/vocode/helpers.py b/vocode/helpers.py index ac95014ff..c7088f64d 100644 --- a/vocode/helpers.py +++ b/vocode/helpers.py @@ -1,31 +1,27 @@ -from typing import List, Optional, Tuple, Union import typing +from typing import List, Optional, Tuple, Union + import sounddevice as sd +from loguru import logger + from vocode.streaming.input_device.microphone_input import ( MicrophoneInput as StreamingMicrophoneInput, ) from vocode.streaming.output_device.blocking_speaker_output import ( BlockingSpeakerOutput as BlockingStreamingSpeakerOutput, ) -from vocode.streaming.output_device.speaker_output import ( - SpeakerOutput as StreamingSpeakerOutput, -) +from vocode.streaming.output_device.speaker_output import SpeakerOutput as StreamingSpeakerOutput from vocode.turn_based.input_device.microphone_input import ( MicrophoneInput as TurnBasedMicrophoneInput, ) -from vocode.turn_based.output_device.speaker_output import ( - SpeakerOutput as TurnBasedSpeakerOutput, -) -import logging +from vocode.turn_based.output_device.speaker_output import SpeakerOutput as TurnBasedSpeakerOutput def _get_device_prompt(device_infos: List[dict]) -> str: return """Please select a device: {} Choice: """.format( - "\n".join( - f"{index}: {device['name']}" for index, device in enumerate(device_infos) - ) + "\n".join(f"{index}: {device['name']}" for index, device in enumerate(device_infos)) ) @@ -36,7 +32,6 @@ def create_streaming_microphone_input_and_speaker_output( mic_sampling_rate=None, speaker_sampling_rate=None, use_blocking_speaker_output=False, - logger: Optional[logging.Logger] = None, ): return _create_microphone_input_and_speaker_output( microphone_class=StreamingMicrophoneInput, @@ -50,7 +45,6 @@ def create_streaming_microphone_input_and_speaker_output( output_device_name=output_device_name, mic_sampling_rate=mic_sampling_rate, speaker_sampling_rate=speaker_sampling_rate, - logger=logger, ) @@ -60,7 +54,6 @@ def create_turn_based_microphone_input_and_speaker_output( output_device_name: Optional[str] = None, mic_sampling_rate=None, speaker_sampling_rate=None, - logger: Optional[logging.Logger] = None, ): return _create_microphone_input_and_speaker_output( microphone_class=TurnBasedMicrophoneInput, @@ -70,14 +63,11 @@ def create_turn_based_microphone_input_and_speaker_output( output_device_name=output_device_name, mic_sampling_rate=mic_sampling_rate, speaker_sampling_rate=speaker_sampling_rate, - logger=logger, ) def _create_microphone_input_and_speaker_output( - microphone_class: typing.Type[ - Union[StreamingMicrophoneInput, TurnBasedMicrophoneInput] - ], + microphone_class: typing.Type[Union[StreamingMicrophoneInput, TurnBasedMicrophoneInput]], speaker_class: typing.Type[ Union[ StreamingSpeakerOutput, @@ -90,7 +80,6 @@ def _create_microphone_input_and_speaker_output( output_device_name: Optional[str], mic_sampling_rate=None, speaker_sampling_rate=None, - logger: Optional[logging.Logger] = None, ) -> Union[ Tuple[ StreamingMicrophoneInput, @@ -111,42 +100,32 @@ def _create_microphone_input_and_speaker_output( output_device_info = sd.query_devices(kind="output") else: if input_device_name is not None: - input_device_info = _find_device_with_name( - input_device_infos, input_device_name - ) + input_device_info = _find_device_with_name(input_device_infos, input_device_name) else: input_device_info = input_device_infos[ int(input(_get_device_prompt(input_device_infos))) ] if output_device_name is not None: - output_device_info = _find_device_with_name( - output_device_infos, output_device_name - ) + output_device_info = _find_device_with_name(output_device_infos, output_device_name) else: output_device_info = output_device_infos[ int(input(_get_device_prompt(output_device_infos))) ] if logger is not None: - logger.info("Using microphone input device: %s", input_device_info["name"]) + logger.info(f"Using microphone input device: {input_device_info['name']}") - microphone_input = microphone_class( - input_device_info, sampling_rate=mic_sampling_rate - ) + microphone_input = microphone_class(input_device_info, sampling_rate=mic_sampling_rate) if logger is not None: - logger.info("Using speaker output device: %s", output_device_info["name"]) + logger.info(f"Using speaker output device: {output_device_info['name']}") - speaker_output = speaker_class( - output_device_info, sampling_rate=speaker_sampling_rate - ) + speaker_output = speaker_class(output_device_info, sampling_rate=speaker_sampling_rate) return microphone_input, speaker_output # type: ignore def _find_device_with_name(device_infos: List[dict], name: str) -> dict: try: - return next( - filter(lambda device_info: name == device_info["name"], device_infos) - ) + return next(filter(lambda device_info: name == device_info["name"], device_infos)) except StopIteration: raise Exception("Could not find device with name: {}".format(name)) diff --git a/vocode/logging.py b/vocode/logging.py new file mode 100644 index 000000000..b33ba4e31 --- /dev/null +++ b/vocode/logging.py @@ -0,0 +1,185 @@ +import json +import logging +import sys + +from loguru import logger +from loguru._handler import Handler + +from vocode import get_serialized_ctx_wrappers + + +def _patched_serialize_record(text: str, record: dict) -> str: + """ + This function takes a text string and a record dictionary as input and returns a serialized + string representation of the record. + + The record dictionary is expected to contain various keys related to logging information such as + 'level', 'time', 'elapsed', 'exception', 'extra', 'file', 'function', 'line', 'message', + 'module', 'name', 'process', 'thread'. Each key's value is processed and added to a new + dictionary 'serializable'. + + If the 'exception' key in the record is not None, it is further processed to extract 'type', + 'value', and 'traceback' information. + + The 'serializable' dictionary is then converted to a JSON string using json.dumps. The 'default' + parameter is set to str to convert any non-serializable types to string. The 'ensure_ascii' + parameter is set to False so that the function can output non-ASCII characters as they are. + + The function finally returns the serialized string with a newline character appended at the end. + + Args: + text (str): A text string. record (dict): A dictionary containing logging information. + + Returns: + str: A serialized string representation of the record dictionary. + """ + exception = record["exception"] + + if exception is not None: + exception = { + "type": None if exception.type is None else exception.type.__name__, + "value": exception.value, + "traceback": bool(exception.traceback), + } + + serializable = { + "severity": record["level"].name, + "text": text, + "timestamp": record["time"].timestamp(), + "elapsed": { + "repr": record["elapsed"], + "seconds": record["elapsed"].total_seconds(), + }, + "exception": exception, + "ctx": get_serialized_ctx_wrappers(), + "extra": record["extra"], + "file": {"name": record["file"].name, "path": record["file"].path}, + "function": record["function"], + "level": { + "icon": record["level"].icon, + "name": record["level"].name, + "no": record["level"].no, + }, + "line": record["line"], + "message": record["message"], + "module": record["module"], + "name": record["name"], + "process": {"id": record["process"].id, "name": record["process"].name}, + "thread": {"id": record["thread"].id, "name": record["thread"].name}, + "time": {"repr": record["time"], "timestamp": record["time"].timestamp()}, + } + + return json.dumps(serializable, default=str, ensure_ascii=False) + "\n" + + +Handler._serialize_record = staticmethod(_patched_serialize_record) # type: ignore + + +class InterceptHandler(logging.Handler): + """ + Default handler from examples in loguru documentation. + + This handler intercepts all log requests and + passes them to loguru. + + For more info see: + https://loguru.readthedocs.io/en/stable/overview.html#entirely-compatible-with-standard-logging + """ + + def emit(self, record: logging.LogRecord) -> None: # pragma: no cover + """ + Propagates logs to loguru. + + :param record: record to log. + """ + try: + level: str | int = logger.level(record.levelname).name + except ValueError: + level = record.levelno + + # Find caller from where originated the logged message + frame, depth = logging.currentframe(), 2 + while ( + frame.f_code.co_filename == logging.__file__ + or frame.f_code.co_filename == __file__ + or "sentry_sdk/integrations" in frame.f_code.co_filename + ): + frame = frame.f_back # type: ignore + depth += 1 + logger.opt(depth=depth, exception=record.exc_info).log( + level, + record.getMessage(), + ) + + +def configure_intercepter() -> None: + """ + Configures the logging system to intercept log messages. + + This function sets up an InterceptHandler instance as the main handler for the root logger. + It sets the logging level to INFO, meaning that all messages with severity INFO and above will be handled. + + It then iterates over all the loggers in the logging system. If a logger's name starts with "uvicorn.", + it removes all handlers from that logger. This is done to prevent uvicorn's default logging configuration + from interfering with our custom configuration. + + Finally, it sets the InterceptHandler instance as the sole handler for the "uvicorn" and "uvicorn.access" loggers. + This ensures that all log messages from uvicorn and its access logger are intercepted by our custom handler. + """ + intercept_handler = InterceptHandler() + logging.basicConfig(handlers=[intercept_handler], level=logging.INFO) + + for logger_name in logging.root.manager.loggerDict: + if logger_name.startswith("uvicorn."): + logging.getLogger(logger_name).handlers = [] + + logging.getLogger("uvicorn").handlers = [intercept_handler] + logging.getLogger("uvicorn.access").handlers = [intercept_handler] + + +def configure_pretty_logging() -> None: + """ + Configures the logging system to output pretty logs. + + This function enables the 'vocode' logger, sets up an intercept handler to + capture logs from the standard logging module, removes all existing handlers + from the 'loguru' logger, and adds a new handler that outputs to stdout with + pretty formatting (colored, not serialized, no backtrace or diagnosis information). + """ + logger.enable("vocode") + + configure_intercepter() + + logger.remove() + logger.add( + sys.stdout, + level=logging.DEBUG, + backtrace=False, + diagnose=False, + serialize=False, + colorize=True, + ) + + +def configure_json_logging() -> None: + """ + Configures the logging system to output logs in JSON format. + + This function enables the 'vocode' logger, sets up an intercept handler to + capture logs from the standard logging module, removes all existing handlers + from the 'loguru' logger, and adds a new handler that outputs to stdout with + JSON formatting (serialized, no backtrace or diagnosis information). + """ + logger.enable("vocode") + + configure_intercepter() + + logger.remove() + logger.add( + sys.stdout, + format="{message}", + level=logging.DEBUG, + backtrace=False, + diagnose=False, + serialize=True, + ) diff --git a/vocode/streaming/action/abstract_factory.py b/vocode/streaming/action/abstract_factory.py new file mode 100644 index 000000000..7e7ace050 --- /dev/null +++ b/vocode/streaming/action/abstract_factory.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod + +from vocode.streaming.action.base_action import BaseAction +from vocode.streaming.models.actions import ActionConfig + + +class AbstractActionFactory(ABC): + @abstractmethod + def create_action(self, action_config: ActionConfig) -> BaseAction: + pass diff --git a/vocode/streaming/action/utils.py b/vocode/streaming/action/action_utils.py similarity index 100% rename from vocode/streaming/action/utils.py rename to vocode/streaming/action/action_utils.py diff --git a/vocode/streaming/action/base_action.py b/vocode/streaming/action/base_action.py index 2ba801227..e1e07f028 100644 --- a/vocode/streaming/action/base_action.py +++ b/vocode/streaming/action/base_action.py @@ -1,30 +1,34 @@ import asyncio -from typing import Any, Dict, Generic, Optional, Type, TypeVar, TYPE_CHECKING -from vocode.streaming.action.utils import exclude_keys_recursive +from typing import TYPE_CHECKING, Any, Dict, Generic, List, Literal, Optional, Type, TypeVar + +import jsonschema +from jsonschema import Draft202012Validator as SchemaValidator + +from vocode.streaming.action.action_utils import exclude_keys_recursive from vocode.streaming.models.actions import ( ActionConfig, ActionInput, ActionOutput, - ActionType, ParametersType, ResponseType, ) if TYPE_CHECKING: - from vocode.streaming.utils.state_manager import ConversationStateManager + from vocode.streaming.utils.state_manager import AbstractConversationStateManager ActionConfigType = TypeVar("ActionConfigType", bound=ActionConfig) -class BaseAction(Generic[ActionConfigType, ParametersType, ResponseType]): +class BaseAction(Generic[ActionConfigType, ParametersType, ResponseType]): # type: ignore description: str = "" def __init__( self, action_config: ActionConfigType, - should_respond: bool = False, + should_respond: Literal["always", "sometimes", "never"] = "never", quiet: bool = False, is_interruptible: bool = True, + **kwargs, ): self.action_config = action_config self.should_respond = should_respond @@ -32,13 +36,11 @@ def __init__( self.is_interruptible = is_interruptible def attach_conversation_state_manager( - self, conversation_state_manager: "ConversationStateManager" + self, conversation_state_manager: "AbstractConversationStateManager" ): self.conversation_state_manager = conversation_state_manager - async def run( - self, action_input: ActionInput[ParametersType] - ) -> ActionOutput[ResponseType]: + async def run(self, action_input: ActionInput[ParametersType]) -> ActionOutput[ResponseType]: raise NotImplementedError @property @@ -49,23 +51,35 @@ def parameters_type(self) -> Type[ParametersType]: def response_type(self) -> Type[ResponseType]: raise NotImplementedError + def get_parameters_schema(self) -> Dict[str, Any]: + return self.parameters_type.schema() + + def get_function_name(self) -> str: + return self.action_config.type + def get_openai_function(self): - parameters_schema = self.parameters_type.schema() + parameters_schema = self.get_parameters_schema() parameters_schema = exclude_keys_recursive(parameters_schema, {"title"}) - if self.should_respond: - parameters_schema["properties"][ - "user_message" - ] = self._user_message_param_info() - required = parameters_schema.get("required", []) - required.append("user_message") - parameters_schema["required"] = required + if self.should_respond != "never": + parameters_schema["properties"]["user_message"] = self._user_message_param_info() + if self.should_respond == "always": + required: List[str] = parameters_schema.get("required", []) + required.append("user_message") + parameters_schema["required"] = required + try: + SchemaValidator.check_schema(parameters_schema) + except jsonschema.exceptions.SchemaError as e: + raise ValueError(f"Invalid parameters schema for {self.action_config.type}: {e}") from e return { - "name": self.action_config.type, + "name": self.get_function_name(), "description": self.description, "parameters": parameters_schema, } + def create_action_params(self, params: Dict[str, Any]) -> ParametersType: + return self.parameters_type(**params) + def create_action_input( self, conversation_id: str, @@ -77,14 +91,14 @@ def create_action_input( return ActionInput( action_config=self.action_config, conversation_id=conversation_id, - params=self.parameters_type(**params), + params=self.create_action_params(params), user_message_tracker=user_message_tracker, ) def _user_message_param_info(self): return { "type": "string", - "description": """A message to reply to the user with BEFORE we make the function call. + "description": """A message to reply to the user with BEFORE we make the function call. Essentially a live response informing them that the function is about to happen. Eg Let me check the weather in San Francisco CA for you """, } diff --git a/vocode/streaming/action/default_factory.py b/vocode/streaming/action/default_factory.py new file mode 100644 index 000000000..227ed56c4 --- /dev/null +++ b/vocode/streaming/action/default_factory.py @@ -0,0 +1,47 @@ +from typing import Dict, Sequence, Type + +from vocode.streaming.action.abstract_factory import AbstractActionFactory +from vocode.streaming.action.base_action import BaseAction +from vocode.streaming.action.dtmf import TwilioDTMF, VonageDTMF +from vocode.streaming.action.end_conversation import EndConversation +from vocode.streaming.action.execute_external_action import ExecuteExternalAction +from vocode.streaming.action.phone_call_action import ( + TwilioPhoneConversationAction, + VonagePhoneConversationAction, +) +from vocode.streaming.action.record_email import RecordEmail +from vocode.streaming.action.transfer_call import TwilioTransferCall, VonageTransferCall +from vocode.streaming.action.wait import Wait +from vocode.streaming.models.actions import ActionConfig, ActionType + +CONVERSATION_ACTIONS: Dict[ActionType, Type[BaseAction]] = { + ActionType.END_CONVERSATION: EndConversation, + ActionType.RECORD_EMAIL: RecordEmail, + ActionType.WAIT: Wait, + ActionType.EXECUTE_EXTERNAL_ACTION: ExecuteExternalAction, +} + +VONAGE_ACTIONS: Dict[ActionType, Type[VonagePhoneConversationAction]] = { + ActionType.TRANSFER_CALL: VonageTransferCall, + ActionType.DTMF: VonageDTMF, +} + +TWILIO_ACTIONS: Dict[ActionType, Type[TwilioPhoneConversationAction]] = { + ActionType.TRANSFER_CALL: TwilioTransferCall, + ActionType.DTMF: TwilioDTMF, +} + + +class DefaultActionFactory(AbstractActionFactory): + def __init__(self, actions: Sequence[ActionConfig] | dict = {}): + + self.action_configs_dict = {action.type: action for action in actions} + self.actions = CONVERSATION_ACTIONS + + def create_action(self, action_config: ActionConfig): + if action_config.type not in self.action_configs_dict: + raise Exception("Action type not supported by Agent config.") + + action_class = self.actions[action_config.type] + + return action_class(action_config) diff --git a/vocode/streaming/action/dtmf.py b/vocode/streaming/action/dtmf.py new file mode 100644 index 000000000..392b8eef6 --- /dev/null +++ b/vocode/streaming/action/dtmf.py @@ -0,0 +1,83 @@ +from typing import Type + +from loguru import logger +from pydantic.v1 import BaseModel, Field + +from vocode.streaming.action.phone_call_action import ( + TwilioPhoneConversationAction, + VonagePhoneConversationAction, +) +from vocode.streaming.models.actions import ActionConfig as VocodeActionConfig +from vocode.streaming.models.actions import ActionInput, ActionOutput +from vocode.streaming.utils.state_manager import ( + TwilioPhoneConversationStateManager, + VonagePhoneConversationStateManager, +) + + +class DTMFParameters(BaseModel): + buttons: str = Field(..., description="The buttons to press.") + + +class DTMFResponse(BaseModel): + success: bool + + +class DTMFVocodeActionConfig(VocodeActionConfig, type="action_dtmf"): # type: ignore + def action_attempt_to_string(self, input: ActionInput) -> str: + assert isinstance(input.params, DTMFParameters) + return "Attempting to press numbers: " f"{list(input.params.buttons)}" + + def action_result_to_string(self, input: ActionInput, output: ActionOutput) -> str: + assert isinstance(input.params, DTMFParameters) + assert isinstance(output.response, DTMFResponse) + return f"Pressed numbers {list(input.params.buttons)} successfully" + + +FUNCTION_DESCRIPTION = "Presses a string numbers using DTMF tones." + + +class VonageDTMF( + VonagePhoneConversationAction[DTMFVocodeActionConfig, DTMFParameters, DTMFResponse] +): + description: str = FUNCTION_DESCRIPTION + parameters_type: Type[DTMFParameters] = DTMFParameters + response_type: Type[DTMFResponse] = DTMFResponse + conversation_state_manager: VonagePhoneConversationStateManager + + def __init__(self, action_config: DTMFVocodeActionConfig): + super().__init__(action_config, quiet=True) + + async def run(self, action_input: ActionInput[DTMFParameters]) -> ActionOutput[DTMFResponse]: + buttons = action_input.params.buttons + vonage_client = self.conversation_state_manager.create_vonage_client() + await vonage_client.send_dtmf( + vonage_uuid=self.get_vonage_uuid(action_input), digits=buttons + ) + + return ActionOutput( + action_type=action_input.action_config.type, + response=DTMFResponse(success=True), + ) + + +class TwilioDTMF( + TwilioPhoneConversationAction[DTMFVocodeActionConfig, DTMFParameters, DTMFResponse] +): + description: str = FUNCTION_DESCRIPTION + parameters_type: Type[DTMFParameters] = DTMFParameters + response_type: Type[DTMFResponse] = DTMFResponse + conversation_state_manager: TwilioPhoneConversationStateManager + + def __init__(self, action_config: DTMFVocodeActionConfig): + super().__init__( + action_config, + quiet=True, + ) + + async def run(self, action_input: ActionInput[DTMFParameters]) -> ActionOutput[DTMFResponse]: + logger.error("DTMF not yet supported with Twilio") + return ActionOutput( + action_type=action_input.action_config.type, + response=DTMFResponse(success=False), + ) diff --git a/vocode/streaming/action/end_conversation.py b/vocode/streaming/action/end_conversation.py new file mode 100644 index 000000000..7175ad846 --- /dev/null +++ b/vocode/streaming/action/end_conversation.py @@ -0,0 +1,89 @@ +from typing import Type + +from loguru import logger +from pydantic.v1 import BaseModel + +from vocode.streaming.action.base_action import BaseAction +from vocode.streaming.models.actions import ActionConfig as VocodeActionConfig +from vocode.streaming.models.actions import ActionInput, ActionOutput + +_END_CONVERSATION_ACTION_DESCRIPTION = """ +Ends the current conversation; use this when we should hang up. Use this +when: someone has indicated they expect the call to finish, and there are no further objectives +to complete. If the user says Goodbye or a different farewell phrase, this indicates that we should +hang up. Example farewell phrases: goodbye, so long, see you, later, take care, etc. People will +sometimes say a farewell phrase at the end of a longer sentence, so make sure to hang up then +as well. Example: \"This sounds great! Talk to you soon.\"""" + + +class EndConversationParameters(BaseModel): + pass + + +class EndConversationResponse(BaseModel): + success: bool + + +class EndConversationVocodeActionConfig( + VocodeActionConfig, type="action_end_conversation" # type: ignore +): + def action_attempt_to_string(self, input: ActionInput) -> str: + assert isinstance(input.params, EndConversationParameters) + return "Attempting to end conversation" + + def action_result_to_string(self, input: ActionInput, output: ActionOutput) -> str: + assert isinstance(output.response, EndConversationResponse) + if output.response.success: + action_description = "Successfully ended conversation" + else: + action_description = "Did not end call because user interrupted" + return action_description + + +class EndConversation( + BaseAction[ + EndConversationVocodeActionConfig, + EndConversationParameters, + EndConversationResponse, + ] +): + description: str = _END_CONVERSATION_ACTION_DESCRIPTION + parameters_type: Type[EndConversationParameters] = EndConversationParameters + response_type: Type[EndConversationResponse] = EndConversationResponse + + def __init__( + self, + action_config: EndConversationVocodeActionConfig, + ): + super().__init__( + action_config, + quiet=True, + should_respond="sometimes", + is_interruptible=False, + ) + + async def _end_of_run_hook(self) -> None: + """This method is called at the end of the run method. It is optional but intended to be + overridden if needed.""" + pass + + async def run( + self, action_input: ActionInput[EndConversationParameters] + ) -> ActionOutput[EndConversationResponse]: + if action_input.user_message_tracker is not None: + await action_input.user_message_tracker.wait() + + if self.conversation_state_manager.transcript.was_last_message_interrupted(): + logger.info("Last bot message was interrupted") + return ActionOutput( + action_type=action_input.action_config.type, + response=EndConversationResponse(success=False), + ) + + await self.conversation_state_manager.terminate_conversation() + + await self._end_of_run_hook() + return ActionOutput( + action_type=action_input.action_config.type, + response=EndConversationResponse(success=True), + ) diff --git a/vocode/streaming/action/execute_external_action.py b/vocode/streaming/action/execute_external_action.py new file mode 100644 index 000000000..c689b206d --- /dev/null +++ b/vocode/streaming/action/execute_external_action.py @@ -0,0 +1,110 @@ +import json +from typing import Any, Dict, Optional, Type + +from pydantic.v1 import BaseModel + +from vocode.streaming.action.base_action import BaseAction +from vocode.streaming.action.external_actions_requester import ( + ExternalActionResponse, + ExternalActionsRequester, +) +from vocode.streaming.models.actions import ActionConfig as VocodeActionConfig +from vocode.streaming.models.actions import ActionInput, ActionOutput, ExternalActionProcessingMode +from vocode.streaming.models.message import BaseMessage + + +class ExecuteExternalActionVocodeActionConfig( + VocodeActionConfig, type="action_external" # type: ignore +): + processing_mode: ExternalActionProcessingMode + name: str + description: str + url: str + input_schema: str + speak_on_send: bool + speak_on_receive: bool + signature_secret: str + + +class ExecuteExternalActionParameters(BaseModel): + payload: Dict[str, Any] + + +class ExecuteExternalActionResponse(BaseModel): + success: bool + result: Optional[dict] + + +class ExecuteExternalAction( + BaseAction[ + ExecuteExternalActionVocodeActionConfig, + ExecuteExternalActionParameters, + ExecuteExternalActionResponse, + ] +): + parameters_type: Type[ExecuteExternalActionParameters] = ExecuteExternalActionParameters + response_type: Type[ExecuteExternalActionResponse] = ExecuteExternalActionResponse + + def __init__( + self, + action_config: ExecuteExternalActionVocodeActionConfig, + ): + self.description = action_config.description + super().__init__( + action_config, + quiet=not action_config.speak_on_receive, + should_respond="always" if action_config.speak_on_send else "never", + is_interruptible=False, + ) + self.external_actions_requester = ExternalActionsRequester(url=action_config.url) + + def _user_message_param_info(self): + return { + "type": "string", + "description": ( + "A message to reply to the user with BEFORE we make the function call." + "\nEssentially a live response informing them that the function is " + "about to happen." + ), + } + + def create_action_params(self, params: Dict[str, Any]) -> ExecuteExternalActionParameters: + return ExecuteExternalActionParameters(payload=params) + + def get_function_name(self) -> str: + return self.action_config.name + + def get_parameters_schema(self) -> Dict[str, Any]: + return json.loads(self.action_config.input_schema) + + async def send_external_action_request( + self, action_input: ActionInput[ExecuteExternalActionParameters] + ) -> ExternalActionResponse: + return await self.external_actions_requester.send_request( + payload=action_input.params.payload, + signature_secret=self.action_config.signature_secret, + ) + + async def run( + self, action_input: ActionInput[ExecuteExternalActionParameters] + ) -> ActionOutput[ExecuteExternalActionResponse]: + # TODO: this interruption handling needs to be refactored / DRYd + if self.should_respond and action_input.user_message_tracker is not None: + await action_input.user_message_tracker.wait() + + self.conversation_state_manager.mute_agent() + response = await self.send_external_action_request(action_input) + self.conversation_state_manager.unmute_agent() + + # TODO (EA): pass specific context based on error + return ActionOutput( + action_type=action_input.action_config.type, + response=ExecuteExternalActionResponse( + result=response.result if response else None, success=response.success + ), + canned_response=( + BaseMessage(text=response.agent_message) + if response and response.agent_message + else None + ), + ) diff --git a/vocode/streaming/action/external_actions_requester.py b/vocode/streaming/action/external_actions_requester.py new file mode 100644 index 000000000..ff82911bd --- /dev/null +++ b/vocode/streaming/action/external_actions_requester.py @@ -0,0 +1,134 @@ +import base64 +import hashlib +import hmac +import json +from typing import Any, Dict, Optional + +import httpx +from loguru import logger +from pydantic.v1 import BaseModel + + +class ExternalActionValueError(ValueError): + pass + + +class ExternalActionsErrorResponses: + client_error = ( + "There was an error with the information provided. " + "Please ask for clarification and try again." + ) + server_error = ( + "There was a server error with status " + "{status}: {text}. Please politely tell the user to try again later." + ) + input_error = ( + "There was an error with the information received from the service. " + "Please politely tell the user to try again later." + "\nThe error was {error}" + ) + unauthorized = ( + "There was an error with the authentication for the service. " + "Please politely tell the user to try again later." + ) + forbidden = ( + "There was an error with the authentication for the service. " + "Please politely tell the user to try again later." + ) + + +class ExternalActionResponse(BaseModel): + result: dict + success: bool + agent_message: Optional[str] = None + + +class ExternalActionsRequester: + def __init__(self, url: str) -> None: + self.url = url + + async def send_request( + self, + payload: Dict[str, Any], + signature_secret: str, + additional_payload_values: Dict[str, Any] = {}, + ) -> ExternalActionResponse: + encoded_payload = json.dumps({"payload": payload} | additional_payload_values).encode( + "utf-8" + ) + + headers = { + "Accept": "application/json", + "Content-Type": "application/json", + "x-vocode-signature": self._encode_payload(encoded_payload, signature_secret), + } + + transport = httpx.AsyncHTTPTransport(retries=2) + async with httpx.AsyncClient( + headers=headers, + transport=transport, + timeout=10, + ) as client: + try: + response = await client.post( + self.url, + content=encoded_payload, + ) + response.raise_for_status() + data = response.json() + return self._validate_response(data) + except httpx.HTTPStatusError as e: + logger.error(f"[External Actions] Request failed: {e}") + if e.response.status_code == 401: + return ExternalActionResponse( + result={"info": ExternalActionsErrorResponses.unauthorized}, + success=False, + ) + elif e.response.status_code == 403: + return ExternalActionResponse( + result={"info": ExternalActionsErrorResponses.forbidden}, + success=False, + ) + if 400 <= e.response.status_code < 500: + return ExternalActionResponse( + result={"info": ExternalActionsErrorResponses.client_error}, + success=False, + ) + elif e.response.status_code >= 500: + return ExternalActionResponse( + result={ + "info": ExternalActionsErrorResponses.server_error.format( + status=e.response.status_code, text=e.response.text + ) + }, + success=False, + ) + else: + raise e + except ExternalActionValueError as e: + return ExternalActionResponse( + result={"info": ExternalActionsErrorResponses.input_error.format(error=str(e))}, + success=False, + ) + + def _encode_payload(self, payload: bytes, signature_secret: str) -> str: + signature_as_bytes = base64.b64decode(signature_secret) + digest = hmac.new(signature_as_bytes, payload, hashlib.sha256).digest() + return base64.b64encode(digest).decode() + + def _validate_response(self, response: Dict[str, Any]) -> ExternalActionResponse: + if "result" not in response: + raise ExternalActionValueError("Invalid response format: missing 'result'") + if not isinstance(response["result"], dict): + raise ExternalActionValueError( + "Invalid response format: 'agent_message' must be a key value map" + ) + if "agent_message" in response and not isinstance(response["agent_message"], str): + raise ExternalActionValueError( + "Invalid response format: 'agent_message' must be a string" + ) + return ExternalActionResponse( + result=response["result"], + agent_message=response.get("agent_message"), + success=True, + ) diff --git a/vocode/streaming/action/factory.py b/vocode/streaming/action/factory.py deleted file mode 100644 index c5398a32d..000000000 --- a/vocode/streaming/action/factory.py +++ /dev/null @@ -1,17 +0,0 @@ -from vocode.streaming.action.base_action import BaseAction -from vocode.streaming.action.nylas_send_email import ( - NylasSendEmail, - NylasSendEmailActionConfig, -) -from vocode.streaming.models.actions import ActionConfig -from vocode.streaming.action.transfer_call import TransferCall, TransferCallActionConfig - - -class ActionFactory: - def create_action(self, action_config: ActionConfig) -> BaseAction: - if isinstance(action_config, NylasSendEmailActionConfig): - return NylasSendEmail(action_config, should_respond=True) - elif isinstance(action_config, TransferCallActionConfig): - return TransferCall(action_config) - else: - raise Exception("Invalid action type") diff --git a/vocode/streaming/action/nylas_send_email.py b/vocode/streaming/action/nylas_send_email.py deleted file mode 100644 index cec889c18..000000000 --- a/vocode/streaming/action/nylas_send_email.py +++ /dev/null @@ -1,62 +0,0 @@ -from typing import Optional, Type -from pydantic.v1 import BaseModel, Field -import os -from vocode.streaming.action.base_action import BaseAction -from vocode.streaming.models.actions import ( - ActionConfig, - ActionInput, - ActionOutput, - ActionType, -) - - -class NylasSendEmailActionConfig(ActionConfig, type=ActionType.NYLAS_SEND_EMAIL): - pass - - -class NylasSendEmailParameters(BaseModel): - recipient_email: str = Field(..., description="The email address of the recipient.") - body: str = Field(..., description="The body of the email.") - subject: Optional[str] = Field(None, description="The subject of the email.") - - -class NylasSendEmailResponse(BaseModel): - success: bool - - -class NylasSendEmail( - BaseAction[ - NylasSendEmailActionConfig, NylasSendEmailParameters, NylasSendEmailResponse - ] -): - description: str = "Sends an email using Nylas API." - parameters_type: Type[NylasSendEmailParameters] = NylasSendEmailParameters - response_type: Type[NylasSendEmailResponse] = NylasSendEmailResponse - - async def run( - self, action_input: ActionInput[NylasSendEmailParameters] - ) -> ActionOutput[NylasSendEmailResponse]: - from nylas import APIClient - - # Initialize the Nylas client - nylas = APIClient( - client_id=os.getenv("NYLAS_CLIENT_ID"), - client_secret=os.getenv("NYLAS_CLIENT_SECRET"), - access_token=os.getenv("NYLAS_ACCESS_TOKEN"), - ) - - # Create the email draft - draft = nylas.drafts.create() - draft.body = action_input.params.body - - email_subject = action_input.params.subject - draft.subject = email_subject if email_subject else "Email from Vocode" - draft.to = [{"email": action_input.params.recipient_email.strip()}] - - # Send the email - draft.send() - - return ActionOutput( - action_type=self.action_config.type, - response=NylasSendEmailResponse(success=True), - ) diff --git a/vocode/streaming/action/phone_call_action.py b/vocode/streaming/action/phone_call_action.py index 3b502f812..f780413fc 100644 --- a/vocode/streaming/action/phone_call_action.py +++ b/vocode/streaming/action/phone_call_action.py @@ -1,27 +1,31 @@ import asyncio -from typing import Dict, Any, Optional +from typing import Any, Dict, Optional + from vocode.streaming.action.base_action import ActionConfigType, BaseAction from vocode.streaming.models.actions import ( ActionInput, - ActionOutput, ParametersType, ResponseType, - TwilioPhoneCallActionInput, - VonagePhoneCallActionInput, + TwilioPhoneConversationActionInput, + VonagePhoneConversationActionInput, +) +from vocode.streaming.utils.state_manager import ( + TwilioPhoneConversationStateManager, + VonagePhoneConversationStateManager, ) -class VonagePhoneCallAction(BaseAction[ActionConfigType, ParametersType, ResponseType]): - def create_phone_call_action_input( +class VonagePhoneConversationAction(BaseAction[ActionConfigType, ParametersType, ResponseType]): + def create_phone_conversation_action_input( self, conversation_id: str, params: Dict[str, Any], vonage_uuid: str, user_message_tracker: Optional[asyncio.Event] = None, - ) -> VonagePhoneCallActionInput[ParametersType]: + ) -> VonagePhoneConversationActionInput[ParametersType]: if "user_message" in params: del params["user_message"] - return VonagePhoneCallActionInput( + return VonagePhoneConversationActionInput( action_config=self.action_config, conversation_id=conversation_id, params=self.parameters_type(**params), @@ -30,21 +34,25 @@ def create_phone_call_action_input( ) def get_vonage_uuid(self, action_input: ActionInput[ParametersType]) -> str: - assert isinstance(action_input, VonagePhoneCallActionInput) + assert isinstance(action_input, VonagePhoneConversationActionInput) return action_input.vonage_uuid + def attach_conversation_state_manager(self, conversation_state_manager: Any): + assert isinstance(conversation_state_manager, VonagePhoneConversationStateManager) + self.conversation_state_manager = conversation_state_manager -class TwilioPhoneCallAction(BaseAction[ActionConfigType, ParametersType, ResponseType]): - def create_phone_call_action_input( + +class TwilioPhoneConversationAction(BaseAction[ActionConfigType, ParametersType, ResponseType]): + def create_phone_conversation_action_input( self, conversation_id: str, params: Dict[str, Any], twilio_sid: str, user_message_tracker: Optional[asyncio.Event] = None, - ) -> TwilioPhoneCallActionInput[ParametersType]: + ) -> TwilioPhoneConversationActionInput[ParametersType]: if "user_message" in params: del params["user_message"] - return TwilioPhoneCallActionInput( + return TwilioPhoneConversationActionInput( action_config=self.action_config, conversation_id=conversation_id, params=self.parameters_type(**params), @@ -53,5 +61,9 @@ def create_phone_call_action_input( ) def get_twilio_sid(self, action_input: ActionInput[ParametersType]) -> str: - assert isinstance(action_input, TwilioPhoneCallActionInput) + assert isinstance(action_input, TwilioPhoneConversationActionInput) return action_input.twilio_sid + + def attach_conversation_state_manager(self, conversation_state_manager: Any): + assert isinstance(conversation_state_manager, TwilioPhoneConversationStateManager) + self.conversation_state_manager = conversation_state_manager diff --git a/vocode/streaming/action/record_email.py b/vocode/streaming/action/record_email.py new file mode 100644 index 000000000..98619ef12 --- /dev/null +++ b/vocode/streaming/action/record_email.py @@ -0,0 +1,76 @@ +import re +from typing import Optional, Type + +from pydantic.v1 import BaseModel, Field + +from vocode.streaming.action.base_action import BaseAction +from vocode.streaming.models.actions import ActionConfig, ActionInput, ActionOutput + +EMAIL_REGEX = r"^(?!\.)(?!.*\.\.)[a-zA-Z0-9._%+-]+(? kian@gmail.com + ajay at vocode dot dev -> ajay@vocode.dev + + This function will do extra validation. + """ + parameters_type: Type[RecordEmailParameters] = RecordEmailParameters + response_type: Type[RecordEmailResponse] = RecordEmailResponse + + def __init__( + self, + action_config: RecordEmailVocodeActionConfig, + ): + super().__init__( + action_config, + quiet=False, + should_respond="never", + ) + + def _validate_email(self, email: str) -> bool: + return bool(re.match(EMAIL_REGEX, email)) + + async def run( + self, action_input: ActionInput[RecordEmailParameters] + ) -> ActionOutput[RecordEmailResponse]: + value = action_input.params.formatted_value + + success = self._validate_email(value) + + return ActionOutput( + action_type=action_input.action_config.type, + response=RecordEmailResponse(success=success), + ) diff --git a/vocode/streaming/action/transfer_call.py b/vocode/streaming/action/transfer_call.py index e9aff0252..f78fcea65 100644 --- a/vocode/streaming/action/transfer_call.py +++ b/vocode/streaming/action/transfer_call.py @@ -1,21 +1,20 @@ -import os -import aiohttp - -from aiohttp import BasicAuth -from typing import Type -from pydantic.v1 import BaseModel, Field - -from vocode.streaming.action.phone_call_action import TwilioPhoneCallAction -from vocode.streaming.models.actions import ( - ActionConfig, - ActionInput, - ActionOutput, - ActionType, -) +from typing import Literal, Type +from loguru import logger +from pydantic.v1 import BaseModel -class TransferCallActionConfig(ActionConfig, type=ActionType.TRANSFER_CALL): - to_phone: str +from vocode.streaming.action.phone_call_action import ( + TwilioPhoneConversationAction, + VonagePhoneConversationAction, +) +from vocode.streaming.models.actions import ActionConfig as VocodeActionConfig +from vocode.streaming.models.actions import ActionInput, ActionOutput +from vocode.streaming.utils.async_requester import AsyncRequestor +from vocode.streaming.utils.phone_numbers import sanitize_phone_number +from vocode.streaming.utils.state_manager import ( + TwilioPhoneConversationStateManager, + VonagePhoneConversationStateManager, +) class TransferCallParameters(BaseModel): @@ -23,40 +22,68 @@ class TransferCallParameters(BaseModel): class TransferCallResponse(BaseModel): - status: str = Field("success", description="status of the transfer") + success: bool + + +class TransferCallVocodeActionConfig(VocodeActionConfig, type="action_transfer_call"): # type: ignore + phone_number: str + + def action_attempt_to_string(self, input: ActionInput) -> str: + assert isinstance(input.params, TransferCallParameters) + return f"Attempting to transfer call to {self.phone_number}" + + def action_result_to_string(self, input: ActionInput, output: ActionOutput) -> str: + assert isinstance(output.response, TransferCallResponse) + if output.response.success: + action_description = "Successfully transferred call" + else: + action_description = "Did not transfer call because user interrupted" + return action_description + +FUNCTION_DESCRIPTION = "Transfers the call to a new number. This is never used while on hold." +QUIET = True +IS_INTERRUPTIBLE = True +SHOULD_RESPOND: Literal["always"] = "always" -class TransferCall( - TwilioPhoneCallAction[ - TransferCallActionConfig, TransferCallParameters, TransferCallResponse + +class TwilioTransferCall( + TwilioPhoneConversationAction[ + TransferCallVocodeActionConfig, TransferCallParameters, TransferCallResponse ] ): - description: str = ( - "transfers the call. use when you need to connect the active call to another phone line." - ) + description: str = FUNCTION_DESCRIPTION parameters_type: Type[TransferCallParameters] = TransferCallParameters response_type: Type[TransferCallResponse] = TransferCallResponse + conversation_state_manager: TwilioPhoneConversationStateManager + + def __init__( + self, + action_config: TransferCallVocodeActionConfig, + ): + super().__init__( + action_config, + quiet=QUIET, + is_interruptible=False, + should_respond=SHOULD_RESPOND, + ) - async def transfer_call(self, twilio_call_sid, to_phone): - twilio_account_sid = os.environ["TWILIO_ACCOUNT_SID"] - twilio_auth_token = os.environ["TWILIO_AUTH_TOKEN"] + async def transfer_call(self, twilio_call_sid: str, to_phone: str): + twilio_client = self.conversation_state_manager.create_twilio_client() - url = "https://api.twilio.com/2010-04-01/Accounts/{twilio_account_sid}/Calls/{twilio_auth_token}.json".format( - twilio_account_sid=twilio_account_sid, twilio_auth_token=twilio_call_sid + url = "https://api.twilio.com/2010-04-01/Accounts/{twilio_account_sid}/Calls/{twilio_call_sid}.json".format( + twilio_account_sid=twilio_client.get_telephony_config().account_sid, + twilio_call_sid=twilio_call_sid, ) - twiml_data = "{to_phone}".format( - to_phone=to_phone - ) + twiml_data = "{to_phone}".format(to_phone=to_phone) payload = {"Twiml": twiml_data} - auth = BasicAuth(twilio_account_sid, twilio_auth_token) - - async with aiohttp.ClientSession(auth=auth) as session: - async with session.post(url, data=payload) as response: + async with AsyncRequestor().get_session() as session: + async with session.post(url, data=payload, auth=twilio_client.auth) as response: if response.status != 200: - print(await response.text()) + logger.error(f"Failed to transfer call: {response.status} {response.reason}") raise Exception("failed to update call") else: return await response.json() @@ -66,9 +93,78 @@ async def run( ) -> ActionOutput[TransferCallResponse]: twilio_call_sid = self.get_twilio_sid(action_input) - await self.transfer_call(twilio_call_sid, self.action_config.to_phone) + sanitized_phone_number = sanitize_phone_number(self.action_config.phone_number) + + if action_input.user_message_tracker is not None: + await action_input.user_message_tracker.wait() + + logger.info("Finished waiting for user message tracker, now attempting to transfer call") + + if self.conversation_state_manager.transcript.was_last_message_interrupted(): + logger.info("Last bot message was interrupted, not transferring call") + return ActionOutput( + action_type=action_input.action_config.type, + response=TransferCallResponse(success=False), + ) + + await self.transfer_call(twilio_call_sid, sanitized_phone_number) + + return ActionOutput( + action_type=action_input.action_config.type, + response=TransferCallResponse(success=True), + ) + + +class VonageTransferCall( + VonagePhoneConversationAction[ + TransferCallVocodeActionConfig, TransferCallParameters, TransferCallResponse + ] +): + description: str = FUNCTION_DESCRIPTION + parameters_type: Type[TransferCallParameters] = TransferCallParameters + response_type: Type[TransferCallResponse] = TransferCallResponse + conversation_state_manager: VonagePhoneConversationStateManager + + def __init__(self, action_config: TransferCallVocodeActionConfig): + super().__init__( + action_config, + quiet=QUIET, + is_interruptible=IS_INTERRUPTIBLE, + should_respond=SHOULD_RESPOND, + ) + + async def run( + self, action_input: ActionInput[TransferCallParameters] + ) -> ActionOutput[TransferCallResponse]: + if action_input.user_message_tracker is not None: + await action_input.user_message_tracker.wait() + self.conversation_state_manager.mute_agent() + + sanitized_phone_number = sanitize_phone_number(self.action_config.phone_number) + + if self.conversation_state_manager.get_direction() == "outbound": + agent_phone_number = self.conversation_state_manager.get_from_phone() + else: + agent_phone_number = self.conversation_state_manager.get_to_phone() + + await self.conversation_state_manager.create_vonage_client().update_call( + vonage_uuid=self.get_vonage_uuid(action_input), + new_ncco=[ + { + "action": "connect", + "timeout": "45", + "from": agent_phone_number, + "endpoint": [ + { + "type": "phone", + "number": sanitized_phone_number, + } + ], + } + ], + ) return ActionOutput( action_type=action_input.action_config.type, - response=TransferCallResponse(status="success"), + response=TransferCallResponse(success=True), ) diff --git a/vocode/streaming/action/wait.py b/vocode/streaming/action/wait.py new file mode 100644 index 000000000..a70c6dbfa --- /dev/null +++ b/vocode/streaming/action/wait.py @@ -0,0 +1,52 @@ +from typing import Type + +from pydantic.v1 import BaseModel + +from vocode.streaming.action.base_action import BaseAction +from vocode.streaming.models.actions import ActionConfig as VocodeActionConfig +from vocode.streaming.models.actions import ActionInput, ActionOutput + + +class WaitVocodeActionConfig(VocodeActionConfig, type="action_wait"): # type: ignore + pass + + +class WaitParameters(BaseModel): + pass + + +class WaitResponse(BaseModel): + success: bool + + +class Wait( + BaseAction[ + WaitVocodeActionConfig, + WaitParameters, + WaitResponse, + ] +): + description: str = ( + "Use this action to wait for the IVR to finish talking or to continue waiting on hold." + ) + parameters_type: Type[WaitParameters] = WaitParameters + response_type: Type[WaitResponse] = WaitResponse + + def __init__( + self, + action_config: WaitVocodeActionConfig, + ): + super().__init__( + action_config, + quiet=True, + should_respond="never", + ) + + async def run(self, action_input: ActionInput[WaitParameters]) -> ActionOutput[WaitResponse]: + if action_input.user_message_tracker is not None: + await action_input.user_message_tracker.wait() + + return ActionOutput( + action_type=action_input.action_config.type, + response=WaitResponse(success=True), + ) diff --git a/vocode/streaming/action/worker.py b/vocode/streaming/action/worker.py index 6ca876f6b..26c51b240 100644 --- a/vocode/streaming/action/worker.py +++ b/vocode/streaming/action/worker.py @@ -1,14 +1,16 @@ from __future__ import annotations import asyncio -from vocode.streaming.action.factory import ActionFactory + +from vocode.streaming.action.abstract_factory import AbstractActionFactory +from vocode.streaming.action.default_factory import DefaultActionFactory from vocode.streaming.agent.base_agent import ActionResultAgentInput, AgentInput from vocode.streaming.models.actions import ( ActionInput, - TwilioPhoneCallActionInput, - VonagePhoneCallActionInput, + TwilioPhoneConversationActionInput, + VonagePhoneConversationActionInput, ) -from vocode.streaming.utils.state_manager import ConversationStateManager +from vocode.streaming.utils.state_manager import AbstractConversationStateManager from vocode.streaming.utils.worker import ( InterruptibleEvent, InterruptibleEventFactory, @@ -19,10 +21,10 @@ class ActionsWorker(InterruptibleWorker): def __init__( self, + action_factory: AbstractActionFactory, input_queue: asyncio.Queue[InterruptibleEvent[ActionInput]], output_queue: asyncio.Queue[InterruptibleEvent[AgentInput]], interruptible_event_factory: InterruptibleEventFactory = InterruptibleEventFactory(), - action_factory: ActionFactory = ActionFactory(), ): super().__init__( input_queue=input_queue, @@ -32,7 +34,7 @@ def __init__( self.action_factory = action_factory def attach_conversation_state_manager( - self, conversation_state_manager: ConversationStateManager + self, conversation_state_manager: AbstractConversationStateManager ): self.conversation_state_manager = conversation_state_manager @@ -48,14 +50,15 @@ async def process(self, item: InterruptibleEvent[ActionInput]): action_output=action_output, vonage_uuid=( action_input.vonage_uuid - if isinstance(action_input, VonagePhoneCallActionInput) + if isinstance(action_input, VonagePhoneConversationActionInput) else None ), twilio_sid=( action_input.twilio_sid - if isinstance(action_input, TwilioPhoneCallActionInput) + if isinstance(action_input, TwilioPhoneConversationActionInput) else None ), is_quiet=action.quiet, - ) + ), + is_interruptible=False, ) diff --git a/vocode/streaming/agent/__init__.py b/vocode/streaming/agent/__init__.py index d001c05cf..39eaf026f 100644 --- a/vocode/streaming/agent/__init__.py +++ b/vocode/streaming/agent/__init__.py @@ -1,10 +1,2 @@ -from vocode.streaming.agent.anthropic_agent import ChatAnthropicAgent from vocode.streaming.agent.base_agent import BaseAgent from vocode.streaming.agent.chat_gpt_agent import ChatGPTAgent -from vocode.streaming.agent.echo_agent import EchoAgent -from vocode.streaming.agent.gpt4all_agent import GPT4AllAgent -from vocode.streaming.agent.information_retrieval_agent import InformationRetrievalAgent -from vocode.streaming.agent.llm_agent import LLMAgent -from vocode.streaming.agent.restful_user_implemented_agent import ( - RESTfulUserImplementedAgent, -) diff --git a/vocode/streaming/agent/abstract_factory.py b/vocode/streaming/agent/abstract_factory.py new file mode 100644 index 000000000..9bef8bc79 --- /dev/null +++ b/vocode/streaming/agent/abstract_factory.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod + +from vocode.streaming.agent.base_agent import BaseAgent +from vocode.streaming.models.agent import AgentConfig + + +class AbstractAgentFactory(ABC): + @abstractmethod + def create_agent(self, agent_config: AgentConfig) -> BaseAgent: + pass diff --git a/vocode/streaming/agent/anthropic_agent.py b/vocode/streaming/agent/anthropic_agent.py index 009bbdd64..820fa6539 100644 --- a/vocode/streaming/agent/anthropic_agent.py +++ b/vocode/streaming/agent/anthropic_agent.py @@ -1,137 +1,122 @@ -from typing import AsyncGenerator, Optional, Tuple -from langchain import ConversationChain -import logging +import os +from typing import Any, AsyncGenerator, Dict -from typing import Optional, Tuple -from pydantic.v1 import SecretStr -from vocode.streaming.agent.base_agent import RespondAgent +import sentry_sdk +from anthropic import AsyncAnthropic, AsyncStream +from anthropic.types import MessageStreamEvent +from loguru import logger -from vocode.streaming.agent.utils import get_sentence_from_buffer +from vocode.streaming.action.abstract_factory import AbstractActionFactory +from vocode.streaming.action.default_factory import DefaultActionFactory +from vocode.streaming.agent.anthropic_utils import format_anthropic_chat_messages_from_transcript +from vocode.streaming.agent.base_agent import GeneratedResponse, RespondAgent, StreamedResponse +from vocode.streaming.agent.streaming_utils import collate_response_async, stream_response_async +from vocode.streaming.models.actions import FunctionFragment +from vocode.streaming.models.agent import AnthropicAgentConfig +from vocode.streaming.models.message import BaseMessage, LLMToken +from vocode.streaming.vector_db.factory import VectorDBFactory +from vocode.utils.sentry_utils import CustomSentrySpans, sentry_create_span -from langchain import ConversationChain -from langchain.schema import ChatMessage, AIMessage, HumanMessage -from langchain_community.chat_models import ChatAnthropic -import logging -from vocode import getenv -from vocode.streaming.models.agent import ChatAnthropicAgentConfig +class AnthropicAgent(RespondAgent[AnthropicAgentConfig]): + anthropic_client: AsyncAnthropic - -from langchain.prompts import ( - ChatPromptTemplate, - MessagesPlaceholder, - HumanMessagePromptTemplate, -) - -from vocode import getenv -from vocode.streaming.models.agent import ChatAnthropicAgentConfig -from langchain.memory import ConversationBufferMemory - -SENTENCE_ENDINGS = [".", "!", "?"] - - -class ChatAnthropicAgent(RespondAgent[ChatAnthropicAgentConfig]): def __init__( self, - agent_config: ChatAnthropicAgentConfig, - logger: Optional[logging.Logger] = None, - anthropic_api_key: Optional[SecretStr] = None, + agent_config: AnthropicAgentConfig, + action_factory: AbstractActionFactory = DefaultActionFactory(), + vector_db_factory=VectorDBFactory(), + **kwargs, ): - super().__init__(agent_config=agent_config, logger=logger) - import anthropic - - # Convert anthropic_api_key to SecretStr if it's not None and not already a SecretStr - if anthropic_api_key is not None and not isinstance( - anthropic_api_key, SecretStr - ): - anthropic_api_key = SecretStr(anthropic_api_key) - else: - # Retrieve anthropic_api_key from environment variable and convert to SecretStr - env_key = getenv("ANTHROPIC_API_KEY") - if env_key: - anthropic_api_key = SecretStr(env_key) - - if not anthropic_api_key: - raise ValueError( - "ANTHROPIC_API_KEY must be set in environment or passed in as a SecretStr" - ) - self.prompt = ChatPromptTemplate.from_messages( - [ - MessagesPlaceholder(variable_name="history"), - HumanMessagePromptTemplate.from_template("{input}"), - ] + super().__init__( + agent_config=agent_config, + action_factory=action_factory, + **kwargs, ) + self.anthropic_client = AsyncAnthropic(api_key=os.environ.get("ANTHROPIC_API_KEY")) - self.llm = ChatAnthropic( - model_name=agent_config.model_name, - anthropic_api_key=anthropic_api_key, - ) + def get_chat_parameters(self, messages: list = [], use_functions: bool = True): + assert self.transcript is not None - # streaming not well supported by langchain, so we will connect directly - self.anthropic_client = ( - anthropic.AsyncAnthropic(api_key=str(anthropic_api_key)) - if agent_config.generate_responses - else None - ) + parameters: dict[str, Any] = { + "messages": messages, + "system": self.agent_config.prompt_preamble, + "max_tokens": self.agent_config.max_tokens, + "temperature": self.agent_config.temperature, + "stream": True, + } - self.memory = ConversationBufferMemory(return_messages=True) - self.memory.chat_memory.messages.append( - HumanMessage(content=self.agent_config.prompt_preamble) - ) - if agent_config.initial_message: - self.memory.chat_memory.messages.append( - AIMessage(content=agent_config.initial_message.text) - ) + parameters["model"] = self.agent_config.model_name - self.conversation = ConversationChain( - memory=self.memory, prompt=self.prompt, llm=self.llm - ) + return parameters - async def respond( + async def token_generator( self, - human_input, - conversation_id: str, - is_interrupt: bool = False, - ) -> Tuple[str, bool]: - text = await self.conversation.apredict(input=human_input) - self.logger.debug(f"LLM response: {text}") - return text, False + gen: AsyncStream[MessageStreamEvent], + ) -> AsyncGenerator[str | FunctionFragment, None]: + async for chunk in gen: + if chunk.type == "content_block_delta" and chunk.delta.type == "text_delta": + yield chunk.delta.text + + async def _get_anthropic_stream(self, chat_parameters: Dict[str, Any]): + return await self.anthropic_client.messages.create(**chat_parameters) async def generate_response( self, human_input, conversation_id: str, is_interrupt: bool = False, - ) -> AsyncGenerator[Tuple[str, bool], None]: - self.memory.chat_memory.messages.append(HumanMessage(content=human_input)) - - bot_memory_message = AIMessage(content="") - self.memory.chat_memory.messages.append(bot_memory_message) - prompt = self.llm._convert_messages_to_prompt(self.memory.chat_memory.messages) - - if self.anthropic_client: - streamed_response = await self.anthropic_client.completions.create( - prompt=prompt, - max_tokens_to_sample=self.agent_config.max_tokens_to_sample, - model=self.agent_config.model_name, - stream=True, + bot_was_in_medias_res: bool = False, + ) -> AsyncGenerator[GeneratedResponse, None]: + if not self.transcript: + raise ValueError("A transcript is not attached to the agent") + messages = format_anthropic_chat_messages_from_transcript(transcript=self.transcript) + chat_parameters = self.get_chat_parameters(messages) + try: + first_sentence_total_span = sentry_create_span( + sentry_callable=sentry_sdk.start_span, op=CustomSentrySpans.LLM_FIRST_SENTENCE_TOTAL + ) + + ttft_span = sentry_create_span( + sentry_callable=sentry_sdk.start_span, op=CustomSentrySpans.TIME_TO_FIRST_TOKEN ) + stream = await self._get_anthropic_stream(chat_parameters) + except Exception as e: + logger.error( + f"Error while hitting Anthropic with chat_parameters: {chat_parameters}", + exc_info=True, + ) + raise e + + response_generator = collate_response_async + + using_input_streaming_synthesizer = ( + self.conversation_state_manager.using_input_streaming_synthesizer() + ) + if using_input_streaming_synthesizer: + response_generator = stream_response_async + async for message in response_generator( + conversation_id=conversation_id, + gen=self.token_generator( + stream, + ), + sentry_span=ttft_span, + ): + if first_sentence_total_span: + first_sentence_total_span.finish() - buffer = "" - async for completion in streamed_response: - buffer += completion.completion - sentence, remainder = get_sentence_from_buffer(buffer) - if sentence: - bot_memory_message.content = bot_memory_message.content + sentence - buffer = remainder - yield sentence, True - continue - - def update_last_bot_message_on_cut_off(self, message: str): - for memory_message in self.memory.chat_memory.messages[::-1]: - if ( - isinstance(memory_message, ChatMessage) - and memory_message.role == "assistant" - ) or isinstance(memory_message, AIMessage): - memory_message.content = message - return + ResponseClass = ( + StreamedResponse if using_input_streaming_synthesizer else GeneratedResponse + ) + MessageType = LLMToken if using_input_streaming_synthesizer else BaseMessage + + if isinstance(message, str): + yield ResponseClass( + message=MessageType(text=message), + is_interruptible=True, + ) + else: + yield ResponseClass( + message=message, + is_interruptible=True, + ) diff --git a/vocode/streaming/agent/anthropic_utils.py b/vocode/streaming/agent/anthropic_utils.py new file mode 100644 index 000000000..2a2e131d2 --- /dev/null +++ b/vocode/streaming/agent/anthropic_utils.py @@ -0,0 +1,29 @@ +from vocode.streaming.agent.openai_utils import merge_event_logs +from vocode.streaming.models.transcript import ActionStart, EventLog, Transcript + + +def format_anthropic_chat_messages_from_transcript( + transcript: Transcript, +) -> list[dict]: + # merge consecutive bot messages + new_event_logs: list[EventLog] = merge_event_logs(event_logs=transcript.event_logs) + + # Removing BOT_ACTION_START so that it doesn't confuse the completion-y prompt, e.g. + # BOT: BOT_ACTION_START: action_end_conversation + # Right now, this version of context does not work for normal actions, only phrase trigger actions + + merged_event_logs_sans_bot_action_start = [ + event_log for event_log in new_event_logs if not isinstance(event_log, ActionStart) + ] + + return [ + { + "role": "user", + "content": Transcript(event_logs=merged_event_logs_sans_bot_action_start).to_string( + include_timestamps=False, + mark_human_backchannels_with_brackets=True, + ), + }, + {"role": "assistant", "content": "BOT:"}, + ] + # TODO: reliably count tokens of Anthropic messages so that we don't exceed the context window diff --git a/vocode/streaming/agent/base_agent.py b/vocode/streaming/agent/base_agent.py index b39d40013..f6a56a7e7 100644 --- a/vocode/streaming/agent/base_agent.py +++ b/vocode/streaming/agent/base_agent.py @@ -1,59 +1,64 @@ from __future__ import annotations import asyncio -from enum import Enum import json -import logging import random -from typing import ( - AsyncGenerator, - Generator, - Generic, - Optional, - Tuple, - TypeVar, - Union, - TYPE_CHECKING, -) import typing -from opentelemetry import trace -from opentelemetry.trace import Span -from vocode.streaming.action.factory import ActionFactory +from enum import Enum +from typing import TYPE_CHECKING, AsyncGenerator, Dict, Generic, Optional, Tuple, TypeVar, Union + +import sentry_sdk +from loguru import logger +from pydantic.v1 import BaseModel + +from vocode import sentry_span_tags +from vocode.streaming.action.abstract_factory import AbstractActionFactory +from vocode.streaming.action.base_action import BaseAction +from vocode.streaming.action.default_factory import DefaultActionFactory +from vocode.streaming.action.execute_external_action import ExecuteExternalActionVocodeActionConfig from vocode.streaming.action.phone_call_action import ( - TwilioPhoneCallAction, - VonagePhoneCallAction, + TwilioPhoneConversationAction, + VonagePhoneConversationAction, ) +from vocode.streaming.agent.goodbye import is_goodbye_simple +from vocode.streaming.agent.phrase_trigger import matches_phrase_trigger from vocode.streaming.models.actions import ( ActionConfig, ActionInput, ActionOutput, + EndOfTurn, FunctionCall, - FunctionFragment, ) - -from vocode.streaming.models.agent import ( - AgentConfig, - ChatGPTAgentConfig, - LLMAgentConfig, -) -from vocode.streaming.models.message import BaseMessage -from vocode.streaming.models.model import BaseModel, TypedModel -from vocode.streaming.transcriber.base_transcriber import Transcription -from vocode.streaming.utils import remove_non_letters_digits -from vocode.streaming.utils.goodbye_model import GoodbyeModel -from vocode.streaming.models.transcript import Transcript +from vocode.streaming.models.agent import AgentConfig, ChatGPTAgentConfig, LLMAgentConfig +from vocode.streaming.models.events import Sender +from vocode.streaming.models.message import BaseMessage, BotBackchannel, SilenceMessage +from vocode.streaming.models.model import TypedModel +from vocode.streaming.models.transcriber import Transcription +from vocode.streaming.models.transcript import Message, Transcript +from vocode.streaming.utils import unrepeating_randomizer +from vocode.streaming.utils.speed_manager import SpeedManager from vocode.streaming.utils.worker import ( InterruptibleAgentResponseEvent, InterruptibleEvent, InterruptibleEventFactory, InterruptibleWorker, ) +from vocode.utils.sentry_utils import CustomSentrySpans, sentry_create_span if TYPE_CHECKING: - from vocode.streaming.utils.state_manager import ConversationStateManager + from vocode.streaming.utils.state_manager import AbstractConversationStateManager -tracer = trace.get_tracer(__name__) AGENT_TRACE_NAME = "agent" +POST_QUESTION_BACKCHANNELS = [ + "Oh okay, got it.", + "Oh, okay, got it.", + "Oh okay got it.", + "Ohhh, okay, got it.", + "Oh got it, okay.", + "Ohhh got it, okay.", + "Ohhh, got it, okay.", + "Oh, got it, okay.", +] class AgentInputType(str, Enum): @@ -62,7 +67,7 @@ class AgentInputType(str, Enum): ACTION_RESULT = "agent_input_action_result" -class AgentInput(TypedModel, type=AgentInputType.BASE.value): +class AgentInput(TypedModel, type=AgentInputType.BASE.value): # type: ignore conversation_id: str vonage_uuid: Optional[str] twilio_sid: Optional[str] @@ -72,11 +77,11 @@ class Config: arbitrary_types_allowed = True -class TranscriptionAgentInput(AgentInput, type=AgentInputType.TRANSCRIPTION.value): +class TranscriptionAgentInput(AgentInput, type=AgentInputType.TRANSCRIPTION.value): # type: ignore transcription: Transcription -class ActionResultAgentInput(AgentInput, type=AgentInputType.ACTION_RESULT.value): +class ActionResultAgentInput(AgentInput, type=AgentInputType.ACTION_RESULT.value): # type: ignore action_input: ActionInput action_output: ActionOutput is_quiet: bool = False @@ -89,25 +94,40 @@ class AgentResponseType(str, Enum): FILLER_AUDIO = "agent_response_filler_audio" -class AgentResponse(TypedModel, type=AgentResponseType.BASE.value): +class AgentResponse(TypedModel, type=AgentResponseType.BASE.value): # type: ignore pass -class AgentResponseMessage(AgentResponse, type=AgentResponseType.MESSAGE.value): - message: BaseMessage +class AgentResponseMessage(AgentResponse, type=AgentResponseType.MESSAGE.value): # type: ignore + message: Union[BaseMessage, EndOfTurn] is_interruptible: bool = True + # Whether the message is the first message in the response; has metrics implications + is_first: bool = False + # If the response is not being chunked up into multiple sentences, this is set to True + is_sole_text_chunk: bool = False -class AgentResponseStop(AgentResponse, type=AgentResponseType.STOP.value): +class AgentResponseStop(AgentResponse, type=AgentResponseType.STOP.value): # type: ignore pass class AgentResponseFillerAudio( - AgentResponse, type=AgentResponseType.FILLER_AUDIO.value + AgentResponse, + type=AgentResponseType.FILLER_AUDIO.value, # type: ignore ): pass +class GeneratedResponse(BaseModel): + message: Union[BaseMessage, FunctionCall, EndOfTurn] + is_interruptible: bool + streamed: bool = False + + +class StreamedResponse(GeneratedResponse): + streamed: bool = True + + AgentConfigType = TypeVar("AgentConfigType", bound=AgentConfig) @@ -124,7 +144,8 @@ def update_last_bot_message_on_cut_off(self, message: str): def get_cut_off_response(self) -> str: assert isinstance(self.agent_config, LLMAgentConfig) or isinstance( - self.agent_config, ChatGPTAgentConfig + self.agent_config, + ChatGPTAgentConfig, ), "Set cutoff response is only implemented in LLMAgent and ChatGPTAgent" assert self.agent_config.cut_off_response is not None on_cut_off_messages = self.agent_config.cut_off_response.messages @@ -136,16 +157,13 @@ class BaseAgent(AbstractAgent[AgentConfigType], InterruptibleWorker): def __init__( self, agent_config: AgentConfigType, - action_factory: ActionFactory = ActionFactory(), + action_factory: AbstractActionFactory = DefaultActionFactory(), interruptible_event_factory: InterruptibleEventFactory = InterruptibleEventFactory(), - logger: Optional[logging.Logger] = None, ): - self.input_queue: asyncio.Queue[InterruptibleEvent[AgentInput]] = ( + self.input_queue: asyncio.Queue[InterruptibleEvent[AgentInput]] = asyncio.Queue() + self.output_queue: asyncio.Queue[InterruptibleAgentResponseEvent[AgentResponse]] = ( asyncio.Queue() ) - self.output_queue: asyncio.Queue[ - InterruptibleAgentResponseEvent[AgentResponse] - ] = asyncio.Queue() AbstractAgent.__init__(self, agent_config=agent_config) InterruptibleWorker.__init__( self, @@ -154,21 +172,16 @@ def __init__( interruptible_event_factory=interruptible_event_factory, ) self.action_factory = action_factory - self.actions_queue: asyncio.Queue[InterruptibleEvent[ActionInput]] = ( - asyncio.Queue() - ) - self.logger = logger or logging.getLogger(__name__) - self.goodbye_model = None - if self.agent_config.end_conversation_on_goodbye: - self.goodbye_model = GoodbyeModel() - self.goodbye_model_initialize_task = asyncio.create_task( - self.goodbye_model.initialize_embeddings() - ) + self.actions_queue: asyncio.Queue[InterruptibleEvent[ActionInput]] = asyncio.Queue() self.transcript: Optional[Transcript] = None self.functions = self.get_functions() if self.agent_config.actions else None self.is_muted = False + self.post_question_bot_backchannel_randomizer = unrepeating_randomizer( + POST_QUESTION_BACKCHANNELS, + ) + def get_functions(self): raise NotImplementedError @@ -176,10 +189,20 @@ def attach_transcript(self, transcript: Transcript): self.transcript = transcript def attach_conversation_state_manager( - self, conversation_state_manager: ConversationStateManager + self, + conversation_state_manager: AbstractConversationStateManager, ): self.conversation_state_manager = conversation_state_manager + def attach_speed_manager(self, speed_manager: SpeedManager): + self.speed_manager = speed_manager + + def _get_speed_adjusted_silence_seconds(self, seconds: float) -> float: + speed_coefficient = ( + self.speed_manager.get_speed_coefficient() if self.speed_manager is not None else 1.0 + ) + return seconds / speed_coefficient + def set_interruptible_event_factory(self, factory: InterruptibleEventFactory): self.interruptible_event_factory = factory @@ -193,62 +216,161 @@ def get_output_queue( ) -> asyncio.Queue[InterruptibleAgentResponseEvent[AgentResponse]]: return self.output_queue - def create_goodbye_detection_task(self, message: str) -> asyncio.Task: - assert self.goodbye_model is not None - return asyncio.create_task(self.goodbye_model.is_goodbye(message)) + def is_first_response(self): + assert self.transcript is not None + + num_bot_messages = sum( + 1 + for event_log in self.transcript.event_logs + if isinstance(event_log, Message) and event_log.sender == Sender.BOT + ) + + return num_bot_messages <= (1 if self.agent_config.initial_message is not None else 0) class RespondAgent(BaseAgent[AgentConfigType]): + async def _maybe_prepend_interrupt_responses( + self, + transcription: Transcription, + responses_stream: AsyncGenerator[GeneratedResponse, None], + ) -> AsyncGenerator[GeneratedResponse, None]: + if transcription.is_interrupt: + if self.agent_config.cut_off_response: + cut_off_response = self.get_cut_off_response() + yield GeneratedResponse( + message=BaseMessage(text=cut_off_response), + is_interruptible=False, + ) + return + if transcription.bot_was_in_medias_res: + silence_message = SilenceMessage() + silence_message.trailing_silence_seconds = self._get_speed_adjusted_silence_seconds( + silence_message.trailing_silence_seconds + ) + yield GeneratedResponse(message=silence_message, is_interruptible=True) + async for response in responses_stream: + yield response + async def handle_generate_response( - self, transcription: Transcription, agent_input: AgentInput + self, + transcription: Transcription, + agent_input: AgentInput, ) -> bool: conversation_id = agent_input.conversation_id - tracer_name_start = await self.get_tracer_name_start() - agent_span = tracer.start_span( - f"{tracer_name_start}.generate_total" # type: ignore - ) - agent_span_first = tracer.start_span( - f"{tracer_name_start}.generate_first" # type: ignore + responses = self._maybe_prepend_interrupt_responses( + transcription=transcription, + responses_stream=self.generate_response( + transcription.message, + is_interrupt=transcription.is_interrupt, + conversation_id=conversation_id, + bot_was_in_medias_res=transcription.bot_was_in_medias_res, + ), ) - responses = self.generate_response( - transcription.message, - is_interrupt=transcription.is_interrupt, - conversation_id=conversation_id, - ) - is_first_response = True + is_first_response_of_turn = True function_call = None - async for response, is_interruptible in responses: - if isinstance(response, FunctionCall): - function_call = response + + responses_buffer = "" + end_of_turn_agent_response_tracker = None + + async for generated_response in responses: + if is_first_response_of_turn: + message_type = "UNKNOWN" + match generated_response.message: + case SilenceMessage(): # type: ignore[misc] + message_type = "silence" + case BotBackchannel(): # type: ignore[misc] + message_type = "backchannel" + case BaseMessage(): # type: ignore[misc] + message_type = "message" + case FunctionCall(): # type: ignore[misc] + message_type = "function_call" + case _: + logger.warning( + "Unknown message type received for Sentry metrics " + f"reporting: {type(generated_response.message)}", + ) + span_tags = sentry_span_tags.value + if span_tags: + span_tags["message_type"] = message_type + sentry_span_tags.set(span_tags) + + if isinstance(generated_response.message, FunctionCall): + function_call = generated_response.message continue - if is_first_response: - agent_span_first.end() - is_first_response = False + + agent_response_tracker = agent_input.agent_response_tracker or asyncio.Event() self.produce_interruptible_agent_response_event_nonblocking( - AgentResponseMessage(message=BaseMessage(text=response)), + AgentResponseMessage( + message=generated_response.message, + is_first=is_first_response_of_turn, + ), + is_interruptible=self.agent_config.allow_agent_to_be_cut_off + and generated_response.is_interruptible, + agent_response_tracker=agent_response_tracker, + ) + if isinstance(generated_response.message, BaseMessage): + responses_buffer = f"{responses_buffer} {generated_response.message.text}" + elif isinstance(generated_response.message, EndOfTurn): + end_of_turn_agent_response_tracker = agent_response_tracker + + if self.agent_config.end_conversation_on_goodbye and isinstance( + generated_response.message, + BaseMessage, + ): + if is_goodbye_simple( + message=generated_response.message.text, + phrases=self.agent_config.goodbye_phrases, + ): + logger.debug("Simple goodbye detected, ending conversation") + return True + is_first_response_of_turn = False + + # if the client (the implemented agent) doesn't create an EndOfTurn, then we need to create one + if not end_of_turn_agent_response_tracker: + end_of_turn_agent_response_tracker = ( + agent_input.agent_response_tracker or asyncio.Event() + ) + self.produce_interruptible_agent_response_event_nonblocking( + AgentResponseMessage( + message=EndOfTurn(), + is_first=is_first_response_of_turn, + ), is_interruptible=self.agent_config.allow_agent_to_be_cut_off - and is_interruptible, - agent_response_tracker=agent_input.agent_response_tracker, + and generated_response.is_interruptible, + agent_response_tracker=end_of_turn_agent_response_tracker, + ) + + phrase_trigger_match = ( + matches_phrase_trigger(responses_buffer, self.agent_config.actions) + if self.agent_config.actions + else None + ) + if phrase_trigger_match: + action_config = self._get_action_config(phrase_trigger_match) + assert action_config is not None + action = self.action_factory.create_action(action_config) + action_input = self.create_action_input( + action, + agent_input, + {}, + end_of_turn_agent_response_tracker, ) + self.enqueue_action_input(action, action_input, agent_input.conversation_id) + # TODO: implement should_stop for generate_responses - agent_span.end() if function_call and self.agent_config.actions is not None: await self.call_function(function_call, agent_input) return False - async def handle_respond( - self, transcription: Transcription, conversation_id: str - ) -> bool: + async def handle_respond(self, transcription: Transcription, conversation_id: str) -> bool: try: - tracer_name_start = await self.get_tracer_name_start() - with tracer.start_as_current_span(f"{tracer_name_start}.respond_total"): - response, should_stop = await self.respond( - transcription.message, - is_interrupt=transcription.is_interrupt, - conversation_id=conversation_id, - ) + response, should_stop = await self.respond( + transcription.message, + is_interrupt=transcription.is_interrupt, + conversation_id=conversation_id, + ) except Exception as e: - self.logger.error(f"Error while generating response: {e}", exc_info=True) + logger.error(f"Error while generating response: {e}", exc_info=True) response = None return True if response: @@ -256,22 +378,21 @@ async def handle_respond( AgentResponseMessage(message=BaseMessage(text=response)), is_interruptible=self.agent_config.allow_agent_to_be_cut_off, ) + self.produce_interruptible_agent_response_event_nonblocking( + AgentResponseMessage(message=EndOfTurn()), + is_interruptible=self.agent_config.allow_agent_to_be_cut_off, + ) return should_stop else: - self.logger.debug("No response generated") + logger.debug("No response generated") return False async def process(self, item: InterruptibleEvent[AgentInput]): - if self.is_muted: - self.logger.debug("Agent is muted, skipping processing") - return assert self.transcript is not None try: agent_input = item.payload if isinstance(agent_input, TranscriptionAgentInput): - transcription = typing.cast( - TranscriptionAgentInput, agent_input - ).transcription + transcription = typing.cast(TranscriptionAgentInput, agent_input).transcription self.transcript.add_human_message( text=transcription.message, conversation_id=agent_input.conversation_id, @@ -284,7 +405,19 @@ async def process(self, item: InterruptibleEvent[AgentInput]): ) if agent_input.is_quiet: # Do not generate a response to quiet actions - self.logger.debug("Action is quiet, skipping response generation") + logger.debug("Action is quiet, skipping response generation") + return + if agent_input.action_output.canned_response is not None: + self.produce_interruptible_agent_response_event_nonblocking( + AgentResponseMessage( + message=agent_input.action_output.canned_response, + is_sole_text_chunk=True, + ), + is_interruptible=True, + ) + self.produce_interruptible_agent_response_event_nonblocking( + AgentResponseMessage(message=EndOfTurn()), + ) return transcription = Transcription( message=agent_input.action_output.response.json(), @@ -294,45 +427,32 @@ async def process(self, item: InterruptibleEvent[AgentInput]): else: raise ValueError("Invalid AgentInput type") - goodbye_detected_task = None - if self.agent_config.end_conversation_on_goodbye: - goodbye_detected_task = self.create_goodbye_detection_task( - transcription.message - ) + if self.is_muted: + logger.debug("Agent is muted, skipping processing") + return + if self.agent_config.send_filler_audio: self.produce_interruptible_agent_response_event_nonblocking( - AgentResponseFillerAudio() + AgentResponseFillerAudio(), ) - self.logger.debug("Responding to transcription") + + logger.debug("Responding to transcription") should_stop = False if self.agent_config.generate_responses: - should_stop = await self.handle_generate_response( - transcription, agent_input - ) + # TODO (EA): this is quite ugly but necessary to have the agent act properly after an action completes + if not isinstance(agent_input, ActionResultAgentInput): + sentry_create_span( + sentry_callable=sentry_sdk.start_span, + op=CustomSentrySpans.LANGUAGE_MODEL_TIME_TO_FIRST_TOKEN, + ) + should_stop = await self.handle_generate_response(transcription, agent_input) else: - should_stop = await self.handle_respond( - transcription, agent_input.conversation_id - ) + should_stop = await self.handle_respond(transcription, agent_input.conversation_id) if should_stop: - self.logger.debug("Agent requested to stop") - self.produce_interruptible_agent_response_event_nonblocking( - AgentResponseStop() - ) + logger.debug("Agent requested to stop") + self.produce_interruptible_agent_response_event_nonblocking(AgentResponseStop()) return - if goodbye_detected_task: - try: - goodbye_detected = await asyncio.wait_for( - goodbye_detected_task, 0.1 - ) - if goodbye_detected: - self.logger.debug("Goodbye detected, ending conversation") - self.produce_interruptible_agent_response_event_nonblocking( - AgentResponseStop() - ) - return - except asyncio.TimeoutError: - self.logger.debug("Goodbye detection timed out") except asyncio.CancelledError: pass @@ -340,16 +460,17 @@ def _get_action_config(self, function_name: str) -> Optional[ActionConfig]: if self.agent_config.actions is None: return None for action_config in self.agent_config.actions: - if action_config.type == function_name: + if action_config.type == function_name or ( + isinstance(action_config, ExecuteExternalActionVocodeActionConfig) + and action_config.name == function_name + ): return action_config return None async def call_function(self, function_call: FunctionCall, agent_input: AgentInput): action_config = self._get_action_config(function_call.name) if action_config is None: - self.logger.error( - f"Function {function_call.name} not found in agent config, skipping" - ) + logger.error(f"Function {function_call.name} not found in agent config, skipping") return action = self.action_factory.create_action(action_config) params = json.loads(function_call.arguments) @@ -358,25 +479,42 @@ async def call_function(self, function_call: FunctionCall, agent_input: AgentInp user_message = params["user_message"] user_message_tracker = asyncio.Event() self.produce_interruptible_agent_response_event_nonblocking( - AgentResponseMessage(message=BaseMessage(text=user_message)), + AgentResponseMessage( + message=BaseMessage(text=user_message), + is_sole_text_chunk=True, + ), + is_interruptible=action.is_interruptible, + ) + self.produce_interruptible_agent_response_event_nonblocking( + AgentResponseMessage(message=EndOfTurn()), agent_response_tracker=user_message_tracker, ) + action_input = self.create_action_input(action, agent_input, params, user_message_tracker) + self.enqueue_action_input(action, action_input, agent_input.conversation_id) + + def create_action_input( + self, + action: BaseAction, + agent_input: AgentInput, + params: Dict, + user_message_tracker: Optional[asyncio.Event] = None, + ) -> ActionInput: action_input: ActionInput - if isinstance(action, VonagePhoneCallAction): + if isinstance(action, VonagePhoneConversationAction): assert ( agent_input.vonage_uuid is not None - ), "Cannot use VonagePhoneCallActionFactory unless the attached conversation is a VonageCall" - action_input = action.create_phone_call_action_input( + ), "Cannot use VonagePhoneConversationActionFactory unless the attached conversation is a VonagePhoneConversation" + action_input = action.create_phone_conversation_action_input( agent_input.conversation_id, params, agent_input.vonage_uuid, user_message_tracker, ) - elif isinstance(action, TwilioPhoneCallAction): + elif isinstance(action, TwilioPhoneConversationAction): assert ( agent_input.twilio_sid is not None - ), "Cannot use TwilioPhoneCallActionFactory unless the attached conversation is a TwilioCall" - action_input = action.create_phone_call_action_input( + ), "Cannot use TwilioPhoneConversationActionFactory unless the attached conversation is a TwilioPhoneConversation" + action_input = action.create_phone_conversation_action_input( agent_input.conversation_id, params, agent_input.twilio_sid, @@ -388,40 +526,25 @@ async def call_function(self, function_call: FunctionCall, agent_input: AgentInp params, user_message_tracker, ) + return action_input + + def enqueue_action_input( + self, + action: BaseAction, + action_input: ActionInput, + conversation_id: str, + ): event = self.interruptible_event_factory.create_interruptible_event( - action_input, is_interruptible=action.is_interruptible + action_input, + is_interruptible=action.is_interruptible, ) assert self.transcript is not None self.transcript.add_action_start_log( action_input=action_input, - conversation_id=agent_input.conversation_id, + conversation_id=conversation_id, ) self.actions_queue.put_nowait(event) - async def get_tracer_name_start(self) -> str: - if hasattr(self, "tracer_name_start"): - return self.tracer_name_start - if ( - hasattr(self.agent_config, "azure_params") - and self.agent_config.azure_params is not None - ): - beginning_agent_name = self.agent_config.type.rsplit("_", 1)[0] - engine = self.agent_config.azure_params.engine - tracer_name_start = ( - f"{AGENT_TRACE_NAME}.{beginning_agent_name}_azuregpt-{engine}" - ) - else: - optional_model_name = ( - f"-{self.agent_config.model_name}" - if hasattr(self.agent_config, "model_name") - else "" - ) - tracer_name_start = remove_non_letters_digits( - f"{AGENT_TRACE_NAME}.{self.agent_config.type}{optional_model_name}" - ) - self.tracer_name_start: str = tracer_name_start - return tracer_name_start - async def respond( self, human_input, @@ -435,7 +558,9 @@ def generate_response( human_input, conversation_id: str, is_interrupt: bool = False, + bot_was_in_medias_res: bool = False, ) -> AsyncGenerator[ - Tuple[Union[str, FunctionCall], bool], None + GeneratedResponse, + None, ]: # tuple of the content and whether it is interruptible raise NotImplementedError diff --git a/vocode/streaming/agent/bot_sentiment_analyser.py b/vocode/streaming/agent/bot_sentiment_analyser.py deleted file mode 100644 index ed2ed1490..000000000 --- a/vocode/streaming/agent/bot_sentiment_analyser.py +++ /dev/null @@ -1,58 +0,0 @@ -from typing import List, Optional -from langchain_community.llms import OpenAI -from langchain.prompts import PromptTemplate -from pydantic.v1 import BaseModel - -from vocode import getenv - -TEMPLATE = """ -Read the following conversation classify the final emotion of the Bot as one of [{emotions}]. -Output the degree of emotion as a value between 0 and 1 in the format EMOTION,DEGREE: ex. {example_emotion},0.5 - - -{{transcript}} - -""" - - -class BotSentiment(BaseModel): - emotion: Optional[str] = None - degree: float = 0.0 - - -class BotSentimentAnalyser: - def __init__( - self, - emotions: List[str], - model_name: str = "text-davinci-003", - openai_api_key: Optional[str] = None, - ): - self.model_name = model_name - openai_api_key = openai_api_key or getenv("OPENAI_API_KEY") - if not openai_api_key: - raise ValueError("OPENAI_API_KEY must be set in environment or passed in") - self.llm = OpenAI(model_name=self.model_name, openai_api_key=openai_api_key) # type: ignore - assert len(emotions) > 0 - self.emotions = [e.lower() for e in emotions] - self.prompt = PromptTemplate( - input_variables=["transcript"], - template=TEMPLATE.format( - emotions=",".join(self.emotions), example_emotion=self.emotions[0] - ), - ) - - async def analyse(self, transcript: str) -> BotSentiment: - prompt = self.prompt.format(transcript=transcript) - response = (await self.llm.agenerate([prompt])).generations[0][0].text.strip() - tokens = response.split(",") - if len(tokens) != 2: - return BotSentiment(emotion=None, degree=0.0) - emotion, degree = tokens - emotion = emotion.strip().lower() - if emotion.lower() not in self.emotions: - return BotSentiment(emotion=None, degree=0.0) - try: - parsed_degree = float(degree.strip()) - except ValueError: - return BotSentiment(emotion=emotion, degree=0.5) - return BotSentiment(emotion=emotion, degree=parsed_degree) diff --git a/vocode/streaming/agent/chat_gpt_agent.py b/vocode/streaming/agent/chat_gpt_agent.py index 4afacf249..889c5f459 100644 --- a/vocode/streaming/agent/chat_gpt_agent.py +++ b/vocode/streaming/agent/chat_gpt_agent.py @@ -1,64 +1,66 @@ -import logging - -from typing import Any, Dict, List, Optional, Tuple, Union - -import openai -from typing import AsyncGenerator, Optional, Tuple - -import logging -from pydantic.v1 import BaseModel - -from vocode import getenv -from vocode.streaming.action.factory import ActionFactory -from vocode.streaming.agent.base_agent import RespondAgent -from vocode.streaming.models.actions import FunctionCall, FunctionFragment -from vocode.streaming.models.agent import ChatGPTAgentConfig -from vocode.streaming.agent.utils import ( +import os +import random +from typing import Any, AsyncGenerator, Dict, List, Optional, TypeVar, Union + +import sentry_sdk +from loguru import logger +from openai import AsyncAzureOpenAI, AsyncOpenAI + +from vocode import sentry_span_tags +from vocode.streaming.action.abstract_factory import AbstractActionFactory +from vocode.streaming.action.default_factory import DefaultActionFactory +from vocode.streaming.agent.base_agent import GeneratedResponse, RespondAgent, StreamedResponse +from vocode.streaming.agent.openai_utils import ( format_openai_chat_messages_from_transcript, - collate_response_async, openai_get_tokens, vector_db_result_to_openai_chat_message, ) +from vocode.streaming.agent.streaming_utils import collate_response_async, stream_response_async +from vocode.streaming.models.actions import FunctionCallActionTrigger +from vocode.streaming.models.agent import ChatGPTAgentConfig from vocode.streaming.models.events import Sender -from vocode.streaming.models.transcript import Transcript +from vocode.streaming.models.message import BaseMessage, BotBackchannel, LLMToken +from vocode.streaming.models.transcript import Message from vocode.streaming.vector_db.factory import VectorDBFactory +from vocode.utils.sentry_utils import CustomSentrySpans, sentry_create_span +ChatGPTAgentConfigType = TypeVar("ChatGPTAgentConfigType", bound=ChatGPTAgentConfig) + + +class ChatGPTAgent(RespondAgent[ChatGPTAgentConfigType]): + openai_client: Union[AsyncOpenAI, AsyncAzureOpenAI] -class ChatGPTAgent(RespondAgent[ChatGPTAgentConfig]): def __init__( self, - agent_config: ChatGPTAgentConfig, - action_factory: ActionFactory = ActionFactory(), - logger: Optional[logging.Logger] = None, - openai_api_key: Optional[str] = None, + agent_config: ChatGPTAgentConfigType, + action_factory: AbstractActionFactory = DefaultActionFactory(), vector_db_factory=VectorDBFactory(), + **kwargs, ): super().__init__( - agent_config=agent_config, action_factory=action_factory, logger=logger + agent_config=agent_config, + action_factory=action_factory, + **kwargs, ) if agent_config.azure_params: - openai.api_type = agent_config.azure_params.api_type - openai.api_base = getenv("AZURE_OPENAI_API_BASE") - openai.api_version = agent_config.azure_params.api_version - openai.api_key = getenv("AZURE_OPENAI_API_KEY") + self.openai_client = AsyncAzureOpenAI( + azure_endpoint=agent_config.azure_params.base_url, + api_key=agent_config.azure_params.api_key, + api_version=agent_config.azure_params.api_version, + ) else: - openai.api_type = "open_ai" - openai.api_base = "https://api.openai.com/v1" - openai.api_version = None - openai.api_key = openai_api_key or getenv("OPENAI_API_KEY") - if not openai.api_key: + if agent_config.openai_api_key is not None: + logger.info("Using OpenAI API key override") + self.openai_client = AsyncOpenAI( + api_key=agent_config.openai_api_key or os.environ["OPENAI_API_KEY"], + base_url="https://api.openai.com/v1", + ) + + if not self.openai_client.api_key: raise ValueError("OPENAI_API_KEY must be set in environment or passed in") - self.first_response = ( - self.create_first_response(agent_config.expected_first_prompt) - if agent_config.expected_first_prompt - else None - ) - self.is_first_response = True if self.agent_config.vector_db_config: - self.vector_db = vector_db_factory.create_vector_db( - self.agent_config.vector_db_config - ) + self.vector_db = vector_db_factory.create_vector_db(self.agent_config.vector_db_config) def get_functions(self): assert self.agent_config.actions @@ -67,14 +69,18 @@ def get_functions(self): return [ self.action_factory.create_action(action_config).get_openai_function() for action_config in self.agent_config.actions + if isinstance(action_config.action_trigger, FunctionCallActionTrigger) ] - def get_chat_parameters( - self, messages: Optional[List] = None, use_functions: bool = True - ): + def get_chat_parameters(self, messages: Optional[List] = None, use_functions: bool = True): assert self.transcript is not None + is_azure = self._is_azure_model() + messages = messages or format_openai_chat_messages_from_transcript( - self.transcript, self.agent_config.prompt_preamble + self.transcript, + self.get_model_name_for_tokenizer(), + self.functions, + self.agent_config.prompt_preamble, ) parameters: Dict[str, Any] = { @@ -83,8 +89,9 @@ def get_chat_parameters( "temperature": self.agent_config.temperature, } - if self.agent_config.azure_params is not None: - parameters["engine"] = self.agent_config.azure_params.engine + if is_azure: + assert self.agent_config.azure_params is not None + parameters["model"] = self.agent_config.azure_params.deployment_name else: parameters["model"] = self.agent_config.model_name @@ -93,54 +100,52 @@ def get_chat_parameters( return parameters - def create_first_response(self, first_prompt): - messages = [ - ( - [{"role": "system", "content": self.agent_config.prompt_preamble}] - if self.agent_config.prompt_preamble - else [] - ) - + [{"role": "user", "content": first_prompt}] - ] - - parameters = self.get_chat_parameters(messages) - return openai.ChatCompletion.create(**parameters) + def _is_azure_model(self) -> bool: + return self.agent_config.azure_params is not None - def attach_transcript(self, transcript: Transcript): - self.transcript = transcript - - async def respond( - self, - human_input, - conversation_id: str, - is_interrupt: bool = False, - ) -> Tuple[str, bool]: - assert self.transcript is not None - if is_interrupt and self.agent_config.cut_off_response: - cut_off_response = self.get_cut_off_response() - return cut_off_response, False - self.logger.debug("LLM responding to human input") - if self.is_first_response and self.first_response: - self.logger.debug("First response is cached") - self.is_first_response = False - text = self.first_response + def get_model_name_for_tokenizer(self): + if not self.agent_config.azure_params: + return self.agent_config.model_name else: - chat_parameters = self.get_chat_parameters() - chat_completion = await openai.ChatCompletion.acreate(**chat_parameters) - text = chat_completion.choices[0].message.content - self.logger.debug(f"LLM response: {text}") - return text, False + return self.agent_config.azure_params.openai_model_name + + async def _create_openai_stream(self, chat_parameters: Dict[str, Any]) -> AsyncGenerator: + try: + stream = await self.openai_client.chat.completions.create(**chat_parameters) + except Exception as e: + logger.error( + f"Error while hitting OpenAI with chat_parameters: {chat_parameters}", + exc_info=True, + ) + raise e + return stream + + def should_backchannel(self, human_input: str) -> bool: + return ( + not self.is_first_response() + and not human_input.strip().endswith("?") + and random.random() < self.agent_config.backchannel_probability + ) + + def choose_backchannel(self) -> Optional[BotBackchannel]: + backchannel = None + if self.transcript is not None: + last_bot_message: Optional[Message] = None + for event_log in self.transcript.event_logs[::-1]: + if isinstance(event_log, Message) and event_log.sender == Sender.BOT: + last_bot_message = event_log + break + if last_bot_message and last_bot_message.text.strip().endswith("?"): + return BotBackchannel(text=self.post_question_bot_backchannel_randomizer()) + return backchannel async def generate_response( self, human_input: str, conversation_id: str, is_interrupt: bool = False, - ) -> AsyncGenerator[Tuple[Union[str, FunctionCall], bool], None]: - if is_interrupt and self.agent_config.cut_off_response: - cut_off_response = self.get_cut_off_response() - yield cut_off_response, False - return + bot_was_in_medias_res: bool = False, + ) -> AsyncGenerator[GeneratedResponse, None]: assert self.transcript is not None chat_parameters = {} @@ -158,22 +163,90 @@ async def generate_response( for doc in docs_with_scores ] ) - vector_db_result = f"Found {len(docs_with_scores)} similar documents:\n{docs_with_scores_str}" - messages = format_openai_chat_messages_from_transcript( - self.transcript, self.agent_config.prompt_preamble + vector_db_result = ( + f"Found {len(docs_with_scores)} similar documents:\n{docs_with_scores_str}" ) - messages.insert( - -1, vector_db_result_to_openai_chat_message(vector_db_result) + messages = format_openai_chat_messages_from_transcript( + self.transcript, + self.agent_config.model_name, + self.functions, + self.agent_config.prompt_preamble, ) + messages.insert(-1, vector_db_result_to_openai_chat_message(vector_db_result)) chat_parameters = self.get_chat_parameters(messages) except Exception as e: - self.logger.error(f"Error while hitting vector db: {e}", exc_info=True) + logger.error(f"Error while hitting vector db: {e}", exc_info=True) chat_parameters = self.get_chat_parameters() else: chat_parameters = self.get_chat_parameters() chat_parameters["stream"] = True - stream = await openai.ChatCompletion.acreate(**chat_parameters) - async for message in collate_response_async( - openai_get_tokens(stream), get_functions=True + + openai_chat_messages: List = chat_parameters.get("messages", []) + + backchannelled = "false" + backchannel: Optional[BotBackchannel] = None + if ( + self.agent_config.use_backchannels + and not bot_was_in_medias_res + and self.should_backchannel(human_input) + ): + backchannel = self.choose_backchannel() + elif self.agent_config.first_response_filler_message and self.is_first_response(): + backchannel = BotBackchannel(text=self.agent_config.first_response_filler_message) + + if backchannel is not None: + # The LLM needs the backchannel context manually - otherwise we're in a race condition + # between sending the response and generating ChatGPT's response + openai_chat_messages.append({"role": "assistant", "content": backchannel.text}) + yield GeneratedResponse( + message=backchannel, + is_interruptible=True, + ) + backchannelled = "true" + + span_tags = sentry_span_tags.value + if span_tags: + span_tags["prior_backchannel"] = backchannelled + sentry_span_tags.set(span_tags) + + first_sentence_total_span = sentry_create_span( + sentry_callable=sentry_sdk.start_span, op=CustomSentrySpans.LLM_FIRST_SENTENCE_TOTAL + ) + + ttft_span = sentry_create_span( + sentry_callable=sentry_sdk.start_span, op=CustomSentrySpans.TIME_TO_FIRST_TOKEN + ) + + stream = await self._create_openai_stream(chat_parameters) + + response_generator = collate_response_async + using_input_streaming_synthesizer = ( + self.conversation_state_manager.using_input_streaming_synthesizer() + ) + if using_input_streaming_synthesizer: + response_generator = stream_response_async + async for message in response_generator( + conversation_id=conversation_id, + gen=openai_get_tokens( + stream, + ), + get_functions=True, + sentry_span=ttft_span, ): - yield message, True + if first_sentence_total_span: + first_sentence_total_span.finish() + + ResponseClass = ( + StreamedResponse if using_input_streaming_synthesizer else GeneratedResponse + ) + MessageType = LLMToken if using_input_streaming_synthesizer else BaseMessage + if isinstance(message, str): + yield ResponseClass( + message=MessageType(text=message), + is_interruptible=True, + ) + else: + yield ResponseClass( + message=message, + is_interruptible=True, + ) diff --git a/vocode/streaming/agent/default_factory.py b/vocode/streaming/agent/default_factory.py new file mode 100644 index 000000000..c862a5cc5 --- /dev/null +++ b/vocode/streaming/agent/default_factory.py @@ -0,0 +1,27 @@ +from vocode.streaming.agent.abstract_factory import AbstractAgentFactory +from vocode.streaming.agent.anthropic_agent import AnthropicAgent +from vocode.streaming.agent.base_agent import BaseAgent +from vocode.streaming.agent.chat_gpt_agent import ChatGPTAgent +from vocode.streaming.agent.echo_agent import EchoAgent +from vocode.streaming.agent.restful_user_implemented_agent import RESTfulUserImplementedAgent +from vocode.streaming.models.agent import ( + AgentConfig, + AnthropicAgentConfig, + ChatGPTAgentConfig, + EchoAgentConfig, + LlamacppAgentConfig, + RESTfulUserImplementedAgentConfig, +) + + +class DefaultAgentFactory(AbstractAgentFactory): + def create_agent(self, agent_config: AgentConfig) -> BaseAgent: + if isinstance(agent_config, ChatGPTAgentConfig): + return ChatGPTAgent(agent_config=agent_config) + elif isinstance(agent_config, EchoAgentConfig): + return EchoAgent(agent_config=agent_config) + elif isinstance(agent_config, RESTfulUserImplementedAgentConfig): + return RESTfulUserImplementedAgent(agent_config=agent_config) + elif isinstance(agent_config, AnthropicAgentConfig): + return AnthropicAgent(agent_config=agent_config) + raise Exception("Invalid agent config", agent_config.type) diff --git a/vocode/streaming/agent/echo_agent.py b/vocode/streaming/agent/echo_agent.py index cd4930dff..010925773 100644 --- a/vocode/streaming/agent/echo_agent.py +++ b/vocode/streaming/agent/echo_agent.py @@ -1,6 +1,8 @@ -from typing import AsyncGenerator, Generator, Optional, Tuple -from vocode.streaming.agent.base_agent import BaseAgent, RespondAgent +from typing import AsyncGenerator, Tuple + +from vocode.streaming.agent.base_agent import GeneratedResponse, RespondAgent from vocode.streaming.models.agent import EchoAgentConfig +from vocode.streaming.models.message import BaseMessage class EchoAgent(RespondAgent[EchoAgentConfig]): @@ -17,8 +19,9 @@ async def generate_response( human_input, conversation_id: str, is_interrupt: bool = False, - ) -> AsyncGenerator[Tuple[str, bool], None]: - yield human_input, True + bot_was_in_medias_res: bool = False, + ) -> AsyncGenerator[GeneratedResponse, None]: + yield GeneratedResponse(message=BaseMessage(text=human_input), is_interruptible=True) def update_last_bot_message_on_cut_off(self, message: str): pass diff --git a/vocode/streaming/agent/factory.py b/vocode/streaming/agent/factory.py deleted file mode 100644 index 6acd75af1..000000000 --- a/vocode/streaming/agent/factory.py +++ /dev/null @@ -1,45 +0,0 @@ -import logging -from typing import Optional -import typing -from vocode.streaming.agent.anthropic_agent import ChatAnthropicAgent -from vocode.streaming.agent.base_agent import BaseAgent -from vocode.streaming.agent.chat_gpt_agent import ChatGPTAgent -from vocode.streaming.agent.echo_agent import EchoAgent -from vocode.streaming.agent.information_retrieval_agent import InformationRetrievalAgent -from vocode.streaming.agent.llm_agent import LLMAgent -from vocode.streaming.agent.restful_user_implemented_agent import ( - RESTfulUserImplementedAgent, -) -from vocode.streaming.agent.llamacpp_agent import LlamacppAgent -from vocode.streaming.models.agent import ( - AgentConfig, - AgentType, - ChatAnthropicAgentConfig, - ChatGPTAgentConfig, - EchoAgentConfig, - InformationRetrievalAgentConfig, - LLMAgentConfig, - RESTfulUserImplementedAgentConfig, - LlamacppAgentConfig, -) - - -class AgentFactory: - def create_agent( - self, agent_config: AgentConfig, logger: Optional[logging.Logger] = None - ) -> BaseAgent: - if isinstance(agent_config, LLMAgentConfig): - return LLMAgent(agent_config=agent_config, logger=logger) - elif isinstance(agent_config, ChatGPTAgentConfig): - return ChatGPTAgent(agent_config=agent_config, logger=logger) - elif isinstance(agent_config, EchoAgentConfig): - return EchoAgent(agent_config=agent_config, logger=logger) - elif isinstance(agent_config, InformationRetrievalAgentConfig): - return InformationRetrievalAgent(agent_config=agent_config, logger=logger) - elif isinstance(agent_config, RESTfulUserImplementedAgentConfig): - return RESTfulUserImplementedAgent(agent_config=agent_config, logger=logger) - elif isinstance(agent_config, ChatAnthropicAgentConfig): - return ChatAnthropicAgent(agent_config=agent_config, logger=logger) - elif isinstance(agent_config, LlamacppAgentConfig): - return LlamacppAgent(agent_config=agent_config, logger=logger) - raise Exception("Invalid agent config", agent_config.type) diff --git a/vocode/streaming/agent/goodbye.py b/vocode/streaming/agent/goodbye.py new file mode 100644 index 000000000..840469c80 --- /dev/null +++ b/vocode/streaming/agent/goodbye.py @@ -0,0 +1,13 @@ +import re +from typing import List, Optional + +_GOODBYE_PHRASES = [ + "bye", +] + + +def is_goodbye_simple(message: str, phrases: Optional[List[str]]): + if not phrases: + phrases = _GOODBYE_PHRASES + cleaned = re.sub(r"[^\w\s]", "", message.lower()) + return any(phrase in cleaned for phrase in phrases) diff --git a/vocode/streaming/agent/gpt4all_agent.py b/vocode/streaming/agent/gpt4all_agent.py index 61087fb8f..f87d8d24f 100644 --- a/vocode/streaming/agent/gpt4all_agent.py +++ b/vocode/streaming/agent/gpt4all_agent.py @@ -1,8 +1,11 @@ from typing import Optional, Tuple -from vocode.streaming.agent.base_agent import BaseAgent, RespondAgent + +from vocode.streaming.agent.base_agent import RespondAgent from vocode.streaming.models.agent import GPT4AllAgentConfig from vocode.turn_based.agent.gpt4all_agent import GPT4AllAgent as TurnBasedGPT4AllAgent +raise DeprecationWarning("This Agent is deprecated and will be removed in the future.") + class GPT4AllAgent(RespondAgent[GPT4AllAgentConfig]): def __init__(self, agent_config: GPT4AllAgentConfig): @@ -11,9 +14,7 @@ def __init__(self, agent_config: GPT4AllAgentConfig): model_path=agent_config.model_path, system_prompt=agent_config.prompt_preamble, initial_message=( - agent_config.initial_message.text - if agent_config.initial_message - else None + agent_config.initial_message.text if agent_config.initial_message else None ), ) diff --git a/vocode/streaming/agent/information_retrieval_agent.py b/vocode/streaming/agent/information_retrieval_agent.py deleted file mode 100644 index 3bfb8861f..000000000 --- a/vocode/streaming/agent/information_retrieval_agent.py +++ /dev/null @@ -1,34 +0,0 @@ -import logging -from typing import List, Optional - -from langchain import OpenAI -from vocode.streaming.agent.llm_agent import LLMAgent -from ..models.agent import InformationRetrievalAgentConfig, LLMAgentConfig - - -class InformationRetrievalAgent(LLMAgent): - def __init__( - self, - agent_config: InformationRetrievalAgentConfig, - logger: Optional[logging.Logger] = None, - ): - # super().__init__(agent_config, logger) - prompt_preamble = f""" - The AI is a friendly phone bot built for information retrieval. It understands IVR navigation and chooses which numbers to press based on the intended goal and the options provided. -Once it reaches the human, it verifies the identity of the person it is trying to reach and states its purpose. If it needs to be transferred, then the AI asks to speak to the intended recipient of the phone call. - -Here is the context for the call: -Intended goal: { agent_config.goal_description } -Intended recipient: { agent_config.recipient_descriptor } -Information to be collected: { agent_config.fields } -Information to provide to the person who answers the phone: this is a robot calling on behalf of { agent_config.caller_descriptor } - -The AI begins the call by introducing itself and who it represents. - """ - super().__init__( - LLMAgentConfig( - prompt_preamble=prompt_preamble, - ), - logger=logger, - ) - self.llm = OpenAI(model_name="text-davinci-003", temperature=1) # type: ignore diff --git a/vocode/streaming/agent/llamacpp_agent.py b/vocode/streaming/agent/llamacpp_agent.py index c7f577733..8b04756b6 100644 --- a/vocode/streaming/agent/llamacpp_agent.py +++ b/vocode/streaming/agent/llamacpp_agent.py @@ -1,30 +1,29 @@ -from concurrent.futures import ThreadPoolExecutor import asyncio -import logging -from typing import AsyncGenerator, Optional, Tuple, Any, Union import typing +from concurrent.futures import ThreadPoolExecutor +from typing import Any, AsyncGenerator, Optional, Tuple, Union + from langchain import ConversationChain -from vocode.streaming.agent.base_agent import RespondAgent -from vocode.streaming.models.agent import LlamacppAgentConfig -from vocode.streaming.agent.utils import collate_response_async from langchain.callbacks.base import BaseCallbackHandler from langchain.callbacks.manager import CallbackManager from langchain.llms import LlamaCpp -from langchain.prompts import ( - ChatPromptTemplate, - MessagesPlaceholder, - HumanMessagePromptTemplate, -) -from pydantic.v1 import BaseModel -from langchain.schema import LLMResult, SystemMessage, get_buffer_string from langchain.memory import ConversationBufferMemory from langchain.prompts import ( ChatPromptTemplate, - MessagesPlaceholder, HumanMessagePromptTemplate, + MessagesPlaceholder, PromptTemplate, ) +from langchain.schema import LLMResult, SystemMessage, get_buffer_string from langchain_core.prompts.string import DEFAULT_FORMATTER_MAPPING +from loguru import logger +from pydantic.v1 import BaseModel + +from vocode.streaming.agent.base_agent import RespondAgent +from vocode.streaming.agent.streaming_utils import collate_response_async +from vocode.streaming.models.agent import LlamacppAgentConfig + +raise DeprecationWarning("This Agent is deprecated and will be removed in the future.") ALPACA_TEMPLATE_WITH_HISTORY = """### Instruction: Your previous conversation history: @@ -65,9 +64,8 @@ class LlamacppAgent(RespondAgent[LlamacppAgentConfig]): def __init__( self, agent_config: LlamacppAgentConfig, - logger: Optional[logging.Logger] = None, ): - super().__init__(agent_config=agent_config, logger=logger) + super().__init__(agent_config=agent_config) self.prompt: Union[PromptTemplate, ChatPromptTemplate] if type(agent_config.prompt_template) is str: @@ -77,9 +75,7 @@ def __init__( template=ALPACA_TEMPLATE_WITH_HISTORY, ) else: - raise ValueError( - f"Unknown prompt template {agent_config.prompt_template}" - ) + raise ValueError(f"Unknown prompt template {agent_config.prompt_template}") else: if agent_config.prompt_template is None: self.prompt = ChatPromptTemplate.from_messages( @@ -94,18 +90,14 @@ def __init__( self.callback_queue: asyncio.Queue = asyncio.Queue() callback = CustomStreamingCallbackHandler(self.callback_queue) callback_manager = CallbackManager([callback]) - self.llm = LlamaCpp( - callback_manager=callback_manager, **agent_config.llamacpp_kwargs - ) + self.llm = LlamaCpp(callback_manager=callback_manager, **agent_config.llamacpp_kwargs) self.memory = ConversationBufferMemory(return_messages=True) self.memory.chat_memory.messages.append( SystemMessage(content=self.agent_config.prompt_preamble) ) - self.conversation = ConversationChain( - memory=self.memory, prompt=self.prompt, llm=self.llm - ) + self.conversation = ConversationChain(memory=self.memory, prompt=self.prompt, llm=self.llm) self.thread_pool_executor = ThreadPoolExecutor(max_workers=1) async def respond( @@ -120,7 +112,7 @@ async def respond( human_input, ) - self.logger.debug(f"LLM response: {text}") + logger.debug(f"LLM response: {text}") return text, False async def llamacpp_get_tokens(self): diff --git a/vocode/streaming/agent/llm_agent.py b/vocode/streaming/agent/llm_agent.py deleted file mode 100644 index a3d510da2..000000000 --- a/vocode/streaming/agent/llm_agent.py +++ /dev/null @@ -1,156 +0,0 @@ -import re -from typing import AsyncGenerator, Optional, Tuple - -from langchain import OpenAI -from typing import Generator -import logging - -import openai -from vocode import getenv - -from vocode.streaming.agent.base_agent import BaseAgent, RespondAgent -from vocode.streaming.agent.utils import collate_response_async, openai_get_tokens -from vocode.streaming.models.agent import LLMAgentConfig - - -class LLMAgent(RespondAgent[LLMAgentConfig]): - SENTENCE_ENDINGS = [".", "!", "?"] - - DEFAULT_PROMPT_TEMPLATE = "{history}\nHuman: {human_input}\nAI:" - - def __init__( - self, - agent_config: LLMAgentConfig, - logger: Optional[logging.Logger] = None, - sender="AI", - recipient="Human", - openai_api_key: Optional[str] = None, - ): - super().__init__(agent_config) - self.prompt_template = ( - f"{agent_config.prompt_preamble}\n\n{self.DEFAULT_PROMPT_TEMPLATE}" - ) - self.initial_bot_message = ( - agent_config.initial_message.text if agent_config.initial_message else None - ) - self.logger = logger or logging.getLogger(__name__) - self.sender = sender - self.recipient = recipient - self.memory = ( - [f"AI: {agent_config.initial_message.text}"] - if agent_config.initial_message - else [] - ) - openai_api_key = openai_api_key or getenv("OPENAI_API_KEY") - if not openai_api_key: - raise ValueError("OPENAI_API_KEY must be set in environment or passed in") - self.llm = OpenAI( # type: ignore - model_name=self.agent_config.model_name, - temperature=self.agent_config.temperature, - max_tokens=self.agent_config.max_tokens, - openai_api_key=openai_api_key, - ) - self.stop_tokens = [f"{recipient}:"] - self.first_response = ( - self.llm( - self.prompt_template.format( - history="", human_input=agent_config.expected_first_prompt - ), - stop=self.stop_tokens, - ).strip() - if agent_config.expected_first_prompt - else None - ) - self.is_first_response = True - - def create_prompt(self, human_input): - history = "\n".join(self.memory[-5:]) - return self.prompt_template.format(history=history, human_input=human_input) - - def get_memory_entry(self, human_input, response): - return f"{self.recipient}: {human_input}\n{self.sender}: {response}" - - async def respond( - self, - human_input, - conversation_id: str, - is_interrupt: bool = False, - ) -> Tuple[str, bool]: - if is_interrupt and self.agent_config.cut_off_response: - cut_off_response = self.get_cut_off_response() - self.memory.append(self.get_memory_entry(human_input, cut_off_response)) - return cut_off_response, False - self.logger.debug("LLM responding to human input") - if self.is_first_response and self.first_response: - self.logger.debug("First response is cached") - self.is_first_response = False - response = self.first_response - else: - response = ( - ( - await self.llm.agenerate( - [self.create_prompt(human_input)], stop=self.stop_tokens - ) - ) - .generations[0][0] - .text - ) - response = response.replace(f"{self.sender}:", "") - self.memory.append(self.get_memory_entry(human_input, response)) - self.logger.debug(f"LLM response: {response}") - return response, False - - async def _stream_sentences(self, prompt): - stream = await openai.Completion.acreate( - prompt=prompt, - max_tokens=self.agent_config.max_tokens, - temperature=self.agent_config.temperature, - model=self.agent_config.model_name, - stop=self.stop_tokens, - stream=True, - ) - async for sentence in collate_response_async( - openai_get_tokens(gen=stream), - ): - yield sentence - - async def _agen_from_list(self, l): - for item in l: - yield item - - async def generate_response( - self, - human_input, - conversation_id: str, - is_interrupt: bool = False, - ) -> AsyncGenerator[Tuple[str, bool], None]: - self.logger.debug("LLM generating response to human input") - if is_interrupt and self.agent_config.cut_off_response: - cut_off_response = self.get_cut_off_response() - self.memory.append(self.get_memory_entry(human_input, cut_off_response)) - yield cut_off_response, False - return - self.memory.append(self.get_memory_entry(human_input, "")) - if self.is_first_response and self.first_response: - self.logger.debug("First response is cached") - self.is_first_response = False - sentences = self._agen_from_list([self.first_response]) - else: - self.logger.debug("Creating LLM prompt") - prompt = self.create_prompt(human_input) - self.logger.debug("Streaming LLM response") - sentences = self._stream_sentences(prompt) - response_buffer = "" - async for sentence in sentences: - sentence = sentence.replace(f"{self.sender}:", "") - sentence = re.sub(r"^\s+(.*)", r" \1", sentence) - response_buffer += sentence - self.memory[-1] = self.get_memory_entry(human_input, response_buffer) - yield sentence, True - - def update_last_bot_message_on_cut_off(self, message: str): - last_message = self.memory[-1] - new_last_message = ( - last_message.split("\n", 1)[0] + f"\n{self.sender}: {message}" - ) - self.memory[-1] = new_last_message diff --git a/vocode/streaming/agent/openai_utils.py b/vocode/streaming/agent/openai_utils.py new file mode 100644 index 000000000..5264e68bd --- /dev/null +++ b/vocode/streaming/agent/openai_utils.py @@ -0,0 +1,179 @@ +from copy import deepcopy +from typing import Any, AsyncGenerator, Dict, List, Optional, Union + +from loguru import logger +from openai.types.chat.chat_completion_chunk import ChatCompletionChunk + +from vocode.streaming.agent.token_utils import ( + get_chat_gpt_max_tokens, + num_tokens_from_functions, + num_tokens_from_messages, +) +from vocode.streaming.models.actions import FunctionFragment, PhraseBasedActionTrigger +from vocode.streaming.models.agent import LLM_AGENT_DEFAULT_MAX_TOKENS +from vocode.streaming.models.events import Sender +from vocode.streaming.models.transcript import ( + ActionFinish, + ActionStart, + ConferenceEvent, + EventLog, + Message, + Transcript, +) + + +def vector_db_result_to_openai_chat_message(vector_db_result): + return {"role": "user", "content": vector_db_result} + + +def is_phrase_based_action_event_log(event_log: EventLog) -> bool: + return ( + (isinstance(event_log, ActionStart) or isinstance(event_log, ActionFinish)) + and event_log.action_input is not None + and event_log.action_input.action_config is not None + and isinstance( + event_log.action_input.action_config.action_trigger, PhraseBasedActionTrigger + ) + ) + + +def get_openai_chat_messages_from_transcript( + merged_event_logs: List[EventLog], + prompt_preamble: str, +) -> List[dict]: + chat_messages = [{"role": "system", "content": prompt_preamble}] + for event_log in merged_event_logs: + if isinstance(event_log, Message): + if len(event_log.text.strip()) == 0: + continue + else: + chat_messages.append( + { + "role": ("assistant" if event_log.sender == Sender.BOT else "user"), + "content": event_log.to_string(include_sender=False), + }, + ) + elif isinstance(event_log, ActionStart): + action_message: Dict[str, Any] + if is_phrase_based_action_event_log(event_log=event_log): + pass + else: + action_message = { + "role": "assistant", + "content": None, + "function_call": { + "name": event_log.action_type, + "arguments": event_log.action_input.params.json(), + }, + } + chat_messages.append(action_message) + elif isinstance(event_log, ActionFinish): + action_message = { + "role": "function", + "name": event_log.action_type, + "content": event_log.to_string(include_header=False), + } + chat_messages.append(action_message) + elif isinstance(event_log, ConferenceEvent): + chat_messages.append( + {"role": "user", "content": event_log.to_string(include_sender=False)}, + ) + return chat_messages + + +def merge_event_logs(event_logs: List[EventLog]) -> List[EventLog]: + """Returns a new list of event logs where consecutive bot messages are merged.""" + new_event_logs: List[EventLog] = [] + idx = 0 + while idx < len(event_logs): + bot_messages_buffer: List[Message] = [] + current_log = event_logs[idx] + while isinstance(current_log, Message) and current_log.sender == Sender.BOT: + bot_messages_buffer.append(current_log) + idx += 1 + try: + current_log = event_logs[idx] + except IndexError: + break + if bot_messages_buffer: + merged_bot_message = deepcopy(bot_messages_buffer[-1]) + merged_bot_message.text = " ".join(event_log.text for event_log in bot_messages_buffer) + new_event_logs.append(merged_bot_message) + else: + new_event_logs.append(current_log) + idx += 1 + + return new_event_logs + + +def format_openai_chat_messages_from_transcript( + transcript: Transcript, + model_name: str, + functions: Optional[List[Dict]], + prompt_preamble: str, +) -> List[dict]: + # merge consecutive bot messages + merged_event_logs: List[EventLog] = merge_event_logs(event_logs=transcript.event_logs) + + chat_messages: List[Dict[str, Optional[Any]]] + chat_messages = get_openai_chat_messages_from_transcript( + merged_event_logs=merged_event_logs, + prompt_preamble=prompt_preamble, + ) + + context_size = num_tokens_from_messages( + messages=chat_messages, + model=model_name, + ) + num_tokens_from_functions(functions=functions, model=model_name) + + num_removed_messages = 0 + while ( + context_size > get_chat_gpt_max_tokens(model_name) - LLM_AGENT_DEFAULT_MAX_TOKENS - 50 + ): # context limit includes the max tokens, and 50 for safety + if len(chat_messages) <= 1: + logger.error(f"Prompt is too long to fit in context window, num tokens {context_size}") + break + num_removed_messages += 1 + chat_messages.pop(1) + context_size = num_tokens_from_messages( + messages=chat_messages, + model=model_name, + ) + num_tokens_from_functions(functions=functions, model=model_name) + + if num_removed_messages > 0: + logger.info( + "Removed %d messages from prompt to satisfy context limit", + num_removed_messages, + ) + + return chat_messages + + +async def openai_get_tokens( + gen: AsyncGenerator[ChatCompletionChunk, None], +) -> AsyncGenerator[Union[str, FunctionFragment], None]: + async for event in gen: + choices = event.choices + if len(choices) == 0: + continue + choice = choices[0] + if choice.finish_reason: + if choice.finish_reason == "content_filter": + logger.warning( + "Detected content filter.", + extra={"chat_completion_chunk": event.model_dump()}, + ) + break + delta = choice.delta + if delta.content is not None: + token = delta.content + yield token + elif delta.function_call is not None: + yield FunctionFragment( + name=(delta.function_call.name if delta.function_call.name is not None else ""), + arguments=( + delta.function_call.arguments + if delta.function_call.arguments is not None + else "" + ), + ) diff --git a/vocode/streaming/agent/phrase_trigger.py b/vocode/streaming/agent/phrase_trigger.py new file mode 100644 index 000000000..0d9587f77 --- /dev/null +++ b/vocode/streaming/agent/phrase_trigger.py @@ -0,0 +1,21 @@ +import re +from typing import List, Optional + +from vocode.streaming.models.actions import ActionConfig, PhraseBasedActionTrigger + + +def matches_phrase_trigger( + message: str, + action_configs: List[ActionConfig], +) -> Optional[str]: + cleaned = re.sub(r"[^\w\s]", "", message.lower()) + for action_config in action_configs: + if not isinstance(action_config.action_trigger, PhraseBasedActionTrigger): + continue + + for phrase_trigger in action_config.action_trigger.config.phrase_triggers: + lowered = phrase_trigger.phrase.lower() + for condition in phrase_trigger.conditions: + if condition == "phrase_condition_type_contains" and lowered in cleaned: + return action_config.type + return None diff --git a/vocode/streaming/agent/prompts/action_prompt.py b/vocode/streaming/agent/prompts/action_prompt.py deleted file mode 100644 index df3c2378c..000000000 --- a/vocode/streaming/agent/prompts/action_prompt.py +++ /dev/null @@ -1,24 +0,0 @@ -ACTION_PROMPT_DEFAULT = """ -The assistant is on a live conversation with a human that is taking place via voice (eg via phone call). It is -a helpful assistant that will help the human with their needs. In every response, the assistant does 2 things: -- respond to the customer with a message -- decide to take an appropriate action (or none, if it isn't necessary) - -The following are the possible actions the assistant can take: -{actions} - -ALL of the assistant's responses should look like the following (and should include "Response", "Action", and "Action parameters"): - -Response: Yes! Let me look up that information for you. -Action: look_up_information -Action parameters: "parameter 1|parameter 2|parameter 3" - -If no action is necessary, the assistant responds with the message and leaves the action blank like so: - -Response: Hey! How can I help you today? -Action: -Action parameters: - -Here's the transcript so far: -{transcript} -""" diff --git a/vocode/streaming/agent/restful_user_implemented_agent.py b/vocode/streaming/agent/restful_user_implemented_agent.py index 126087dd0..02999617c 100644 --- a/vocode/streaming/agent/restful_user_implemented_agent.py +++ b/vocode/streaming/agent/restful_user_implemented_agent.py @@ -1,29 +1,28 @@ -from .base_agent import BaseAgent, RespondAgent -from ..models.agent import ( - RESTfulUserImplementedAgentConfig, +from typing import Optional, Tuple, cast + +import aiohttp +from loguru import logger + +from vocode.streaming.agent.base_agent import RespondAgent +from vocode.streaming.models.agent import ( RESTfulAgentInput, RESTfulAgentOutput, RESTfulAgentOutputType, RESTfulAgentText, + RESTfulUserImplementedAgentConfig, ) -from typing import Generator, Optional, Tuple, cast -import requests -import logging -import aiohttp class RESTfulUserImplementedAgent(RespondAgent[RESTfulUserImplementedAgentConfig]): def __init__( self, agent_config: RESTfulUserImplementedAgentConfig, - logger=None, ): super().__init__(agent_config) if self.agent_config.generate_responses: raise NotImplementedError( "Use the WebSocket user implemented agent to stream responses" ) - self.logger = logger or logging.getLogger(__name__) async def respond( self, @@ -45,9 +44,7 @@ async def respond( timeout=aiohttp.ClientTimeout(total=15), ) as response: assert response.status == 200 - output: RESTfulAgentOutput = RESTfulAgentOutput.parse_obj( - await response.json() - ) + output: RESTfulAgentOutput = RESTfulAgentOutput.parse_obj(await response.json()) output_response = None should_stop = False if output.type == RESTfulAgentOutputType.TEXT: @@ -56,5 +53,5 @@ async def respond( should_stop = True return output_response, should_stop except Exception as e: - self.logger.error(f"Error in response from RESTful agent: {e}") + logger.error(f"Error in response from RESTful agent: {e}") return None, True diff --git a/vocode/streaming/agent/streaming_utils.py b/vocode/streaming/agent/streaming_utils.py new file mode 100644 index 000000000..ac0dee34c --- /dev/null +++ b/vocode/streaming/agent/streaming_utils.py @@ -0,0 +1,139 @@ +import re +from typing import AsyncGenerator, AsyncIterable, List, Literal, Optional, Union + +from sentry_sdk.tracing import Span + +from vocode.streaming.models.actions import FunctionCall, FunctionFragment + +TOKENS_TO_GENERATE_PAST_PERIOD = 3 +SENTENCE_ENDINGS_EXCEPT_PERIOD_PATTERN = r"[?!\n\t\r]" + + +SHORT_SENTENCE_CUTOFF = 3 + + +def split_sentences(text: str) -> List[str]: + """Splits text into sentences and preserve trailing periods. + + Merge sentences that are just numbers, as they are part of lists. + """ + initial_split = text.split(". ") + + final_split = [] + buffer = "" + + for i, sentence in enumerate(initial_split): + is_last = i == len(initial_split) - 1 + buffer += sentence + if not is_last: + buffer += ". " + if not re.fullmatch(r"\d+", sentence.strip()): + final_split.append(buffer.strip()) + buffer = "" + + if buffer.strip(): + final_split.append(buffer.strip()) + + return [sentence for sentence in final_split if sentence] + + +async def collate_response_async( + conversation_id: str, + gen: AsyncIterable[Union[str, FunctionFragment]], + get_functions: Literal[True, False] = False, + sentry_span: Optional[Span] = None, +) -> AsyncGenerator[ + Union[str, FunctionCall], + None, +]: # tuple of message to send and whether it's the final message + buffer = "" + function_name_buffer = "" + function_args_buffer = "" + is_post_period = False + tokens_since_period = 0 + is_first = True + async for token in gen: + if is_first: + if sentry_span: + sentry_span.finish() + is_first = False + if not token: + continue + if isinstance(token, str): + buffer += token + if len(buffer.strip().split()) < SHORT_SENTENCE_CUTOFF: + continue + if re.search(SENTENCE_ENDINGS_EXCEPT_PERIOD_PATTERN, token): + # split on last occurrence of sentence ending + matches = [ + match for match in re.finditer(SENTENCE_ENDINGS_EXCEPT_PERIOD_PATTERN, buffer) + ] + last_match = matches[-1] + split_point = last_match.start() + 1 + to_keep, to_return = buffer[split_point:], buffer[:split_point] + if to_return.strip(): + yield to_return.strip() + buffer = to_keep + elif "." in token: + is_post_period = True + tokens_since_period = 0 + + if is_post_period and tokens_since_period > TOKENS_TO_GENERATE_PAST_PERIOD: + sentences = split_sentences(buffer) + if len(sentences) > 1: + yield " ".join(sentences[:-1]) + buffer = sentences[-1] + is_post_period = False + tokens_since_period = 0 + else: + tokens_since_period += 1 + + elif isinstance(token, FunctionFragment): + function_name_buffer += token.name + function_args_buffer += token.arguments + to_return = buffer.strip() + if to_return: + yield to_return + if function_name_buffer and get_functions: + yield FunctionCall(name=function_name_buffer, arguments=function_args_buffer) + + +async def stream_response_async( + conversation_id: str, + gen: AsyncIterable[Union[str, FunctionFragment]], + get_functions: Literal[True, False] = False, + sentry_span: Optional[Span] = None, +) -> AsyncGenerator[ + Union[str, FunctionCall], + None, +]: # tuple of message to send and whether it's the final message + splitters = (".", ",", "?", "!", ";", ":", "—", "-", "(", ")", "[", "]", "}", " ") + buffer = "" + function_name_buffer = "" + function_args_buffer = "" + is_first = True + async for token in gen: + if is_first: + if sentry_span: + sentry_span.finish() + is_first = False + if not token: + continue + if isinstance(token, str): + if buffer.endswith(splitters): + yield buffer if buffer.endswith(" ") else buffer + " " + buffer = token + elif token.startswith(splitters): + output = buffer + token[0] + yield output if output.endswith(" ") else output + " " + buffer = token[1:] + else: + buffer += token + + elif isinstance(token, FunctionFragment): + function_name_buffer += token.name + function_args_buffer += token.arguments + if buffer != "": + yield buffer + " " + if function_name_buffer and get_functions: + yield FunctionCall(name=function_name_buffer, arguments=function_args_buffer) diff --git a/vocode/streaming/agent/token_utils.py b/vocode/streaming/agent/token_utils.py new file mode 100644 index 000000000..7cd80f8cc --- /dev/null +++ b/vocode/streaming/agent/token_utils.py @@ -0,0 +1,252 @@ +"""Utilities for chat_gpt_agent, mostly around token counting for cost estimation purposes.""" + +import json +import textwrap +from typing import Any, Dict, List, NamedTuple, Optional + +import tiktoken +from loguru import logger + +# THE FOLLOWING CODE, UNTIL THE END MARKER, WERE RETRIEVED ON 9/13/2023 FROM +# THE OPENAI COOKBOOK UNDER THE MIT LICENSE. +# MIT License + +# Copyright (c) 2023 OpenAI + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +# Used to count the amount of tokens Actions add to the billable cost +_FUNCTION_OVERHEAD_STR = """# Tools + +## functions + +namespace functions { + +} // namespace functions""" + +CHAT_GPT_MAX_TOKENS = { + "gpt-3.5-turbo-0613": 4050, + "gpt-3.5-turbo-16k-0613": 16340, + "gpt-3.5-turbo-16k": 16340, + "gpt-3.5-turbo": 16340, + "gpt-3.5-turbo-1106": 16340, + "gpt-3.5-turbo-0125": 16340, + "gpt-4-0314": 8150, + "gpt-4-32k-0314": 32700, + "gpt-4-0613": 8150, + "gpt-4-32k-0613": 32700, + "gpt-4-0125-preview": 127940, + "gpt-4-turbo": 127940, + "gpt-4o": 127940, + "gpt-4o-2024-05-13": 127940, +} + + +def get_chat_gpt_max_tokens(model_name: str): + if model_name.startswith("ft:"): + model_name = model_name.split(":")[1] + + if model_name in CHAT_GPT_MAX_TOKENS: + return CHAT_GPT_MAX_TOKENS[model_name] + + return 4050 + + +TokenizerInfo = NamedTuple( + "TokenizerInfo", + [ + ("encoding", tiktoken.Encoding), + ("tokens_per_message", int), + ("tokens_per_name", int), + ], +) + + +def get_tokenizer_info(model: str) -> Optional[TokenizerInfo]: + if "gpt-35-turbo" in model: + model = "gpt-3.5-turbo" + elif "gpt-4o" == model: + model = "gpt-4o" + elif "gpt4" in model or "gpt-4" in model: + model = "gpt-4" + try: + encoding = tiktoken.encoding_for_model(model) + except KeyError: + logger.warning("Warning: model not found. Using cl100k_base encoding.") + encoding = tiktoken.get_encoding("cl100k_base") + if model in { + "gpt-3.5-turbo-0613", + "gpt-3.5-turbo-16k-0613", + "gpt-4-0314", + "gpt-4-32k-0314", + "gpt-4-0613", + "gpt-4-32k-0613", + }: + tokens_per_message = 3 + tokens_per_name = 1 + elif model == "gpt-3.5-turbo-0301": + tokens_per_message = 4 # every message follows <|start|>{role/name}\n{content}<|end|>\n + tokens_per_name = -1 # if there's a name, the role is omitted + elif "gpt-3.5-turbo" in model: + logger.debug( + "Warning: gpt-3.5-turbo may update over time. Returning num tokens assuming gpt-3.5-turbo-0613." + ) + tokens_per_message = 3 + tokens_per_name = 1 + elif "gpt-4" in model: + logger.debug( + "Warning: gpt-4 may update over time. Returning num tokens assuming gpt-4-0613." + ) + tokens_per_message = 3 + tokens_per_name = 1 + else: + return None + + return TokenizerInfo( + encoding=encoding, + tokens_per_message=tokens_per_message, + tokens_per_name=tokens_per_name, + ) + + +def num_tokens_from_messages(messages: List[dict], model: str = "gpt-3.5-turbo-0613"): + """Return the number of tokens used by a list of messages.""" + tokenizer_info = get_tokenizer_info(model) + if tokenizer_info is None: + raise NotImplementedError( + f"""num_tokens_from_messages() is not implemented for model {model}. See https://github.com/openai/openai-python/blob/main/chatml.md for information on how messages are converted to tokens.""" + ) + num_tokens = 0 + for message in messages: + num_tokens += tokenizer_info.tokens_per_message + num_tokens += tokens_from_dict( + encoding=tokenizer_info.encoding, + d=message, + tokens_per_name=tokenizer_info.tokens_per_name, + ) + num_tokens += 3 # every reply is primed with <|start|>assistant<|message|> + return num_tokens + + +# END OF OPENAI COOKBOOK CODE AND GIVEN MIT LICENSE. + + +def tokens_from_dict(encoding: tiktoken.Encoding, d: Dict[str, Any], tokens_per_name: int) -> int: + """Return the number of OpenAI tokens in a dict.""" + num_tokens: int = 0 + for key, value in d.items(): + if value is None: + continue + if isinstance(value, str): + num_tokens += len(encoding.encode(value)) + if key == "name": + num_tokens += tokens_per_name + elif isinstance(value, dict): + num_tokens += tokens_from_dict( + encoding=encoding, d=value, tokens_per_name=tokens_per_name + ) + + return num_tokens + + +def num_tokens_from_functions(functions: List[dict] | None, model="gpt-3.5-turbo-0613") -> int: + """Return the number of tokens used by a list of functions.""" + if not functions: + return 0 + + try: + encoding = tiktoken.encoding_for_model(model) + except KeyError: + logger.warning("Warning: model not found. Using cl100k_base encoding.") + encoding = tiktoken.get_encoding("cl100k_base") + + function_overhead = 3 + len(encoding.encode(_FUNCTION_OVERHEAD_STR)) + + return function_overhead + sum( + len(encoding.encode(_format_func_into_prompt_str(func=f))) for f in functions + ) + + +# Calculates the amount of tokens added to a given OpenAI prompt for functions +# specifically for billing purposes +def _format_func_into_prompt_str(func) -> str: + def resolve_ref(schema): + if schema.get("$ref") is not None: + ref = schema["$ref"][14:] + schema = json_schema["definitions"][ref] + return schema + + def format_schema(schema, indent): + schema = resolve_ref(schema) + if "enum" in schema: + return format_enum(schema, indent) + elif schema["type"] == "object": + return format_object(schema, indent) + elif schema["type"] == "integer": + return "number" + elif schema["type"] == "boolean": + return "boolean" + elif schema["type"] in ["string", "number"]: + return schema["type"] + elif schema["type"] == "array": + return format_schema(schema["items"], indent) + "[]" + else: + raise ValueError("unknown schema type " + schema["type"]) + + def format_enum(schema, indent): + return " | ".join(json.dumps(o) for o in schema["enum"]) + + def format_object(schema, indent): + result = "{\n" + if "properties" not in schema or len(schema["properties"]) == 0: + if schema.get("additionalProperties", False): + return "object" + return None + for key, value in schema["properties"].items(): + value = resolve_ref(value) + value_rendered = format_schema(value, indent + 1) + if value_rendered is None: + continue + if "description" in value and indent == 0: + for line in textwrap.dedent(value["description"]).strip().split("\n"): + result += f"{' '*indent}// {line}\n" + optional = "" if key in schema.get("required", {}) else "?" + comment = ( + "" if value.get("default") is None else f" // default: {format_default(value)}" + ) + result += f"{' '*indent}{key}{optional}: {value_rendered},{comment}\n" + result += (" " * (indent - 1)) + "}" + return result + + def format_default(schema): + v = schema["default"] + if schema["type"] == "number": + return f"{v:.1f}" if float(v).is_integer() else str(v) + else: + return str(v) + + json_schema = func["parameters"] + result = f"// {func['description']}\ntype {func['name']} = (" + formatted = format_object(json_schema, 0) + if formatted is not None: + result += "_: " + formatted + result += ") => any;\n\n" + return result diff --git a/vocode/streaming/agent/utils.py b/vocode/streaming/agent/utils.py deleted file mode 100644 index 0ce4df77f..000000000 --- a/vocode/streaming/agent/utils.py +++ /dev/null @@ -1,182 +0,0 @@ -from copy import deepcopy -import re -from typing import ( - Dict, - Any, - AsyncGenerator, - AsyncIterable, - Callable, - List, - Literal, - Optional, - TypeVar, - Union, -) - -from openai.openai_object import OpenAIObject -from vocode.streaming.models.actions import FunctionCall, FunctionFragment -from vocode.streaming.models.events import Sender -from vocode.streaming.models.transcript import ( - ActionFinish, - ActionStart, - EventLog, - Message, - Transcript, -) - -SENTENCE_ENDINGS = [".", "!", "?", "\n"] - - -async def collate_response_async( - gen: AsyncIterable[Union[str, FunctionFragment]], - sentence_endings: List[str] = SENTENCE_ENDINGS, - get_functions: Literal[True, False] = False, -) -> AsyncGenerator[Union[str, FunctionCall], None]: - sentence_endings_pattern = "|".join(map(re.escape, sentence_endings)) - list_item_ending_pattern = r"\n" - buffer = "" - function_name_buffer = "" - function_args_buffer = "" - prev_ends_with_money = False - async for token in gen: - if not token: - continue - if isinstance(token, str): - if prev_ends_with_money and token.startswith(" "): - yield buffer.strip() - buffer = "" - - buffer += token - possible_list_item = bool(re.match(r"^\d+[ .]", buffer)) - ends_with_money = bool(re.findall(r"\$\d+.$", buffer)) - if re.findall( - ( - list_item_ending_pattern - if possible_list_item - else sentence_endings_pattern - ), - token, - ): - if not ends_with_money: - to_return = buffer.strip() - if to_return: - yield to_return - buffer = "" - prev_ends_with_money = ends_with_money - elif isinstance(token, FunctionFragment): - function_name_buffer += token.name - function_args_buffer += token.arguments - to_return = buffer.strip() - if to_return: - yield to_return - if function_name_buffer and get_functions: - yield FunctionCall(name=function_name_buffer, arguments=function_args_buffer) - - -async def openai_get_tokens(gen) -> AsyncGenerator[Union[str, FunctionFragment], None]: - async for event in gen: - choices = event.get("choices", []) - if len(choices) == 0: - continue - choice = choices[0] - if choice.finish_reason: - break - delta = choice.get("delta", {}) - if "text" in delta and delta["text"] is not None: - token = delta["text"] - yield token - if "content" in delta and delta["content"] is not None: - token = delta["content"] - yield token - elif "function_call" in delta and delta["function_call"] is not None: - yield FunctionFragment( - name=( - delta["function_call"]["name"] - if "name" in delta["function_call"] - else "" - ), - arguments=( - delta["function_call"]["arguments"] - if "arguments" in delta["function_call"] - else "" - ), - ) - - -def find_last_punctuation(buffer: str) -> Optional[int]: - indices = [buffer.rfind(ending) for ending in SENTENCE_ENDINGS] - if not indices: - return None - return max(indices) - - -def get_sentence_from_buffer(buffer: str): - last_punctuation = find_last_punctuation(buffer) - if last_punctuation: - return buffer[: last_punctuation + 1], buffer[last_punctuation + 1 :] - else: - return None, None - - -def format_openai_chat_messages_from_transcript( - transcript: Transcript, prompt_preamble: Optional[str] = None -) -> List[dict]: - chat_messages: List[Dict[str, Optional[Any]]] = ( - [{"role": "system", "content": prompt_preamble}] if prompt_preamble else [] - ) - - # merge consecutive bot messages - new_event_logs: List[EventLog] = [] - idx = 0 - while idx < len(transcript.event_logs): - bot_messages_buffer: List[Message] = [] - current_log = transcript.event_logs[idx] - while isinstance(current_log, Message) and current_log.sender == Sender.BOT: - bot_messages_buffer.append(current_log) - idx += 1 - try: - current_log = transcript.event_logs[idx] - except IndexError: - break - if bot_messages_buffer: - merged_bot_message = deepcopy(bot_messages_buffer[-1]) - merged_bot_message.text = " ".join( - event_log.text for event_log in bot_messages_buffer - ) - new_event_logs.append(merged_bot_message) - else: - new_event_logs.append(current_log) - idx += 1 - - for event_log in new_event_logs: - if isinstance(event_log, Message): - chat_messages.append( - { - "role": "assistant" if event_log.sender == Sender.BOT else "user", - "content": event_log.text, - } - ) - elif isinstance(event_log, ActionStart): - chat_messages.append( - { - "role": "assistant", - "content": None, - "function_call": { - "name": event_log.action_type, - "arguments": event_log.action_input.params.json(), - }, - } - ) - elif isinstance(event_log, ActionFinish): - chat_messages.append( - { - "role": "function", - "name": event_log.action_type, - "content": event_log.action_output.response.json(), - } - ) - return chat_messages - - -def vector_db_result_to_openai_chat_message(vector_db_result): - return {"role": "user", "content": vector_db_result} diff --git a/vocode/streaming/agent/vertex_ai_agent.py b/vocode/streaming/agent/vertex_ai_agent.py index 0f979bc8a..264676733 100644 --- a/vocode/streaming/agent/vertex_ai_agent.py +++ b/vocode/streaming/agent/vertex_ai_agent.py @@ -1,28 +1,24 @@ -from concurrent.futures import ThreadPoolExecutor import asyncio -import logging -from typing import Optional, Tuple +from concurrent.futures import ThreadPoolExecutor +from typing import Tuple + from langchain import ConversationChain -from vocode.streaming.agent.base_agent import RespondAgent -from vocode.streaming.models.agent import ChatVertexAIAgentConfig +from langchain.memory import ConversationBufferMemory +from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate, MessagesPlaceholder +from langchain.schema import SystemMessage from langchain_community.chat_models import ChatVertexAI -from langchain.prompts import ( - ChatPromptTemplate, - MessagesPlaceholder, - HumanMessagePromptTemplate, -) +from loguru import logger -from langchain.schema import HumanMessage, SystemMessage, AIMessage -from langchain.memory import ConversationBufferMemory +from vocode.streaming.agent.base_agent import RespondAgent +from vocode.streaming.models.agent import ChatVertexAIAgentConfig class ChatVertexAIAgent(RespondAgent[ChatVertexAIAgentConfig]): def __init__( self, agent_config: ChatVertexAIAgentConfig, - logger: Optional[logging.Logger] = None, ): - super().__init__(agent_config=agent_config, logger=logger) + super().__init__(agent_config=agent_config) self.prompt = ChatPromptTemplate.from_messages( [ @@ -38,9 +34,7 @@ def __init__( SystemMessage(content=self.agent_config.prompt_preamble) ) - self.conversation = ConversationChain( - memory=self.memory, prompt=self.prompt, llm=self.llm - ) + self.conversation = ConversationChain(memory=self.memory, prompt=self.prompt, llm=self.llm) if agent_config.initial_message: raise NotImplementedError("initial_message not supported for Vertex AI") self.thread_pool_executor = ThreadPoolExecutor(max_workers=1) @@ -58,5 +52,5 @@ async def respond( human_input, ) - self.logger.debug(f"LLM response: {text}") + logger.debug(f"LLM response: {text}") return text, False diff --git a/vocode/streaming/agent/websocket_user_implemented_agent.py b/vocode/streaming/agent/websocket_user_implemented_agent.py index e965388f0..1a09e199d 100644 --- a/vocode/streaming/agent/websocket_user_implemented_agent.py +++ b/vocode/streaming/agent/websocket_user_implemented_agent.py @@ -1,25 +1,15 @@ import asyncio import json -import logging -from typing import Dict -from vocode.streaming.transcriber.base_transcriber import Transcription -from vocode.streaming.utils.worker import ( - InterruptibleAgentResponseEvent, - InterruptibleEvent, -) + import websockets -from websockets.client import ( - connect, - WebSocketClientProtocol, -) +from loguru import logger +from websockets.client import WebSocketClientProtocol, connect -from typing import Awaitable, Callable, Optional, cast from vocode.streaming.agent.base_agent import ( AgentInput, AgentResponse, AgentResponseMessage, AgentResponseStop, - AgentResponseFillerAudio, BaseAgent, TranscriptionAgentInput, ) @@ -30,6 +20,7 @@ WebSocketAgentTextMessage, WebSocketUserImplementedAgentConfig, ) +from vocode.streaming.utils.worker import InterruptibleAgentResponseEvent, InterruptibleEvent NUM_RESTARTS = 5 @@ -41,50 +32,44 @@ class WebSocketUserImplementedAgent(BaseAgent[WebSocketUserImplementedAgentConfi def __init__( self, agent_config: WebSocketUserImplementedAgentConfig, - logger: Optional[logging.Logger] = None, ): self.agent_config = agent_config - self.logger = logger or logging.getLogger(__name__) self.has_ended = False - super().__init__(agent_config=agent_config, logger=logger) + super().__init__(agent_config=agent_config) def get_agent_config(self) -> WebSocketUserImplementedAgentConfig: return self.agent_config async def _run_loop(self) -> None: restarts = 0 - self.logger.info("Starting Socket Agent") + logger.info("Starting Socket Agent") while not self.has_ended and restarts < NUM_RESTARTS: await self._process() restarts += 1 - self.logger.debug( - "Socket Agent connection died, restarting, num_restarts: %s", restarts - ) + logger.debug("Socket Agent connection died, restarting, num_restarts: %s", restarts) def _handle_incoming_socket_message(self, message: WebSocketAgentMessage) -> None: - self.logger.info("Handling incoming message from Socket Agent: %s", message) + logger.info("Handling incoming message from Socket Agent: %s", message) agent_response: AgentResponse if isinstance(message, WebSocketAgentTextMessage): - agent_response = AgentResponseMessage( - message=BaseMessage(text=message.data.text) - ) + agent_response = AgentResponseMessage(message=BaseMessage(text=message.data.text)) elif isinstance(message, WebSocketAgentStopMessage): agent_response = AgentResponseStop() self.has_ended = True else: raise Exception("Unknown Socket message type") - self.logger.info("Putting interruptible agent response event in output queue") + logger.info("Putting interruptible agent response event in output queue") self.produce_interruptible_agent_response_event_nonblocking( agent_response, self.get_agent_config().allow_agent_to_be_cut_off ) async def _process(self) -> None: socket_url = self.get_agent_config().respond.url - self.logger.info("Connecting to web socket agent %s", socket_url) + logger.info("Connecting to web socket agent %s", socket_url) async with connect(socket_url) as ws: @@ -92,23 +77,19 @@ async def sender( ws: WebSocketClientProtocol, ) -> None: # sends audio to websocket while not self.has_ended: - self.logger.info("Waiting for data from agent request queue") + logger.info("Waiting for data from agent request queue") try: input = await self.input_queue.get() payload = input.payload if isinstance(payload, TranscriptionAgentInput): transcription = payload.transcription - self.logger.info( - "Transcription message: %s", transcription.message - ) + logger.info("Transcription message: %s", transcription.message) agent_request = WebSocketAgentTextMessage.from_text( transcription.message, conversation_id=payload.conversation_id, ) agent_request_json = agent_request.json() - self.logger.info( - f"Sending data to web socket agent: {agent_request_json}" - ) + logger.info(f"Sending data to web socket agent: {agent_request_json}") if isinstance(agent_request, AgentResponseStop): # In practice, it doesn't make sense for the client to send a text and stop message to the agent service self.has_ended = True @@ -119,47 +100,39 @@ async def sender( break except Exception as e: - self.logger.error( + logger.error( f'WebSocket Agent Send Error: "{e}" in Web Socket User Implemented Agent sender' ) break - self.logger.debug("Terminating web socket agent sender") + logger.debug("Terminating web socket agent sender") async def receiver(ws: WebSocketClientProtocol) -> None: while not self.has_ended: try: msg = await ws.recv() - self.logger.info("Received data from web socket agent") + logger.info("Received data from web socket agent") data = json.loads(msg) message = WebSocketAgentMessage.parse_obj(data) self._handle_incoming_socket_message(message) except websockets.exceptions.ConnectionClosed as e: - self.logger.error( - f'WebSocket Agent Receive Error: Connection Closed - "{e}"' - ) + logger.error(f'WebSocket Agent Receive Error: Connection Closed - "{e}"') break except websockets.exceptions.ConnectionClosedOK as e: - self.logger.error( - f'WebSocket Agent Receive Error: Connection Closed OK - "{e}"' - ) + logger.error(f'WebSocket Agent Receive Error: Connection Closed OK - "{e}"') break except websockets.exceptions.InvalidStatus as e: - self.logger.error( - f'WebSocket Agent Receive Error: Invalid Status - "{e}"' - ) + logger.error(f'WebSocket Agent Receive Error: Invalid Status - "{e}"') break except Exception as e: - self.logger.error(f'WebSocket Agent Receive Error: "{e}"') + logger.error(f'WebSocket Agent Receive Error: "{e}"') break - self.logger.debug( - "Terminating Web Socket User Implemented Agent receiver" - ) + logger.debug("Terminating Web Socket User Implemented Agent receiver") await asyncio.gather(sender(ws), receiver(ws)) diff --git a/vocode/streaming/client_backend/conversation.py b/vocode/streaming/client_backend/conversation.py index da3a2be0d..5970c475b 100644 --- a/vocode/streaming/client_backend/conversation.py +++ b/vocode/streaming/client_backend/conversation.py @@ -1,16 +1,18 @@ -import logging -from typing import Callable, Optional import typing +from typing import Callable from fastapi import APIRouter, WebSocket +from loguru import logger + from vocode.streaming.agent.base_agent import BaseAgent -from vocode.streaming.models.audio_encoding import AudioEncoding from vocode.streaming.models.client_backend import InputAudioConfig, OutputAudioConfig +from vocode.streaming.models.events import Event, EventType from vocode.streaming.models.synthesizer import AzureSynthesizerConfig from vocode.streaming.models.transcriber import ( DeepgramTranscriberConfig, PunctuationEndpointingConfig, ) +from vocode.streaming.models.transcript import TranscriptEvent from vocode.streaming.models.websocket import ( AudioConfigStartMessage, AudioMessage, @@ -18,18 +20,14 @@ WebSocketMessage, WebSocketMessageType, ) - from vocode.streaming.output_device.websocket_output_device import WebsocketOutputDevice from vocode.streaming.streaming_conversation import StreamingConversation from vocode.streaming.synthesizer.azure_synthesizer import AzureSynthesizer from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer from vocode.streaming.transcriber.base_transcriber import BaseTranscriber from vocode.streaming.transcriber.deepgram_transcriber import DeepgramTranscriber -from vocode.streaming.utils.base_router import BaseRouter - -from vocode.streaming.models.events import Event, EventType -from vocode.streaming.models.transcript import TranscriptEvent from vocode.streaming.utils import events_manager +from vocode.streaming.utils.base_router import BaseRouter BASE_CONVERSATION_ENDPOINT = "/conversation" @@ -49,18 +47,14 @@ def __init__( synthesizer_thunk: Callable[ [OutputAudioConfig], BaseSynthesizer ] = lambda output_audio_config: AzureSynthesizer( - AzureSynthesizerConfig.from_output_audio_config( - output_audio_config=output_audio_config - ) + AzureSynthesizerConfig.from_output_audio_config(output_audio_config=output_audio_config) ), - logger: Optional[logging.Logger] = None, conversation_endpoint: str = BASE_CONVERSATION_ENDPOINT, ): super().__init__() self.transcriber_thunk = transcriber_thunk self.agent_thunk = agent_thunk self.synthesizer_thunk = synthesizer_thunk - self.logger = logger or logging.getLogger(__name__) self.router = APIRouter() self.router.websocket(conversation_endpoint)(self.conversation) @@ -71,7 +65,7 @@ def get_conversation( ) -> StreamingConversation: transcriber = self.transcriber_thunk(start_message.input_audio_config) synthesizer = self.synthesizer_thunk(start_message.output_audio_config) - synthesizer.synthesizer_config.should_encode_as_wav = True + synthesizer.get_synthesizer_config().should_encode_as_wav = True return StreamingConversation( output_device=output_device, transcriber=transcriber, @@ -79,11 +73,10 @@ def get_conversation( synthesizer=synthesizer, conversation_id=start_message.conversation_id, events_manager=( - TranscriptEventManager(output_device, self.logger) + TranscriptEventManager(output_device) if start_message.subscribe_transcript else None ), - logger=self.logger, ) async def conversation(self, websocket: WebSocket): @@ -91,7 +84,7 @@ async def conversation(self, websocket: WebSocket): start_message: AudioConfigStartMessage = AudioConfigStartMessage.parse_obj( await websocket.receive_json() ) - self.logger.debug(f"Conversation started") + logger.debug(f"Conversation started") output_device = WebsocketOutputDevice( websocket, start_message.output_audio_config.sampling_rate, @@ -100,9 +93,7 @@ async def conversation(self, websocket: WebSocket): conversation = self.get_conversation(output_device, start_message) await conversation.start(lambda: websocket.send_text(ReadyMessage().json())) while conversation.is_active(): - message: WebSocketMessage = WebSocketMessage.parse_obj( - await websocket.receive_json() - ) + message: WebSocketMessage = WebSocketMessage.parse_obj(await websocket.receive_json()) if message.type == WebSocketMessageType.STOP: break audio_message = typing.cast(AudioMessage, message) @@ -118,17 +109,15 @@ class TranscriptEventManager(events_manager.EventsManager): def __init__( self, output_device: WebsocketOutputDevice, - logger: Optional[logging.Logger] = None, ): super().__init__(subscriptions=[EventType.TRANSCRIPT]) self.output_device = output_device - self.logger = logger or logging.getLogger(__name__) async def handle_event(self, event: Event): if event.type == EventType.TRANSCRIPT: transcript_event = typing.cast(TranscriptEvent, event) self.output_device.consume_transcript(transcript_event) - # self.logger.debug(event.dict()) + # logger.debug(event.dict()) def restart(self, output_device: WebsocketOutputDevice): self.output_device = output_device diff --git a/vocode/streaming/constants.py b/vocode/streaming/constants.py index 7f91d2f6f..3b84e2e56 100644 --- a/vocode/streaming/constants.py +++ b/vocode/streaming/constants.py @@ -1,3 +1,10 @@ -TEXT_TO_SPEECH_CHUNK_SIZE_SECONDS = 1 +TEXT_TO_SPEECH_CHUNK_SIZE_SECONDS = 0.1 PER_CHUNK_ALLOWANCE_SECONDS = 0.01 ALLOWED_IDLE_TIME = 15 +SENTENCE_ENDINGS = [".", "!", "?", "\n"] +CHECK_HUMAN_PRESENT_MESSAGE_CHOICES = [ + "Hello?", + "Are you there?", + "Are you still there?", + "Hi, are you there?", +] diff --git a/vocode/streaming/input_device/base_input_device.py b/vocode/streaming/input_device/base_input_device.py index 7816515f5..d7c82bc0b 100644 --- a/vocode/streaming/input_device/base_input_device.py +++ b/vocode/streaming/input_device/base_input_device.py @@ -1,12 +1,11 @@ -from vocode.streaming.models.audio_encoding import AudioEncoding import queue from typing import Optional +from vocode.streaming.models.audio import AudioEncoding + class BaseInputDevice: - def __init__( - self, sampling_rate: int, audio_encoding: AudioEncoding, chunk_size: int - ): + def __init__(self, sampling_rate: int, audio_encoding: AudioEncoding, chunk_size: int): self.sampling_rate = sampling_rate self.audio_encoding = audio_encoding self.chunk_size = chunk_size diff --git a/vocode/streaming/input_device/file_input_device.py b/vocode/streaming/input_device/file_input_device.py index 7ba88b41d..b39045688 100644 --- a/vocode/streaming/input_device/file_input_device.py +++ b/vocode/streaming/input_device/file_input_device.py @@ -1,10 +1,12 @@ -from vocode.streaming.models.audio_encoding import AudioEncoding -import janus -from vocode.streaming.input_device.base_input_device import BaseInputDevice -import wave import struct +import wave + +import janus import numpy as np +from vocode.streaming.input_device.base_input_device import BaseInputDevice +from vocode.streaming.models.audio import AudioEncoding + class FileInputDevice(BaseInputDevice): DEFAULT_SAMPLING_RATE = 44100 diff --git a/vocode/streaming/input_device/microphone_input.py b/vocode/streaming/input_device/microphone_input.py index ac3c50149..e27dc95d2 100644 --- a/vocode/streaming/input_device/microphone_input.py +++ b/vocode/streaming/input_device/microphone_input.py @@ -1,15 +1,16 @@ from __future__ import annotations -import typing -import janus -import sounddevice as sd -import numpy as np -from typing import Optional import queue +import typing import wave +from typing import Optional + +import janus +import numpy as np +import sounddevice as sd from vocode.streaming.input_device.base_input_device import BaseInputDevice -from vocode.streaming.models.audio_encoding import AudioEncoding +from vocode.streaming.models.audio import AudioEncoding class MicrophoneInput(BaseInputDevice): @@ -29,9 +30,7 @@ def __init__( or ( typing.cast( int, - self.device_info.get( - "default_samplerate", self.DEFAULT_SAMPLING_RATE - ), + self.device_info.get("default_samplerate", self.DEFAULT_SAMPLING_RATE), ) ), AudioEncoding.LINEAR16, diff --git a/vocode/streaming/models/actions.py b/vocode/streaming/models/actions.py index e93a0006b..52afeeaec 100644 --- a/vocode/streaming/models/actions.py +++ b/vocode/streaming/models/actions.py @@ -1,21 +1,89 @@ import asyncio +from distutils.sysconfig import EXEC_PREFIX from enum import Enum -from typing import Generic, Optional, TypeVar -from pydantic.v1 import BaseModel +from typing import Annotated, Generic, List, Literal, Optional, TypeVar, Union + +from pydantic.v1 import BaseModel, Field + +from vocode.streaming.models.message import BaseMessage from vocode.streaming.models.model import TypedModel +TriggerType = Literal["action_trigger_function_call", "action_trigger_phrase_based"] + + +class ActionTriggerConfig(BaseModel): + pass + + +class _ActionTrigger(BaseModel): + type: TriggerType + config: ActionTriggerConfig + + +class FunctionCallActionTriggerConfig(ActionTriggerConfig): + pass + + +class FunctionCallActionTrigger(_ActionTrigger): + type: Literal["action_trigger_function_call"] = "action_trigger_function_call" + config: FunctionCallActionTriggerConfig = Field(default_factory=FunctionCallActionTriggerConfig) + + +PhraseConditionType = Literal["phrase_condition_type_contains"] + + +class PhraseTrigger(BaseModel): + phrase: str + conditions: List[PhraseConditionType] + + +class PhraseBasedActionTriggerConfig(ActionTriggerConfig): + phrase_triggers: List[PhraseTrigger] + + +class PhraseBasedActionTrigger(_ActionTrigger): + type: Literal["action_trigger_phrase_based"] = "action_trigger_phrase_based" + config: PhraseBasedActionTriggerConfig + + +ActionTrigger = Annotated[ + Union[FunctionCallActionTrigger, PhraseBasedActionTrigger], + Field(discriminator="type"), +] + class ActionType(str, Enum): BASE = "action_base" NYLAS_SEND_EMAIL = "action_nylas_send_email" + WAIT = "action_wait" + RECORD_EMAIL = "action_record_email" + END_CONVERSATION = "action_end_conversation" + EXECUTE_EXTERNAL_ACTION = "action_external" + TRANSFER_CALL = "action_transfer_call" + DTMF = "action_dtmf" -class ActionConfig(TypedModel, type=ActionType.BASE): - pass +ParametersType = TypeVar("ParametersType", bound=BaseModel) +ACTION_STARTED_FORMAT_STRING = "!STARTING ACTION {action_name} WITH PARAMETERS {action_params}!" +ACTION_FINISHED_FORMAT_STRING = "!ACTION {action_name} FINISHED WITH OUTPUT {action_output}!" -ParametersType = TypeVar("ParametersType", bound=BaseModel) + +class ActionConfig(TypedModel, type=ActionType.BASE): # type: ignore + action_trigger: ActionTrigger = FunctionCallActionTrigger(type="action_trigger_function_call") + + def action_attempt_to_string(self, input: "ActionInput") -> str: + return ACTION_STARTED_FORMAT_STRING.format( + action_name=self.type, + action_params=input.params.json(), + ) + + def action_result_to_string(self, input: "ActionInput", output: "ActionOutput") -> str: + return ACTION_FINISHED_FORMAT_STRING.format( + action_name=self.type, + action_output=output.response.json(), + ) class ActionInput(BaseModel, Generic[ParametersType]): @@ -38,11 +106,15 @@ class FunctionCall(BaseModel): arguments: str -class VonagePhoneCallActionInput(ActionInput[ParametersType]): +class EndOfTurn(BaseModel): + pass + + +class VonagePhoneConversationActionInput(ActionInput[ParametersType]): vonage_uuid: str -class TwilioPhoneCallActionInput(ActionInput[ParametersType]): +class TwilioPhoneConversationActionInput(ActionInput[ParametersType]): twilio_sid: str @@ -51,4 +123,8 @@ class TwilioPhoneCallActionInput(ActionInput[ParametersType]): class ActionOutput(BaseModel, Generic[ResponseType]): action_type: str + canned_response: Optional[BaseMessage] = None response: ResponseType + + +ExternalActionProcessingMode = Literal["muted"] diff --git a/vocode/streaming/models/agent.py b/vocode/streaming/models/agent.py index 47e7da1df..fb9832fba 100644 --- a/vocode/streaming/models/agent.py +++ b/vocode/streaming/models/agent.py @@ -1,25 +1,38 @@ -from typing import List, Optional, Union from enum import Enum -from langchain.prompts import PromptTemplate +from typing import List, Literal, Optional, Union +from langchain.prompts import PromptTemplate from pydantic.v1 import validator -from vocode.streaming.models.actions import ActionConfig -from vocode.streaming.models.message import BaseMessage -from .model import TypedModel, BaseModel +from .model import BaseModel, TypedModel from .vector_db import VectorDBConfig +from vocode.streaming.models.actions import ActionConfig +from vocode.streaming.models.message import BaseMessage FILLER_AUDIO_DEFAULT_SILENCE_THRESHOLD_SECONDS = 0.5 LLM_AGENT_DEFAULT_TEMPERATURE = 1.0 LLM_AGENT_DEFAULT_MAX_TOKENS = 256 LLM_AGENT_DEFAULT_MODEL_NAME = "text-curie-001" -CHAT_GPT_AGENT_DEFAULT_MODEL_NAME = "gpt-3.5-turbo-0613" +CHAT_GPT_AGENT_DEFAULT_MODEL_NAME = "gpt-3.5-turbo-1106" +CHAT_GPT_AGENT_16K_MODEL_NAME = "gpt-3.5-turbo-0613-16k" ACTION_AGENT_DEFAULT_MODEL_NAME = "gpt-3.5-turbo-0613" -CHAT_ANTHROPIC_DEFAULT_MODEL_NAME = "claude-v1" +CHAT_ANTHROPIC_DEFAULT_MODEL_NAME = "claude-3-haiku-20240307" CHAT_VERTEX_AI_DEFAULT_MODEL_NAME = "chat-bison@001" AZURE_OPENAI_DEFAULT_API_TYPE = "azure" -AZURE_OPENAI_DEFAULT_API_VERSION = "2023-03-15-preview" +AZURE_OPENAI_DEFAULT_API_VERSION = "2023-07-01-preview" AZURE_OPENAI_DEFAULT_ENGINE = "gpt-35-turbo" +AZURE_OPENAI_GPT_35_16K_ENGINE = "gpt-35-turbo-16k" +AZURE_OPENAI_GPT_4_ENGINE = "vocode-api-gpt4" +OPENAI_GPT_4_MODEL_NAME = "gpt-4" +OPENAI_GPT_4_32K_MODEL_NAME = "gpt-4-32k" +OPENAI_GPT_4_O_MODEL_NAME = "gpt-4o" +OPENAI_GPT_35_TURBO_1106_MODEL_NAME = "gpt-3.5-turbo-1106" +OPENAI_GPT_4_1106_PREVIEW_MODEL_NAME = "gpt-4-1106-preview" +ANTHROPIC_CLAUDE_3_HAIKU_MODEL_NAME = "claude-3-haiku-20240307" +ANTHROPIC_CLAUDE_3_SONNET_MODEL_NAME = "claude-3-sonnet-20240229" +ANTHROPIC_CLAUDE_3_OPUS_MODEL_NAME = "claude-3-opus-20240229" + +InterruptSensitivity = Literal["low", "high"] class AgentType(str, Enum): @@ -27,7 +40,7 @@ class AgentType(str, Enum): LLM = "agent_llm" CHAT_GPT_ALPHA = "agent_chat_gpt_alpha" CHAT_GPT = "agent_chat_gpt" - CHAT_ANTHROPIC = "agent_chat_anthropic" + ANTHROPIC = "agent_anthropic" CHAT_VERTEX_AI = "agent_chat_vertex_ai" ECHO = "agent_echo" GPT4ALL = "agent_gpt4all" @@ -57,67 +70,77 @@ class WebhookConfig(BaseModel): class AzureOpenAIConfig(BaseModel): + base_url: str + api_key: str + region: str + deployment_name: str + openai_model_name: str api_type: str = AZURE_OPENAI_DEFAULT_API_TYPE api_version: Optional[str] = AZURE_OPENAI_DEFAULT_API_VERSION - engine: str = AZURE_OPENAI_DEFAULT_ENGINE -class AgentConfig(TypedModel, type=AgentType.BASE.value): +class CutOffResponse(BaseModel): + messages: List[BaseMessage] = [BaseMessage(text="Sorry?")] + + +class AgentConfig(TypedModel, type=AgentType.BASE.value): # type: ignore initial_message: Optional[BaseMessage] = None generate_responses: bool = True allowed_idle_time_seconds: Optional[float] = None + num_check_human_present_times: int = 0 allow_agent_to_be_cut_off: bool = True end_conversation_on_goodbye: bool = False send_filler_audio: Union[bool, FillerAudioConfig] = False webhook_config: Optional[WebhookConfig] = None - track_bot_sentiment: bool = False actions: Optional[List[ActionConfig]] = None + initial_message_delay: float = 0.0 + goodbye_phrases: Optional[List[str]] = None + interrupt_sensitivity: InterruptSensitivity = "low" + cut_off_response: Optional[CutOffResponse] = None -class CutOffResponse(BaseModel): - messages: List[BaseMessage] = [BaseMessage(text="Sorry?")] - - -class LLMAgentConfig(AgentConfig, type=AgentType.LLM.value): +class LLMAgentConfig(AgentConfig, type=AgentType.LLM.value): # type: ignore prompt_preamble: str - expected_first_prompt: Optional[str] = None model_name: str = LLM_AGENT_DEFAULT_MODEL_NAME temperature: float = LLM_AGENT_DEFAULT_TEMPERATURE max_tokens: int = LLM_AGENT_DEFAULT_MAX_TOKENS - cut_off_response: Optional[CutOffResponse] = None -class ChatGPTAgentConfig(AgentConfig, type=AgentType.CHAT_GPT.value): +class ChatGPTAgentConfig(AgentConfig, type=AgentType.CHAT_GPT.value): # type: ignore + openai_api_key: Optional[str] = None prompt_preamble: str - expected_first_prompt: Optional[str] = None model_name: str = CHAT_GPT_AGENT_DEFAULT_MODEL_NAME temperature: float = LLM_AGENT_DEFAULT_TEMPERATURE max_tokens: int = LLM_AGENT_DEFAULT_MAX_TOKENS - cut_off_response: Optional[CutOffResponse] = None azure_params: Optional[AzureOpenAIConfig] = None vector_db_config: Optional[VectorDBConfig] = None + # TODO: the below fields should moved up to AgentConfig, and their logic should live in BaseAgent + use_backchannels: bool = False + backchannel_probability: float = 0.7 + first_response_filler_message: Optional[str] = None -class ChatAnthropicAgentConfig(AgentConfig, type=AgentType.CHAT_ANTHROPIC.value): +class AnthropicAgentConfig(AgentConfig, type=AgentType.ANTHROPIC.value): # type: ignore prompt_preamble: str model_name: str = CHAT_ANTHROPIC_DEFAULT_MODEL_NAME - max_tokens_to_sample: int = 200 + max_tokens: int = LLM_AGENT_DEFAULT_MAX_TOKENS + temperature: float = LLM_AGENT_DEFAULT_TEMPERATURE -class ChatVertexAIAgentConfig(AgentConfig, type=AgentType.CHAT_VERTEX_AI.value): +class ChatVertexAIAgentConfig(AgentConfig, type=AgentType.CHAT_VERTEX_AI.value): # type: ignore prompt_preamble: str model_name: str = CHAT_VERTEX_AI_DEFAULT_MODEL_NAME generate_responses: bool = False # Google Vertex AI doesn't support streaming -class LlamacppAgentConfig(AgentConfig, type=AgentType.LLAMACPP.value): +class LlamacppAgentConfig(AgentConfig, type=AgentType.LLAMACPP.value): # type: ignore prompt_preamble: str llamacpp_kwargs: dict = {} prompt_template: Optional[Union[PromptTemplate, str]] = None class InformationRetrievalAgentConfig( - AgentConfig, type=AgentType.INFORMATION_RETRIEVAL.value + AgentConfig, type=AgentType.INFORMATION_RETRIEVAL.value # type: ignore ): recipient_descriptor: str caller_descriptor: str @@ -126,18 +149,18 @@ class InformationRetrievalAgentConfig( # TODO: add fields for IVR, voicemail -class EchoAgentConfig(AgentConfig, type=AgentType.ECHO.value): +class EchoAgentConfig(AgentConfig, type=AgentType.ECHO.value): # type: ignore pass -class GPT4AllAgentConfig(AgentConfig, type=AgentType.GPT4ALL.value): +class GPT4AllAgentConfig(AgentConfig, type=AgentType.GPT4ALL.value): # type: ignore prompt_preamble: str model_path: str generate_responses: bool = False class RESTfulUserImplementedAgentConfig( - AgentConfig, type=AgentType.RESTFUL_USER_IMPLEMENTED.value + AgentConfig, type=AgentType.RESTFUL_USER_IMPLEMENTED.value # type: ignore ): class EndpointConfig(BaseModel): url: str @@ -159,13 +182,13 @@ class RESTfulAgentOutputType(str, Enum): END = "restful_agent_end" -class RESTfulAgentOutput(TypedModel, type=RESTfulAgentOutputType.BASE): +class RESTfulAgentOutput(TypedModel, type=RESTfulAgentOutputType.BASE): # type: ignore pass -class RESTfulAgentText(RESTfulAgentOutput, type=RESTfulAgentOutputType.TEXT): +class RESTfulAgentText(RESTfulAgentOutput, type=RESTfulAgentOutputType.TEXT): # type: ignore response: str -class RESTfulAgentEnd(RESTfulAgentOutput, type=RESTfulAgentOutputType.END): +class RESTfulAgentEnd(RESTfulAgentOutput, type=RESTfulAgentOutputType.END): # type: ignore pass diff --git a/vocode/streaming/models/audio.py b/vocode/streaming/models/audio.py new file mode 100644 index 000000000..42108a783 --- /dev/null +++ b/vocode/streaming/models/audio.py @@ -0,0 +1,15 @@ +from enum import Enum + + +class AudioEncoding(str, Enum): + LINEAR16 = "linear16" + MULAW = "mulaw" + + +class SamplingRate(int, Enum): + RATE_8000 = 8000 + RATE_16000 = 16000 + RATE_22050 = 22050 + RATE_24000 = 24000 + RATE_44100 = 44100 + RATE_48000 = 48000 diff --git a/vocode/streaming/models/audio_encoding.py b/vocode/streaming/models/audio_encoding.py deleted file mode 100644 index 1fd324002..000000000 --- a/vocode/streaming/models/audio_encoding.py +++ /dev/null @@ -1,6 +0,0 @@ -from enum import Enum - - -class AudioEncoding(str, Enum): - LINEAR16 = "linear16" - MULAW = "mulaw" diff --git a/vocode/streaming/models/client_backend.py b/vocode/streaming/models/client_backend.py index da4f3de76..e655f32b3 100644 --- a/vocode/streaming/models/client_backend.py +++ b/vocode/streaming/models/client_backend.py @@ -1,5 +1,6 @@ from typing import Optional -from vocode.streaming.models.audio_encoding import AudioEncoding + +from vocode.streaming.models.audio import AudioEncoding from vocode.streaming.models.model import BaseModel diff --git a/vocode/streaming/models/events.py b/vocode/streaming/models/events.py index 9d9a143a9..901fd3a33 100644 --- a/vocode/streaming/models/events.py +++ b/vocode/streaming/models/events.py @@ -1,5 +1,6 @@ from enum import Enum from typing import Optional + from vocode.streaming.models.model import TypedModel @@ -8,6 +9,7 @@ class Sender(str, Enum): BOT = "bot" ACTION_WORKER = "action_worker" VECTOR_DB = "vector_db" + CONFERENCE = "conference" class EventType(str, Enum): @@ -15,6 +17,7 @@ class EventType(str, Enum): TRANSCRIPT_COMPLETE = "event_transcript_complete" PHONE_CALL_CONNECTED = "event_phone_call_connected" PHONE_CALL_ENDED = "event_phone_call_ended" + PHONE_CALL_DID_NOT_CONNECT = "event_phone_call_did_not_connect" RECORDING = "event_recording" ACTION = "event_action" @@ -23,19 +26,23 @@ class Event(TypedModel): conversation_id: str -class PhoneCallConnectedEvent(Event, type=EventType.PHONE_CALL_CONNECTED): +class PhoneCallConnectedEvent(Event, type=EventType.PHONE_CALL_CONNECTED): # type: ignore to_phone_number: str from_phone_number: str -class PhoneCallEndedEvent(Event, type=EventType.PHONE_CALL_ENDED): +class PhoneCallEndedEvent(Event, type=EventType.PHONE_CALL_ENDED): # type: ignore conversation_minutes: float = 0 -class RecordingEvent(Event, type=EventType.RECORDING): +class PhoneCallDidNotConnectEvent(Event, type=EventType.PHONE_CALL_DID_NOT_CONNECT): # type: ignore + telephony_status: str + + +class RecordingEvent(Event, type=EventType.RECORDING): # type: ignore recording_url: str -class ActionEvent(Event, type=EventType.ACTION): +class ActionEvent(Event, type=EventType.ACTION): # type: ignore action_input: Optional[dict] = None action_output: Optional[dict] = None diff --git a/vocode/streaming/models/message.py b/vocode/streaming/models/message.py index 529e7dac4..db32f9e29 100644 --- a/vocode/streaming/models/message.py +++ b/vocode/streaming/models/message.py @@ -1,16 +1,34 @@ from enum import Enum +from typing import Optional + from .model import TypedModel -from enum import Enum class MessageType(str, Enum): BASE = "message_base" SSML = "message_ssml" + BOT_BACKCHANNEL = "bot_backchannel" + LLM_TOKEN = "llm_token" -class BaseMessage(TypedModel, type=MessageType.BASE): +class BaseMessage(TypedModel, type=MessageType.BASE): # type: ignore text: str + trailing_silence_seconds: float = 0.0 + cache_phrase: Optional[str] = None -class SSMLMessage(BaseMessage, type=MessageType.SSML): +class SSMLMessage(BaseMessage, type=MessageType.SSML): # type: ignore ssml: str + + +class BotBackchannel(BaseMessage, type=MessageType.BOT_BACKCHANNEL): # type: ignore + pass + + +class LLMToken(BaseMessage, type=MessageType.LLM_TOKEN): # type: ignore + pass + + +class SilenceMessage(BotBackchannel): + text: str = "" + trailing_silence_seconds: float = 1.0 diff --git a/vocode/streaming/models/model.py b/vocode/streaming/models/model.py index a4a810e68..05ec13f6e 100644 --- a/vocode/streaming/models/model.py +++ b/vocode/streaming/models/model.py @@ -1,12 +1,15 @@ from typing import Any, List, Tuple -from pydantic.v1 import BaseModel as PydanticBaseModel +from pydantic.v1 import BaseModel as Pydantic1BaseModel -class BaseModel(PydanticBaseModel): + +class BaseModel(Pydantic1BaseModel): def __init__(self, **data): for key, value in data.items(): if isinstance(value, dict): - if "type" in value: + if ( + "type" in value and key != "action_trigger" + ): # TODO: this is a quick workaround until we get a vocode object version of action trigger (ajay has approved it) data[key] = TypedModel.parse_obj(value) if isinstance(value, list): for i, v in enumerate(value): @@ -16,11 +19,11 @@ def __init__(self, **data): super().__init__(**data) -# Adapted from https://github.com/pydantic.v1/pydantic.v1/discussions/3091 +# Adapted from https://github.com/pydantic/pydantic/discussions/3091 class TypedModel(BaseModel): _subtypes_: List[Tuple[Any, Any]] = [] - def __init_subclass__(cls, type=None): + def __init_subclass__(cls, type=None): # type: ignore cls._subtypes_.append((type, cls)) @classmethod diff --git a/vocode/streaming/models/synthesizer.py b/vocode/streaming/models/synthesizer.py index c9d2c33b8..24616bb8b 100644 --- a/vocode/streaming/models/synthesizer.py +++ b/vocode/streaming/models/synthesizer.py @@ -1,16 +1,13 @@ from enum import Enum -from typing import Any, Dict, List, Optional, Union +from typing import Any, Dict, List, Literal, Optional from pydantic.v1 import validator -from vocode.streaming.models.client_backend import OutputAudioConfig -from vocode.streaming.output_device.base_output_device import BaseOutputDevice -from vocode.streaming.telephony.constants import ( - DEFAULT_AUDIO_ENCODING, - DEFAULT_SAMPLING_RATE, -) +from .audio import AudioEncoding, SamplingRate from .model import BaseModel, TypedModel -from .audio_encoding import AudioEncoding +from vocode.streaming.models.client_backend import OutputAudioConfig +from vocode.streaming.output_device.base_output_device import BaseOutputDevice +from vocode.streaming.telephony.constants import DEFAULT_AUDIO_ENCODING, DEFAULT_SAMPLING_RATE class SynthesizerType(str, Enum): @@ -38,7 +35,7 @@ def emotions_must_not_be_empty(cls, v): return v -class SynthesizerConfig(TypedModel, type=SynthesizerType.BASE.value): +class SynthesizerConfig(TypedModel, type=SynthesizerType.BASE.value): # type: ignore sampling_rate: int audio_encoding: AudioEncoding should_encode_as_wav: bool = False @@ -59,9 +56,7 @@ def from_output_device(cls, output_device: BaseOutputDevice, **kwargs): @classmethod def from_telephone_output_device(cls, **kwargs): return cls( - sampling_rate=DEFAULT_SAMPLING_RATE, - audio_encoding=DEFAULT_AUDIO_ENCODING, - **kwargs + sampling_rate=DEFAULT_SAMPLING_RATE, audio_encoding=DEFAULT_AUDIO_ENCODING, **kwargs ) @classmethod @@ -78,7 +73,7 @@ def from_output_audio_config(cls, output_audio_config: OutputAudioConfig, **kwar AZURE_SYNTHESIZER_DEFAULT_RATE = 15 -class AzureSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.AZURE.value): +class AzureSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.AZURE.value): # type: ignore voice_name: str = AZURE_SYNTHESIZER_DEFAULT_VOICE_NAME pitch: int = AZURE_SYNTHESIZER_DEFAULT_PITCH rate: int = AZURE_SYNTHESIZER_DEFAULT_RATE @@ -91,7 +86,7 @@ class AzureSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.AZURE.value DEFAULT_GOOGLE_SPEAKING_RATE = 1.2 -class GoogleSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.GOOGLE.value): +class GoogleSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.GOOGLE.value): # type: ignore language_code: str = DEFAULT_GOOGLE_LANGUAGE_CODE voice_name: str = DEFAULT_GOOGLE_VOICE_NAME pitch: float = DEFAULT_GOOGLE_PITCH @@ -102,15 +97,17 @@ class GoogleSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.GOOGLE.val class ElevenLabsSynthesizerConfig( - SynthesizerConfig, type=SynthesizerType.ELEVEN_LABS.value + SynthesizerConfig, type=SynthesizerType.ELEVEN_LABS.value # type: ignore ): api_key: Optional[str] = None voice_id: Optional[str] = ELEVEN_LABS_ADAM_VOICE_ID optimize_streaming_latency: Optional[int] - experimental_streaming: Optional[bool] = False + experimental_streaming: bool = False stability: Optional[float] similarity_boost: Optional[float] model_id: Optional[str] + experimental_websocket: bool = False + backchannel_amplitude_factor: float = 0.5 @validator("voice_id") def set_name(cls, voice_id): @@ -120,36 +117,46 @@ def set_name(cls, voice_id): def stability_and_similarity_boost_check(cls, similarity_boost, values): stability = values.get("stability") if (stability is None) != (similarity_boost is None): - raise ValueError( - "Both stability and similarity_boost must be set or not set." - ) + raise ValueError("Both stability and similarity_boost must be set or not set.") return similarity_boost @validator("optimize_streaming_latency") def optimize_streaming_latency_check(cls, optimize_streaming_latency): - if optimize_streaming_latency is not None and not ( - 0 <= optimize_streaming_latency <= 4 - ): + if optimize_streaming_latency is not None and not (0 <= optimize_streaming_latency <= 4): raise ValueError("optimize_streaming_latency must be between 0 and 4.") return optimize_streaming_latency + @validator("backchannel_amplitude_factor") + def backchannel_amplitude_factor_check(cls, backchannel_amplitude_factor): + if backchannel_amplitude_factor is not None and not (0 < backchannel_amplitude_factor <= 1): + raise ValueError( + "backchannel_amplitude_factor must be between 0 (not inclusive) and 1." + ) + return backchannel_amplitude_factor + +RIME_DEFAULT_BASE_URL = "https://users.rime.ai/v1/rime-tts" +RIME_DEFAULT_MODEL_ID = None RIME_DEFAULT_SPEAKER = "young_male_unmarked-1" -RIME_DEFAULT_SAMPLE_RATE = 22050 -RIME_DEFAULT_BASE_URL = "https://rjmopratfrdjgmfmaios.functions.supabase.co/rime-tts" +RIME_DEFAULT_SPEED_ALPHA = 1.0 +RIME_DEFAULT_SAMPLE_RATE = SamplingRate.RATE_22050 +RIME_DEFAULT_REDUCE_LATENCY = False +RimeModelId = Literal["mist", "v1"] -class RimeSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.RIME.value): +class RimeSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.RIME.value): # type: ignore + base_url: str = RIME_DEFAULT_BASE_URL + model_id: Optional[Literal[RimeModelId]] = RIME_DEFAULT_MODEL_ID speaker: str = RIME_DEFAULT_SPEAKER + speed_alpha: Optional[float] = RIME_DEFAULT_SPEED_ALPHA sampling_rate: int = RIME_DEFAULT_SAMPLE_RATE - base_url: str = RIME_DEFAULT_BASE_URL - speed_alpha: Optional[float] = None + reduce_latency: Optional[bool] = RIME_DEFAULT_REDUCE_LATENCY COQUI_DEFAULT_SPEAKER_ID = "ebe2db86-62a6-49a1-907a-9a1360d4416e" -class CoquiSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.COQUI.value): +class CoquiSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.COQUI.value): # type: ignore api_key: Optional[str] = None voice_id: Optional[str] = COQUI_DEFAULT_SPEAKER_ID voice_prompt: Optional[str] = None @@ -163,27 +170,36 @@ def override_voice_id_with_prompt(cls, voice_id, values): PLAYHT_DEFAULT_VOICE_ID = "larry" +PlayHtVoiceVersionType = Literal["1", "2"] -class PlayHtSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.PLAY_HT.value): +class PlayHtSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.PLAY_HT.value): # type: ignore api_key: Optional[str] = None user_id: Optional[str] = None - speed: Optional[int] = None + speed: Optional[float] = None seed: Optional[int] = None - temperature: Optional[int] = None + temperature: Optional[float] = None + quality: Optional[str] = None voice_id: str = PLAYHT_DEFAULT_VOICE_ID experimental_streaming: bool = False + version: Literal[PlayHtVoiceVersionType] = "2" + top_p: Optional[float] = None + text_guidance: Optional[float] = None + voice_guidance: Optional[float] = None + on_prem: bool = False + on_prem_provider: Literal["aws", "gcp"] = "gcp" + experimental_remove_silence: bool = False class CoquiTTSSynthesizerConfig( - SynthesizerConfig, type=SynthesizerType.COQUI_TTS.value + SynthesizerConfig, type=SynthesizerType.COQUI_TTS.value # type: ignore ): tts_kwargs: dict = {} speaker: Optional[str] = None language: Optional[str] = None -class GTTSSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.GTTS.value): +class GTTSSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.GTTS.value): # type: ignore pass @@ -191,22 +207,22 @@ class GTTSSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.GTTS.value): class StreamElementsSynthesizerConfig( - SynthesizerConfig, type=SynthesizerType.STREAM_ELEMENTS.value + SynthesizerConfig, type=SynthesizerType.STREAM_ELEMENTS.value # type: ignore ): voice: str = STREAM_ELEMENTS_SYNTHESIZER_DEFAULT_VOICE -class BarkSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.BARK.value): +class BarkSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.BARK.value): # type: ignore preload_kwargs: Dict[str, Any] = {} generate_kwargs: Dict[str, Any] = {} DEFAULT_POLLY_LANGUAGE_CODE = "en-US" DEFAULT_POLLY_VOICE_ID = "Matthew" -DEFAULT_POLLY_SAMPLING_RATE = 16000 +DEFAULT_POLLY_SAMPLING_RATE = SamplingRate.RATE_16000 -class PollySynthesizerConfig(SynthesizerConfig, type=SynthesizerType.POLLY.value): +class PollySynthesizerConfig(SynthesizerConfig, type=SynthesizerType.POLLY.value): # type: ignore language_code: str = DEFAULT_POLLY_LANGUAGE_CODE voice_id: str = DEFAULT_POLLY_VOICE_ID sampling_rate: int = DEFAULT_POLLY_SAMPLING_RATE diff --git a/vocode/streaming/models/telephony.py b/vocode/streaming/models/telephony.py index 616a85b14..cd01b3ced 100644 --- a/vocode/streaming/models/telephony.py +++ b/vocode/streaming/models/telephony.py @@ -1,12 +1,9 @@ from enum import Enum -from typing import Any, Dict, Optional -from vocode.streaming.models.audio_encoding import AudioEncoding -from vocode.streaming.models.model import BaseModel, TypedModel +from typing import Any, Dict, Literal, Optional, Union + from vocode.streaming.models.agent import AgentConfig -from vocode.streaming.models.synthesizer import ( - AzureSynthesizerConfig, - SynthesizerConfig, -) +from vocode.streaming.models.model import BaseModel, TypedModel +from vocode.streaming.models.synthesizer import AzureSynthesizerConfig, SynthesizerConfig from vocode.streaming.models.transcriber import ( DeepgramTranscriberConfig, PunctuationEndpointingConfig, @@ -16,25 +13,28 @@ DEFAULT_AUDIO_ENCODING, DEFAULT_CHUNK_SIZE, DEFAULT_SAMPLING_RATE, - VONAGE_CHUNK_SIZE, VONAGE_AUDIO_ENCODING, + VONAGE_CHUNK_SIZE, VONAGE_SAMPLING_RATE, ) -class TwilioConfig(BaseModel): +class TelephonyProviderConfig(BaseModel): + record: bool = False + + +class TwilioConfig(TelephonyProviderConfig): account_sid: str auth_token: str - record: bool = False extra_params: Optional[Dict[str, Any]] = {} + account_supports_any_caller_id: bool = True -class VonageConfig(BaseModel): +class VonageConfig(TelephonyProviderConfig): api_key: str api_secret: str application_id: str private_key: str - record: bool = False class CallEntity(BaseModel): @@ -91,12 +91,19 @@ class CallConfigType(str, Enum): VONAGE = "call_config_vonage" -class BaseCallConfig(TypedModel, type=CallConfigType.BASE.value): +PhoneCallDirection = Literal["inbound", "outbound"] + + +class BaseCallConfig(TypedModel, type=CallConfigType.BASE.value): # type: ignore transcriber_config: TranscriberConfig agent_config: AgentConfig synthesizer_config: SynthesizerConfig from_phone: str to_phone: str + sentry_tags: Dict[str, str] = {} + conference: bool = False + telephony_params: Optional[Dict[str, str]] = None + direction: PhoneCallDirection @staticmethod def default_transcriber_config(): @@ -107,7 +114,7 @@ def default_synthesizer_config(): raise NotImplementedError -class TwilioCallConfig(BaseCallConfig, type=CallConfigType.TWILIO.value): +class TwilioCallConfig(BaseCallConfig, type=CallConfigType.TWILIO.value): # type: ignore twilio_config: TwilioConfig twilio_sid: str @@ -130,7 +137,7 @@ def default_synthesizer_config(): ) -class VonageCallConfig(BaseCallConfig, type=CallConfigType.VONAGE.value): +class VonageCallConfig(BaseCallConfig, type=CallConfigType.VONAGE.value): # type: ignore vonage_config: VonageConfig vonage_uuid: str output_to_speaker: bool = False @@ -152,3 +159,6 @@ def default_synthesizer_config(): sampling_rate=VONAGE_SAMPLING_RATE, audio_encoding=VONAGE_AUDIO_ENCODING, ) + + +TelephonyConfig = Union[TwilioConfig, VonageConfig] diff --git a/vocode/streaming/models/transcriber.py b/vocode/streaming/models/transcriber.py index d0391e9fd..c666767fa 100644 --- a/vocode/streaming/models/transcriber.py +++ b/vocode/streaming/models/transcriber.py @@ -3,17 +3,19 @@ from pydantic.v1 import validator +from .audio import AudioEncoding +from .model import TypedModel from vocode.streaming.input_device.base_input_device import BaseInputDevice from vocode.streaming.models.client_backend import InputAudioConfig +from vocode.streaming.models.model import BaseModel from vocode.streaming.telephony.constants import ( DEFAULT_AUDIO_ENCODING, DEFAULT_CHUNK_SIZE, DEFAULT_SAMPLING_RATE, ) -from .audio_encoding import AudioEncoding -from .model import TypedModel AZURE_DEFAULT_LANGUAGE = "en-US" +DEEPGRAM_API_WS_URL = "wss://api.deepgram.com" class TranscriberType(str, Enum): @@ -33,21 +35,21 @@ class EndpointingType(str, Enum): PUNCTUATION_BASED = "endpointing_punctuation_based" -class EndpointingConfig(TypedModel, type=EndpointingType.BASE): +class EndpointingConfig(TypedModel, type=EndpointingType.BASE): # type: ignore pass -class TimeEndpointingConfig(EndpointingConfig, type=EndpointingType.TIME_BASED): +class TimeEndpointingConfig(EndpointingConfig, type=EndpointingType.TIME_BASED): # type: ignore time_cutoff_seconds: float = 0.4 class PunctuationEndpointingConfig( - EndpointingConfig, type=EndpointingType.PUNCTUATION_BASED + EndpointingConfig, type=EndpointingType.PUNCTUATION_BASED # type: ignore ): time_cutoff_seconds: float = 0.4 -class TranscriberConfig(TypedModel, type=TranscriberType.BASE.value): +class TranscriberConfig(TypedModel, type=TranscriberType.BASE.value): # type: ignore sampling_rate: int audio_encoding: AudioEncoding chunk_size: int @@ -103,30 +105,32 @@ def from_input_audio_config(cls, input_audio_config: InputAudioConfig, **kwargs) ) -class DeepgramTranscriberConfig(TranscriberConfig, type=TranscriberType.DEEPGRAM.value): +class DeepgramTranscriberConfig(TranscriberConfig, type=TranscriberType.DEEPGRAM.value): # type: ignore language: Optional[str] = None model: Optional[str] = "nova" tier: Optional[str] = None version: Optional[str] = None keywords: Optional[list] = None + on_prem: bool = False + ws_url: str = DEEPGRAM_API_WS_URL -class GladiaTranscriberConfig(TranscriberConfig, type=TranscriberType.GLADIA.value): +class GladiaTranscriberConfig(TranscriberConfig, type=TranscriberType.GLADIA.value): # type: ignore buffer_size_seconds: float = 0.1 -class GoogleTranscriberConfig(TranscriberConfig, type=TranscriberType.GOOGLE.value): +class GoogleTranscriberConfig(TranscriberConfig, type=TranscriberType.GOOGLE.value): # type: ignore model: Optional[str] = None language_code: str = "en-US" -class AzureTranscriberConfig(TranscriberConfig, type=TranscriberType.AZURE.value): +class AzureTranscriberConfig(TranscriberConfig, type=TranscriberType.AZURE.value): # type: ignore language: str = AZURE_DEFAULT_LANGUAGE candidate_languages: Optional[List[str]] = None class AssemblyAITranscriberConfig( - TranscriberConfig, type=TranscriberType.ASSEMBLY_AI.value + TranscriberConfig, type=TranscriberType.ASSEMBLY_AI.value # type: ignore ): buffer_size_seconds: float = 0.1 word_boost: Optional[List[str]] = None @@ -134,12 +138,40 @@ class AssemblyAITranscriberConfig( class WhisperCPPTranscriberConfig( - TranscriberConfig, type=TranscriberType.WHISPER_CPP.value + TranscriberConfig, type=TranscriberType.WHISPER_CPP.value # type: ignore ): buffer_size_seconds: float = 1 libname: str fname_model: str -class RevAITranscriberConfig(TranscriberConfig, type=TranscriberType.REV_AI.value): +class RevAITranscriberConfig(TranscriberConfig, type=TranscriberType.REV_AI.value): # type: ignore pass + + +class Transcription(BaseModel): + message: str + confidence: float + is_final: bool + is_interrupt: bool = False + bot_was_in_medias_res: bool = False + duration_seconds: Optional[float] = None # gets added only on final transcription + + def __str__(self): + return ( + f"Transcription(message={self.message}, " + + f"confidence={self.confidence}, " + + f"is_final={self.is_final}, " + + f"is_interrupt={self.is_interrupt}, " + + f"bot_was_in_medias_res={self.bot_was_in_medias_res}, " + + f"duration_seconds={self.duration_seconds}, " + + f"wpm={self.wpm()}" + + ")" + ) + + def wpm(self) -> Optional[float]: + return ( + 60 * len(self.message.split()) / self.duration_seconds + if self.duration_seconds + else None + ) diff --git a/vocode/streaming/models/transcript.py b/vocode/streaming/models/transcript.py index 140a3adb9..380047d3a 100644 --- a/vocode/streaming/models/transcript.py +++ b/vocode/streaming/models/transcript.py @@ -1,10 +1,11 @@ import time -from typing import Any, Dict, List, Optional, Union +from datetime import datetime +from typing import List, Literal, Optional + from pydantic.v1 import BaseModel, Field -from enum import Enum -from vocode.streaming.models.actions import ActionInput, ActionOutput -from vocode.streaming.models.events import ActionEvent, Sender, Event, EventType +from vocode.streaming.models.actions import ActionInput, ActionOutput +from vocode.streaming.models.events import ActionEvent, Event, EventType, Sender from vocode.streaming.utils.events_manager import EventsManager @@ -15,14 +16,34 @@ class EventLog(BaseModel): def to_string(self, include_timestamp: bool = False) -> str: raise NotImplementedError + def get_timestamp_string(self, start_timestamp: float) -> str: + dt = datetime.fromtimestamp(self.timestamp - start_timestamp) + return f"[{dt.strftime('%M:%S')}.{dt.microsecond // 10000:02}]" + class Message(EventLog): text: str + is_final: bool = False + is_backchannel: bool = False + is_end_of_turn: bool = False - def to_string(self, include_timestamp: bool = False) -> str: + def to_string( + self, + include_timestamp: bool = False, + mark_human_backchannels_with_brackets: bool = False, + include_sender: bool = True, + ) -> str: + text = self.text + if not self.is_final and self.sender == Sender.BOT: + text = f"{text}-" + if self.is_backchannel and mark_human_backchannels_with_brackets: + text = f"[{text}]" if include_timestamp: - return f"{self.sender.name}: {self.text} ({self.timestamp})" - return f"{self.sender.name}: {self.text}" + return f"{self.sender.name}: {text} ({self.timestamp})" + elif include_sender: + return f"{self.sender.name}: {text}" + else: + return text class ActionStart(EventLog): @@ -30,21 +51,69 @@ class ActionStart(EventLog): action_type: str action_input: ActionInput - def to_string(self, include_timestamp: bool = False): + def to_string(self, include_timestamp: bool = False, include_header: bool = True): + main_string = self.action_input.action_config.action_attempt_to_string(self.action_input) + if include_header: + main_string = f"BOT_ACTION_START: {main_string}" if include_timestamp: - return f"{Sender.ACTION_WORKER.name}: params={self.action_input.params.dict()} ({self.timestamp})" - return f"{Sender.ACTION_WORKER.name}: params={self.action_input.params.dict()}" + return f"{main_string} ({self.timestamp})" + return main_string class ActionFinish(EventLog): sender: Sender = Sender.ACTION_WORKER action_type: str + action_input: ActionInput action_output: ActionOutput - def to_string(self, include_timestamp: bool = False): + def to_string(self, include_timestamp: bool = False, include_header: bool = True): + main_string = self.action_input.action_config.action_result_to_string( + self.action_input, self.action_output + ) + if include_header: + main_string = f"BOT_ACTION_FINISH: {main_string}" + if include_timestamp: + return f"{main_string} ({self.timestamp})" + return main_string + + +ConferenceEventType = Literal[ + "participant_joined", "participant_left", "participant_unanswered", "voicemail" +] +ConferenceEventRole = Literal["primary", "transfer"] + + +class ConferenceEvent(EventLog): + sender: Sender = Sender.CONFERENCE + conference_event_type: ConferenceEventType + conference_event_role: ConferenceEventRole + participant_phone_number: str + + def to_string(self, include_timestamp: bool = False, include_sender: bool = True): + if ( + self.conference_event_type == "participant_unanswered" + or self.conference_event_type == "voicemail" + ): + msg_string = f"{self.conference_event_role.capitalize()} number ({self.participant_phone_number}) did not join the conference because they are busy" + else: + verb = "joined" if self.conference_event_type == "participant_joined" else "left" + msg_string = f"{self.conference_event_role.capitalize()} number ({self.participant_phone_number}) {verb} the conference" + if include_sender: + msg_string = f"CONFERENCE_EVENT: {msg_string}" + if include_timestamp: + return f"{msg_string} ({self.timestamp})" + return msg_string + + +class TranscriptEvent(Event, type=EventType.TRANSCRIPT): # type: ignore + text: str + sender: Sender + timestamp: float + + def to_string(self, include_timestamp: bool = False) -> str: if include_timestamp: - return f"{Sender.ACTION_WORKER.name}: action_type='{self.action_type}' response={self.action_output.response.dict()} ({self.timestamp})" - return f"{Sender.ACTION_WORKER.name}: action_type='{self.action_type}' response={self.action_output.response.dict()}" + return f"{self.sender.name}: {self.text} ({self.timestamp})" + return f"{self.sender.name}: {self.text}" class Transcript(BaseModel): @@ -55,18 +124,29 @@ class Transcript(BaseModel): class Config: arbitrary_types_allowed = True + def to_string( + self, include_timestamps: bool = False, mark_human_backchannels_with_brackets: bool = False + ) -> str: + event_strings = [] + for event in self.event_logs: + if isinstance(event, Message): + event_string = event.to_string( + include_timestamp=False, + mark_human_backchannels_with_brackets=mark_human_backchannels_with_brackets, + ) + else: + event_string = event.to_string(include_timestamp=False) + + if include_timestamps: + event_string = f"{event.get_timestamp_string(self.start_time)} {event_string}" + event_strings.append(event_string) + + return "\n".join(event_strings) + def attach_events_manager(self, events_manager: EventsManager): self.events_manager = events_manager - def to_string(self, include_timestamps: bool = False) -> str: - return "\n".join( - event.to_string(include_timestamp=include_timestamps) - for event in self.event_logs - ) - - def maybe_publish_transcript_event_from_message( - self, message: Message, conversation_id: str - ): + def maybe_publish_transcript_event_from_message(self, message: Message, conversation_id: str): if self.events_manager is not None: self.events_manager.publish_event( TranscriptEvent( @@ -82,10 +162,18 @@ def add_message_from_props( text: str, sender: Sender, conversation_id: str, + is_final: bool = False, + is_backchannel: bool = False, publish_to_events_manager: bool = True, ): timestamp = time.time() - message = Message(text=text, sender=sender, timestamp=timestamp) + message = Message( + text=text, + sender=sender, + timestamp=timestamp, + is_final=is_final, + is_backchannel=is_backchannel, + ) self.event_logs.append(message) if publish_to_events_manager: self.maybe_publish_transcript_event_from_message( @@ -104,18 +192,20 @@ def add_message( message=message, conversation_id=conversation_id ) - def add_human_message(self, text: str, conversation_id: str): + def add_human_message(self, text: str, conversation_id: str, is_backchannel: bool = False): self.add_message_from_props( text=text, sender=Sender.HUMAN, conversation_id=conversation_id, + is_backchannel=is_backchannel, ) - def add_bot_message(self, text: str, conversation_id: str): + def add_bot_message(self, text: str, conversation_id: str, is_final: bool = False): self.add_message_from_props( text=text, sender=Sender.BOT, conversation_id=conversation_id, + is_final=is_final, ) def get_last_user_message(self): @@ -149,6 +239,7 @@ def add_action_finish_log( timestamp = time.time() self.event_logs.append( ActionFinish( + action_input=action_input, action_output=action_output, action_type=action_output.action_type, timestamp=timestamp, @@ -170,17 +261,17 @@ def update_last_bot_message_on_cut_off(self, text: str): event_log.text = text break - -class TranscriptEvent(Event, type=EventType.TRANSCRIPT): - text: str - sender: Sender - timestamp: float - - def to_string(self, include_timestamp: bool = False) -> str: - if include_timestamp: - return f"{self.sender.name}: {self.text} ({self.timestamp})" - return f"{self.sender.name}: {self.text}" + def was_last_message_interrupted(self): + bot_messages = [ + message + for message in self.event_logs + if isinstance(message, Message) and message.sender == Sender.BOT + ] + if len(bot_messages) > 0: + last_bot_message = bot_messages[-1] + return not last_bot_message.is_final or not last_bot_message.is_end_of_turn + return False -class TranscriptCompleteEvent(Event, type=EventType.TRANSCRIPT_COMPLETE): +class TranscriptCompleteEvent(Event, type=EventType.TRANSCRIPT_COMPLETE): # type: ignore transcript: Transcript diff --git a/vocode/streaming/models/vector_db.py b/vocode/streaming/models/vector_db.py index b87c5bade..44fdf64c6 100644 --- a/vocode/streaming/models/vector_db.py +++ b/vocode/streaming/models/vector_db.py @@ -1,5 +1,6 @@ from enum import Enum from typing import Optional + from .model import TypedModel DEFAULT_EMBEDDINGS_MODEL = "text-embedding-ada-002" @@ -10,12 +11,12 @@ class VectorDBType(str, Enum): PINECONE = "vector_db_pinecone" -class VectorDBConfig(TypedModel, type=VectorDBType.BASE.value): +class VectorDBConfig(TypedModel, type=VectorDBType.BASE.value): # type: ignore embeddings_model: str = DEFAULT_EMBEDDINGS_MODEL -class PineconeConfig(VectorDBConfig, type=VectorDBType.PINECONE.value): +class PineconeConfig(VectorDBConfig, type=VectorDBType.PINECONE.value): # type: ignore index: str - api_key: Optional[str] = None - api_environment: Optional[str] = None + api_key: Optional[str] + api_environment: Optional[str] top_k: int = 3 diff --git a/vocode/streaming/models/websocket.py b/vocode/streaming/models/websocket.py index 41a302dc6..ab1f8e42b 100644 --- a/vocode/streaming/models/websocket.py +++ b/vocode/streaming/models/websocket.py @@ -2,14 +2,13 @@ from enum import Enum from typing import Optional -from vocode.streaming.models.audio_encoding import AudioEncoding -from vocode.streaming.models.client_backend import InputAudioConfig, OutputAudioConfig -from .model import TypedModel -from .transcriber import TranscriberConfig from .agent import AgentConfig -from .synthesizer import SynthesizerConfig from .events import Sender +from .model import TypedModel +from .synthesizer import SynthesizerConfig +from .transcriber import TranscriberConfig from .transcript import TranscriptEvent +from vocode.streaming.models.client_backend import InputAudioConfig, OutputAudioConfig class WebSocketMessageType(str, Enum): @@ -22,11 +21,11 @@ class WebSocketMessageType(str, Enum): AUDIO_CONFIG_START = "websocket_audio_config_start" -class WebSocketMessage(TypedModel, type=WebSocketMessageType.BASE): +class WebSocketMessage(TypedModel, type=WebSocketMessageType.BASE): # type: ignore pass -class AudioMessage(WebSocketMessage, type=WebSocketMessageType.AUDIO): +class AudioMessage(WebSocketMessage, type=WebSocketMessageType.AUDIO): # type: ignore data: str @classmethod @@ -37,7 +36,7 @@ def get_bytes(self) -> bytes: return base64.b64decode(self.data) -class TranscriptMessage(WebSocketMessage, type=WebSocketMessageType.TRANSCRIPT): +class TranscriptMessage(WebSocketMessage, type=WebSocketMessageType.TRANSCRIPT): # type: ignore text: str sender: Sender timestamp: float @@ -47,7 +46,7 @@ def from_event(cls, event: TranscriptEvent): return cls(text=event.text, sender=event.sender, timestamp=event.timestamp) -class StartMessage(WebSocketMessage, type=WebSocketMessageType.START): +class StartMessage(WebSocketMessage, type=WebSocketMessageType.START): # type: ignore transcriber_config: TranscriberConfig agent_config: AgentConfig synthesizer_config: SynthesizerConfig @@ -55,7 +54,7 @@ class StartMessage(WebSocketMessage, type=WebSocketMessageType.START): class AudioConfigStartMessage( - WebSocketMessage, type=WebSocketMessageType.AUDIO_CONFIG_START + WebSocketMessage, type=WebSocketMessageType.AUDIO_CONFIG_START # type: ignore ): input_audio_config: InputAudioConfig output_audio_config: OutputAudioConfig @@ -63,9 +62,9 @@ class AudioConfigStartMessage( subscribe_transcript: Optional[bool] = None -class ReadyMessage(WebSocketMessage, type=WebSocketMessageType.READY): +class ReadyMessage(WebSocketMessage, type=WebSocketMessageType.READY): # type: ignore pass -class StopMessage(WebSocketMessage, type=WebSocketMessageType.STOP): +class StopMessage(WebSocketMessage, type=WebSocketMessageType.STOP): # type: ignore pass diff --git a/vocode/streaming/models/websocket_agent.py b/vocode/streaming/models/websocket_agent.py index c94224260..f9d06e59e 100644 --- a/vocode/streaming/models/websocket_agent.py +++ b/vocode/streaming/models/websocket_agent.py @@ -1,7 +1,7 @@ from enum import Enum from typing import Optional -from vocode.streaming.models.agent import AgentConfig, AgentType +from vocode.streaming.models.agent import AgentConfig, AgentType from vocode.streaming.models.model import BaseModel, TypedModel @@ -11,12 +11,12 @@ class WebSocketAgentMessageType(str, Enum): STOP = "websocket_agent_stop" -class WebSocketAgentMessage(TypedModel, type=WebSocketAgentMessageType.BASE): +class WebSocketAgentMessage(TypedModel, type=WebSocketAgentMessageType.BASE): # type: ignore conversation_id: Optional[str] = None class WebSocketAgentTextMessage( - WebSocketAgentMessage, type=WebSocketAgentMessageType.TEXT + WebSocketAgentMessage, type=WebSocketAgentMessageType.TEXT # type: ignore ): class Payload(BaseModel): text: str @@ -29,13 +29,13 @@ def from_text(cls, text: str, conversation_id: Optional[str] = None): class WebSocketAgentStopMessage( - WebSocketAgentMessage, type=WebSocketAgentMessageType.STOP + WebSocketAgentMessage, type=WebSocketAgentMessageType.STOP # type: ignore ): pass class WebSocketUserImplementedAgentConfig( - AgentConfig, type=AgentType.WEBSOCKET_USER_IMPLEMENTED.value + AgentConfig, type=AgentType.WEBSOCKET_USER_IMPLEMENTED.value # type: ignore ): class RouteConfig(BaseModel): url: str diff --git a/vocode/streaming/output_device/base_output_device.py b/vocode/streaming/output_device/base_output_device.py index 52bb7bcbe..2ce90d5c2 100644 --- a/vocode/streaming/output_device/base_output_device.py +++ b/vocode/streaming/output_device/base_output_device.py @@ -1,4 +1,4 @@ -from vocode.streaming.models.audio_encoding import AudioEncoding +from vocode.streaming.models.audio import AudioEncoding class BaseOutputDevice: @@ -12,8 +12,5 @@ def start(self): def consume_nonblocking(self, chunk: bytes): raise NotImplemented - def maybe_send_mark_nonblocking(self, message): - pass - def terminate(self): pass diff --git a/vocode/streaming/output_device/blocking_speaker_output.py b/vocode/streaming/output_device/blocking_speaker_output.py index 7c402fbf3..ba1515d9c 100644 --- a/vocode/streaming/output_device/blocking_speaker_output.py +++ b/vocode/streaming/output_device/blocking_speaker_output.py @@ -1,10 +1,11 @@ import asyncio import queue from typing import Optional -import sounddevice as sd + import numpy as np -from vocode.streaming.models.audio_encoding import AudioEncoding +import sounddevice as sd +from vocode.streaming.models.audio import AudioEncoding from vocode.streaming.output_device.base_output_device import BaseOutputDevice from vocode.streaming.utils.worker import ThreadAsyncWorker @@ -22,7 +23,7 @@ def __init__( sampling_rate = sampling_rate or int( self.device_info.get("default_samplerate", self.DEFAULT_SAMPLING_RATE) ) - self.input_queue = asyncio.Queue() + self.input_queue: asyncio.Queue[bytes] = asyncio.Queue() BaseOutputDevice.__init__(self, sampling_rate, audio_encoding) ThreadAsyncWorker.__init__(self, self.input_queue) self.stream = sd.OutputStream( diff --git a/vocode/streaming/output_device/file_output_device.py b/vocode/streaming/output_device/file_output_device.py index 3538bee7c..d9ab22d8d 100644 --- a/vocode/streaming/output_device/file_output_device.py +++ b/vocode/streaming/output_device/file_output_device.py @@ -1,10 +1,11 @@ +import asyncio import wave from asyncio import Queue -import asyncio + import numpy as np from .base_output_device import BaseOutputDevice -from vocode.streaming.models.audio_encoding import AudioEncoding +from vocode.streaming.models.audio import AudioEncoding from vocode.streaming.utils.worker import ThreadAsyncWorker diff --git a/vocode/streaming/output_device/speaker_output.py b/vocode/streaming/output_device/speaker_output.py index 69c0729f0..543dbbfb0 100644 --- a/vocode/streaming/output_device/speaker_output.py +++ b/vocode/streaming/output_device/speaker_output.py @@ -1,10 +1,11 @@ import queue from typing import Optional -import sounddevice as sd + import numpy as np +import sounddevice as sd from .base_output_device import BaseOutputDevice -from vocode.streaming.models.audio_encoding import AudioEncoding +from vocode.streaming.models.audio import AudioEncoding class SpeakerOutput(BaseOutputDevice): diff --git a/vocode/streaming/output_device/twilio_output_device.py b/vocode/streaming/output_device/twilio_output_device.py index f92c20d02..0563f08cf 100644 --- a/vocode/streaming/output_device/twilio_output_device.py +++ b/vocode/streaming/output_device/twilio_output_device.py @@ -1,31 +1,25 @@ from __future__ import annotations import asyncio -import json import base64 +import json from typing import Optional from fastapi import WebSocket from vocode.streaming.output_device.base_output_device import BaseOutputDevice -from vocode.streaming.telephony.constants import ( - DEFAULT_AUDIO_ENCODING, - DEFAULT_SAMPLING_RATE, -) +from vocode.streaming.telephony.constants import DEFAULT_AUDIO_ENCODING, DEFAULT_SAMPLING_RATE +from vocode.streaming.utils.create_task import asyncio_create_task_with_done_error_log class TwilioOutputDevice(BaseOutputDevice): - def __init__( - self, ws: Optional[WebSocket] = None, stream_sid: Optional[str] = None - ): - super().__init__( - sampling_rate=DEFAULT_SAMPLING_RATE, audio_encoding=DEFAULT_AUDIO_ENCODING - ) + def __init__(self, ws: Optional[WebSocket] = None, stream_sid: Optional[str] = None): + super().__init__(sampling_rate=DEFAULT_SAMPLING_RATE, audio_encoding=DEFAULT_AUDIO_ENCODING) self.ws = ws self.stream_sid = stream_sid self.active = True self.queue: asyncio.Queue[str] = asyncio.Queue() - self.process_task = asyncio.create_task(self.process()) + self.process_task = asyncio_create_task_with_done_error_log(self.process()) async def process(self): while self.active: @@ -40,15 +34,32 @@ def consume_nonblocking(self, chunk: bytes): } self.queue.put_nowait(json.dumps(twilio_message)) - def maybe_send_mark_nonblocking(self, message_sent): + def send_chunk_finished_mark(self, utterance_id, chunk_idx): mark_message = { "event": "mark", "streamSid": self.stream_sid, "mark": { - "name": "Sent {}".format(message_sent), + "name": f"chunk-{utterance_id}-{chunk_idx}", }, } self.queue.put_nowait(json.dumps(mark_message)) + def send_utterance_finished_mark(self, utterance_id): + mark_message = { + "event": "mark", + "streamSid": self.stream_sid, + "mark": { + "name": f"utterance-{utterance_id}", + }, + } + self.queue.put_nowait(json.dumps(mark_message)) + + def send_clear_message(self): + clear_message = { + "event": "clear", + "streamSid": self.stream_sid, + } + self.queue.put_nowait(json.dumps(clear_message)) + def terminate(self): self.process_task.cancel() diff --git a/vocode/streaming/output_device/vonage_output_device.py b/vocode/streaming/output_device/vonage_output_device.py index 186c9d0aa..646630322 100644 --- a/vocode/streaming/output_device/vonage_output_device.py +++ b/vocode/streaming/output_device/vonage_output_device.py @@ -1,16 +1,17 @@ import asyncio from typing import Optional -import wave from fastapi import WebSocket -from vocode.streaming.models.audio_encoding import AudioEncoding + from vocode.streaming.output_device.base_output_device import BaseOutputDevice from vocode.streaming.output_device.speaker_output import SpeakerOutput from vocode.streaming.telephony.constants import ( + PCM_SILENCE_BYTE, VONAGE_AUDIO_ENCODING, VONAGE_CHUNK_SIZE, VONAGE_SAMPLING_RATE, ) +from vocode.streaming.utils.create_task import asyncio_create_task_with_done_error_log class VonageOutputDevice(BaseOutputDevice): @@ -19,13 +20,11 @@ def __init__( ws: Optional[WebSocket] = None, output_to_speaker: bool = False, ): - super().__init__( - sampling_rate=VONAGE_SAMPLING_RATE, audio_encoding=VONAGE_AUDIO_ENCODING - ) + super().__init__(sampling_rate=VONAGE_SAMPLING_RATE, audio_encoding=VONAGE_AUDIO_ENCODING) self.ws = ws self.active = True self.queue: asyncio.Queue[bytes] = asyncio.Queue() - self.process_task = asyncio.create_task(self.process()) + self.process_task = asyncio_create_task_with_done_error_log(self.process()) self.output_to_speaker = output_to_speaker if output_to_speaker: self.output_speaker = SpeakerOutput.from_default_device( @@ -39,13 +38,12 @@ async def process(self): self.output_speaker.consume_nonblocking(chunk) for i in range(0, len(chunk), VONAGE_CHUNK_SIZE): subchunk = chunk[i : i + VONAGE_CHUNK_SIZE] + if len(subchunk) % 2 == 1: + subchunk += PCM_SILENCE_BYTE # pad with silence, Vonage goes crazy otherwise await self.ws.send_bytes(subchunk) def consume_nonblocking(self, chunk: bytes): self.queue.put_nowait(chunk) - def maybe_send_mark_nonblocking(self, message_sent): - pass - def terminate(self): self.process_task.cancel() diff --git a/vocode/streaming/output_device/websocket_output_device.py b/vocode/streaming/output_device/websocket_output_device.py index 53f82f622..ca0133c14 100644 --- a/vocode/streaming/output_device/websocket_output_device.py +++ b/vocode/streaming/output_device/websocket_output_device.py @@ -1,18 +1,18 @@ from __future__ import annotations import asyncio + from fastapi import WebSocket -from vocode.streaming.models.audio_encoding import AudioEncoding -from vocode.streaming.output_device.base_output_device import BaseOutputDevice -from vocode.streaming.models.websocket import AudioMessage -from vocode.streaming.models.websocket import TranscriptMessage + +from vocode.streaming.models.audio import AudioEncoding from vocode.streaming.models.transcript import TranscriptEvent +from vocode.streaming.models.websocket import AudioMessage, TranscriptMessage +from vocode.streaming.output_device.base_output_device import BaseOutputDevice +from vocode.streaming.utils.create_task import asyncio_create_task_with_done_error_log class WebsocketOutputDevice(BaseOutputDevice): - def __init__( - self, ws: WebSocket, sampling_rate: int, audio_encoding: AudioEncoding - ): + def __init__(self, ws: WebSocket, sampling_rate: int, audio_encoding: AudioEncoding): super().__init__(sampling_rate, audio_encoding) self.ws = ws self.active = False @@ -20,7 +20,7 @@ def __init__( def start(self): self.active = True - self.process_task = asyncio.create_task(self.process()) + self.process_task = asyncio_create_task_with_done_error_log(self.process()) def mark_closed(self): self.active = False diff --git a/vocode/streaming/streaming_conversation.py b/vocode/streaming/streaming_conversation.py index 0bf22cd86..13162bbdf 100644 --- a/vocode/streaming/streaming_conversation.py +++ b/vocode/streaming/streaming_conversation.py @@ -3,71 +3,105 @@ import asyncio import queue import random +import re import threading -from typing import Any, Awaitable, Callable, Generic, Optional, Tuple, TypeVar, cast -import logging import time import typing - -from vocode.streaming.action.worker import ActionsWorker - -from vocode.streaming.agent.bot_sentiment_analyser import ( - BotSentimentAnalyser, -) -from vocode.streaming.agent.chat_gpt_agent import ChatGPTAgent -from vocode.streaming.models.actions import ActionInput -from vocode.streaming.models.events import Sender -from vocode.streaming.models.transcript import ( - Message, - Transcript, - TranscriptCompleteEvent, +from typing import ( + Any, + AsyncGenerator, + Awaitable, + Callable, + Generic, + Iterator, + List, + Optional, + Tuple, + TypeVar, + Union, ) -from vocode.streaming.models.message import BaseMessage -from vocode.streaming.models.transcriber import EndpointingConfig, TranscriberConfig -from vocode.streaming.output_device.base_output_device import BaseOutputDevice -from vocode.streaming.utils.conversation_logger_adapter import wrap_logger -from vocode.streaming.utils.events_manager import EventsManager -from vocode.streaming.utils.goodbye_model import GoodbyeModel -from vocode.streaming.models.agent import ChatGPTAgentConfig, FillerAudioConfig -from vocode.streaming.models.synthesizer import ( - SentimentConfig, -) -from vocode.streaming.constants import ( - TEXT_TO_SPEECH_CHUNK_SIZE_SECONDS, - PER_CHUNK_ALLOWANCE_SECONDS, - ALLOWED_IDLE_TIME, -) +import sentry_sdk +from loguru import logger +from sentry_sdk.tracing import Span + +from vocode.streaming.action.worker import ActionsWorker from vocode.streaming.agent.base_agent import ( AgentInput, AgentResponse, AgentResponseFillerAudio, AgentResponseMessage, AgentResponseStop, - AgentResponseType, BaseAgent, TranscriptionAgentInput, ) +from vocode.streaming.agent.chat_gpt_agent import ChatGPTAgent +from vocode.streaming.constants import ( + ALLOWED_IDLE_TIME, + CHECK_HUMAN_PRESENT_MESSAGE_CHOICES, + PER_CHUNK_ALLOWANCE_SECONDS, + TEXT_TO_SPEECH_CHUNK_SIZE_SECONDS, +) +from vocode.streaming.models.actions import EndOfTurn +from vocode.streaming.models.agent import FillerAudioConfig +from vocode.streaming.models.events import Sender +from vocode.streaming.models.message import BaseMessage, BotBackchannel, LLMToken, SilenceMessage +from vocode.streaming.models.transcriber import TranscriberConfig, Transcription +from vocode.streaming.models.transcript import Message, Transcript, TranscriptCompleteEvent +from vocode.streaming.output_device.base_output_device import BaseOutputDevice from vocode.streaming.synthesizer.base_synthesizer import ( BaseSynthesizer, - SynthesisResult, FillerAudio, + SynthesisResult, ) +from vocode.streaming.synthesizer.input_streaming_synthesizer import InputStreamingSynthesizer +from vocode.streaming.transcriber.base_transcriber import BaseTranscriber +from vocode.streaming.transcriber.deepgram_transcriber import DeepgramTranscriber from vocode.streaming.utils import create_conversation_id, get_chunk_size_per_second -from vocode.streaming.transcriber.base_transcriber import ( - Transcription, - BaseTranscriber, -) +from vocode.streaming.utils.create_task import asyncio_create_task_with_done_error_log +from vocode.streaming.utils.events_manager import EventsManager +from vocode.streaming.utils.speed_manager import SpeedManager from vocode.streaming.utils.state_manager import ConversationStateManager from vocode.streaming.utils.worker import ( AsyncQueueWorker, + InterruptibleAgentResponseEvent, InterruptibleAgentResponseWorker, InterruptibleEvent, InterruptibleEventFactory, - InterruptibleAgentResponseEvent, - InterruptibleWorker, +) +from vocode.utils.sentry_utils import ( + CustomSentrySpans, + complete_span_by_op, + sentry_create_span, + synthesizer_base_name_if_should_report_to_sentry, ) +BACKCHANNEL_PATTERNS = [ + r"m+-?hm+", + r"m+", + r"oh+", + r"ah+", + r"um+", + r"uh+", + "yes", + "sure", + "quite", + "right", + "really", + "good heavens", + "i see", + "of course", + "oh dear", + "oh god", + "thats nice", + "thats not bad", + "thats right", + r"yeah+", + "makes sense", +] +LOW_INTERRUPT_SENSITIVITY_BACKCHANNEL_UTTERANCE_LENGTH_THRESHOLD = 3 + + OutputDeviceType = TypeVar("OutputDeviceType", bound=BaseOutputDevice) @@ -77,10 +111,13 @@ def __init__(self, conversation: "StreamingConversation"): self.conversation = conversation def create_interruptible_event( - self, payload: Any, is_interruptible: bool = True + self, + payload: Any, + is_interruptible: bool = True, ) -> InterruptibleEvent[Any]: - interruptible_event: InterruptibleEvent = ( - super().create_interruptible_event(payload, is_interruptible) + interruptible_event: InterruptibleEvent = super().create_interruptible_event( + payload, + is_interruptible, ) self.conversation.interruptible_events.put_nowait(interruptible_event) return interruptible_event @@ -115,42 +152,163 @@ def __init__( self.output_queue = output_queue self.conversation = conversation self.interruptible_event_factory = interruptible_event_factory + self.in_interrupt_endpointing_config = False + self.deepgram_transcriber: Optional[DeepgramTranscriber] = None + if isinstance(self.conversation.transcriber, DeepgramTranscriber): + self.deepgram_transcriber = self.conversation.transcriber + self.has_associated_ignored_utterance: bool = False + self.has_associated_unignored_utterance: bool = False + self.human_backchannels_buffer: List[Transcription] = [] + self.ignore_next_message: bool = False + + def should_ignore_utterance(self, transcription: Transcription): + if self.has_associated_unignored_utterance: + return False + bot_still_speaking = self.is_bot_still_speaking() + if self.has_associated_ignored_utterance or bot_still_speaking: + logger.info( + f"Associated ignored utterance: {self.has_associated_ignored_utterance}. Bot still speaking: {bot_still_speaking}" + ) + return self.is_transcription_backchannel(transcription) + return False + + def is_transcription_backchannel(self, transcription: Transcription): + num_words = len(transcription.message.strip().split()) + if ( + self.conversation.agent.get_agent_config().interrupt_sensitivity == "high" + and num_words >= 1 + ): + logger.info(f"High interrupt sensitivity; {num_words} word(s) not a backchannel") + return False + + if num_words <= LOW_INTERRUPT_SENSITIVITY_BACKCHANNEL_UTTERANCE_LENGTH_THRESHOLD: + return True + cleaned = re.sub("[^\w\s]", "", transcription.message).strip().lower() + return any(re.fullmatch(regex, cleaned) for regex in BACKCHANNEL_PATTERNS) + + def _most_recent_transcript_messages(self) -> Iterator[Message]: + return ( + event_log + for event_log in reversed(self.conversation.transcript.event_logs) + if isinstance(event_log, Message) + ) + + def get_maybe_last_transcript_event_log(self) -> Optional[Message]: + return next(self._most_recent_transcript_messages(), None) + + def is_bot_in_medias_res(self): + last_message = self.get_maybe_last_transcript_event_log() + return ( + last_message is not None + and not last_message.is_backchannel + and last_message.sender == Sender.BOT + and not last_message.is_final + and last_message.text.strip() != "" + ) + + def is_bot_still_speaking(self): # in_medias_res OR bot has more utterances + transcript_messages_iter = self._most_recent_transcript_messages() + last_message, second_to_last_message = next(transcript_messages_iter, None), next( + transcript_messages_iter, None + ) + + is_first_bot_message = ( + second_to_last_message is None or second_to_last_message.sender == Sender.HUMAN + ) + + return ( + last_message is not None + and not last_message.is_backchannel + and last_message.sender == Sender.BOT + and (not last_message.is_final or not last_message.is_end_of_turn) + and not (is_first_bot_message and last_message.text.strip() == "") + ) async def process(self, transcription: Transcription): self.conversation.mark_last_action_timestamp() if transcription.message.strip() == "": - self.conversation.logger.info("Ignoring empty transcription") + logger.info("Ignoring empty transcription") + return + # ignore utterances during the initial message but still add them to the transcript + initial_message_ongoing = not self.conversation.initial_message_tracker.is_set() + if initial_message_ongoing or self.should_ignore_utterance(transcription): + logger.info( + f"Ignoring utterance: {transcription.message}. IMO: {initial_message_ongoing}" + ) + self.has_associated_ignored_utterance = ( + not transcription.is_final # if it's final, we're done with this backchannel + ) + if transcription.is_final: + # for all ignored backchannels, store them to be added to the transcript later + self.human_backchannels_buffer.append(transcription) + return + if self.ignore_next_message and transcription.is_final: + # TODO: delete this once transcription reset is implemented for processing conference voicemail + # Push human message to transcript but do not respond + self.has_associated_ignored_utterance = False + agent_response_tracker = None + self.ignore_next_message = False return if transcription.is_final: - self.conversation.logger.debug( - "Got transcription: {}, confidence: {}".format( - transcription.message, transcription.confidence + if ( + self.deepgram_transcriber is not None + and self.deepgram_transcriber.is_first_transcription + ): + logger.debug( + "Switching to non-first transcription endpointing config if configured" + ) + self.deepgram_transcriber.is_first_transcription = False + logger.debug( + "Got transcription: {}, confidence: {}, wpm: {}".format( + transcription.message, + transcription.confidence, + transcription.wpm(), ) ) - if ( - not self.conversation.is_human_speaking - and self.conversation.is_interrupt(transcription) - ): + if not self.conversation.is_human_speaking: self.conversation.current_transcription_is_interrupt = ( self.conversation.broadcast_interrupt() ) + self.has_associated_unignored_utterance = not transcription.is_final if self.conversation.current_transcription_is_interrupt: - self.conversation.logger.debug("sending interrupt") - self.conversation.logger.debug("Human started speaking") + logger.debug("sent interrupt") + logger.debug("Human started speaking") - transcription.is_interrupt = ( - self.conversation.current_transcription_is_interrupt - ) + transcription.is_interrupt = self.conversation.current_transcription_is_interrupt self.conversation.is_human_speaking = not transcription.is_final if transcription.is_final: - # we use getattr here to avoid the dependency cycle between VonageCall and StreamingConversation + self.has_associated_ignored_utterance = False + self.has_associated_unignored_utterance = False + agent_response_tracker = None + + # clear out backchannels and add to the transcript + for human_backchannel in self.human_backchannels_buffer: + self.conversation.transcript.add_human_message( + text=human_backchannel.message, + conversation_id=self.conversation.id, + is_backchannel=True, + ) + self.human_backchannels_buffer = [] + + if transcription.is_interrupt: + transcription.bot_was_in_medias_res = self.is_bot_in_medias_res() + logger.debug( + f"Bot is {'not ' if not transcription.bot_was_in_medias_res else ''}in medias res" + ) + + self.conversation.speed_manager.update(transcription) + + self.conversation.warmup_synthesizer() + + # we use getattr here to avoid the dependency cycle between PhoneConversation and StreamingConversation event = self.interruptible_event_factory.create_interruptible_event( TranscriptionAgentInput( transcription=transcription, conversation_id=self.conversation.id, vonage_uuid=getattr(self.conversation, "vonage_uuid", None), twilio_sid=getattr(self.conversation, "twilio_sid", None), - ) + agent_response_tracker=agent_response_tracker, + ), ) self.output_queue.put_nowait(event) @@ -173,16 +331,14 @@ def __init__( self.filler_audio_started_event: Optional[threading.Event] = None async def wait_for_filler_audio_to_finish(self): - if ( - self.filler_audio_started_event is None - or not self.filler_audio_started_event.set() - ): - self.conversation.logger.debug( - "Not waiting for filler audio to finish since we didn't send any chunks" + if self.filler_audio_started_event is None or not self.filler_audio_started_event.set(): + logger.debug( + "Not waiting for filler audio to finish since we didn't send any chunks", ) return if self.interruptible_event and isinstance( - self.interruptible_event, InterruptibleAgentResponseEvent + self.interruptible_event, + InterruptibleAgentResponseEvent, ): await self.interruptible_event.agent_response_tracker.wait() @@ -195,11 +351,9 @@ async def process(self, item: InterruptibleAgentResponseEvent[FillerAudio]): assert self.conversation.filler_audio_config is not None filler_synthesis_result = filler_audio.create_synthesis_result() self.current_filler_seconds_per_chunk = filler_audio.seconds_per_chunk - silence_threshold = ( - self.conversation.filler_audio_config.silence_threshold_seconds - ) + silence_threshold = self.conversation.filler_audio_config.silence_threshold_seconds await asyncio.sleep(silence_threshold) - self.conversation.logger.debug("Sending filler audio to output") + logger.debug("Sending filler audio to output") self.filler_audio_started_event = threading.Event() await self.conversation.send_speech_to_output( filler_audio.message.text, @@ -219,7 +373,9 @@ def __init__( self, input_queue: asyncio.Queue[InterruptibleAgentResponseEvent[AgentResponse]], output_queue: asyncio.Queue[ - InterruptibleAgentResponseEvent[Tuple[BaseMessage, SynthesisResult]] + InterruptibleAgentResponseEvent[ + Tuple[Union[BaseMessage, EndOfTurn], Optional[SynthesisResult]] + ] ], conversation: "StreamingConversation", interruptible_event_factory: InterruptibleEventFactory, @@ -232,22 +388,16 @@ def __init__( self.output_queue = output_queue self.conversation = conversation self.interruptible_event_factory = interruptible_event_factory - self.chunk_size = ( - get_chunk_size_per_second( - self.conversation.synthesizer.get_synthesizer_config().audio_encoding, - self.conversation.synthesizer.get_synthesizer_config().sampling_rate, - ) - * TEXT_TO_SPEECH_CHUNK_SIZE_SECONDS - ) + self.chunk_size = self.conversation._get_synthesizer_chunk_size() + self.last_agent_response_tracker: Optional[asyncio.Event] = None + self.is_first_text_chunk = True def send_filler_audio(self, agent_response_tracker: Optional[asyncio.Event]): assert self.conversation.filler_audio_worker is not None - self.conversation.logger.debug("Sending filler audio") + logger.debug("Sending filler audio") if self.conversation.synthesizer.filler_audios: - filler_audio = random.choice( - self.conversation.synthesizer.filler_audios - ) - self.conversation.logger.debug(f"Chose {filler_audio.message.text}") + filler_audio = random.choice(self.conversation.synthesizer.filler_audios) + logger.debug(f"Chose {filler_audio.message.text}") event = self.interruptible_event_factory.create_interruptible_agent_response_event( filler_audio, is_interruptible=filler_audio.is_interruptible, @@ -255,15 +405,11 @@ def send_filler_audio(self, agent_response_tracker: Optional[asyncio.Event]): ) self.conversation.filler_audio_worker.consume_nonblocking(event) else: - self.conversation.logger.debug( - "No filler audio available for synthesizer" - ) + logger.debug("No filler audio available for synthesizer") async def process(self, item: InterruptibleAgentResponseEvent[AgentResponse]): if not self.conversation.synthesis_enabled: - self.conversation.logger.debug( - "Synthesis disabled, not synthesizing speech" - ) + logger.debug("Synthesis disabled, not synthesizing speech") return try: agent_response = item.payload @@ -271,32 +417,101 @@ async def process(self, item: InterruptibleAgentResponseEvent[AgentResponse]): self.send_filler_audio(item.agent_response_tracker) return if isinstance(agent_response, AgentResponseStop): - self.conversation.logger.debug("Agent requested to stop") + logger.debug("Agent requested to stop") + if self.last_agent_response_tracker is not None: + await self.last_agent_response_tracker.wait() item.agent_response_tracker.set() - await self.conversation.terminate() + self.conversation.mark_terminated(bot_disconnect=True) return - agent_response_message = typing.cast( - AgentResponseMessage, agent_response - ) + agent_response_message = typing.cast(AgentResponseMessage, agent_response) if self.conversation.filler_audio_worker is not None: - if ( - self.conversation.filler_audio_worker.interrupt_current_filler_audio() - ): + if self.conversation.filler_audio_worker.interrupt_current_filler_audio(): await self.conversation.filler_audio_worker.wait_for_filler_audio_to_finish() - self.conversation.logger.debug("Synthesizing speech for message") - synthesis_result = await self.conversation.synthesizer.create_speech( - agent_response_message.message, - self.chunk_size, - bot_sentiment=self.conversation.bot_sentiment, - ) - self.produce_interruptible_agent_response_event_nonblocking( - (agent_response_message.message, synthesis_result), - is_interruptible=item.is_interruptible, - agent_response_tracker=item.agent_response_tracker, + if isinstance(agent_response_message.message, EndOfTurn): + logger.debug("Sending end of turn") + if isinstance(self.conversation.synthesizer, InputStreamingSynthesizer): + await self.conversation.synthesizer.handle_end_of_turn() + self.produce_interruptible_agent_response_event_nonblocking( + (agent_response_message.message, None), + is_interruptible=item.is_interruptible, + agent_response_tracker=item.agent_response_tracker, + ) + self.is_first_text_chunk = True + return + + synthesizer_base_name: Optional[str] = ( + synthesizer_base_name_if_should_report_to_sentry(self.conversation.synthesizer) ) + create_speech_span: Optional[Span] = None + ttft_span: Optional[Span] = None + synthesis_span: Optional[Span] = None + if synthesizer_base_name and agent_response_message.is_first: + complete_span_by_op(CustomSentrySpans.LANGUAGE_MODEL_TIME_TO_FIRST_TOKEN) + + sentry_create_span( + sentry_callable=sentry_sdk.start_span, + op=CustomSentrySpans.SYNTHESIS_TIME_TO_FIRST_TOKEN, + ) + + synthesis_span = sentry_create_span( + sentry_callable=sentry_sdk.start_span, + op=f"{synthesizer_base_name}{CustomSentrySpans.SYNTHESIZER_SYNTHESIS_TOTAL}", + ) + if synthesis_span: + ttft_span = sentry_create_span( + sentry_callable=synthesis_span.start_child, + op=f"{synthesizer_base_name}{CustomSentrySpans.SYNTHESIZER_TIME_TO_FIRST_TOKEN}", + ) + if ttft_span: + create_speech_span = sentry_create_span( + sentry_callable=ttft_span.start_child, + op=f"{synthesizer_base_name}{CustomSentrySpans.SYNTHESIZER_CREATE_SPEECH}", + ) + maybe_synthesis_result: Optional[SynthesisResult] = None + if isinstance( + self.conversation.synthesizer, + InputStreamingSynthesizer, + ) and isinstance(agent_response_message.message, LLMToken): + logger.debug("Sending chunk to synthesizer") + await self.conversation.synthesizer.send_token_to_synthesizer( + message=agent_response_message.message, + chunk_size=self.chunk_size, + ) + else: + logger.debug("Synthesizing speech for message") + maybe_synthesis_result = await self.conversation.synthesizer.create_speech( + agent_response_message.message, + self.chunk_size, + is_first_text_chunk=self.is_first_text_chunk, + is_sole_text_chunk=agent_response_message.is_sole_text_chunk, + ) + if create_speech_span: + create_speech_span.finish() + # For input streaming synthesizers, subsequent chunks are contained in the same SynthesisResult + if isinstance(self.conversation.synthesizer, InputStreamingSynthesizer): + if not self.is_first_text_chunk: + maybe_synthesis_result = None + elif isinstance(agent_response_message.message, LLMToken): + maybe_synthesis_result = ( + self.conversation.synthesizer.get_current_utterance_synthesis_result() + ) + if maybe_synthesis_result is not None: + synthesis_result = maybe_synthesis_result + synthesis_result.is_first = agent_response_message.is_first + if not synthesis_result.cached and synthesis_span: + synthesis_result.synthesis_total_span = synthesis_span + synthesis_result.ttft_span = ttft_span + self.produce_interruptible_agent_response_event_nonblocking( + (agent_response_message.message, synthesis_result), + is_interruptible=item.is_interruptible, + agent_response_tracker=item.agent_response_tracker, + ) + self.last_agent_response_tracker = item.agent_response_tracker + if not isinstance(agent_response_message.message, SilenceMessage): + self.is_first_text_chunk = False except asyncio.CancelledError: pass @@ -306,30 +521,47 @@ class SynthesisResultsWorker(InterruptibleAgentResponseWorker): def __init__( self, input_queue: asyncio.Queue[ - InterruptibleAgentResponseEvent[Tuple[BaseMessage, SynthesisResult]] + InterruptibleAgentResponseEvent[ + Tuple[Union[BaseMessage, EndOfTurn], Optional[SynthesisResult]] + ] ], conversation: "StreamingConversation", ): super().__init__(input_queue=input_queue) self.input_queue = input_queue self.conversation = conversation + self.last_transcript_message: Optional[Message] = None async def process( self, - item: InterruptibleAgentResponseEvent[Tuple[BaseMessage, SynthesisResult]], + item: InterruptibleAgentResponseEvent[ + Tuple[Union[BaseMessage, EndOfTurn], Optional[SynthesisResult]] + ], ): try: message, synthesis_result = item.payload + if isinstance(message, EndOfTurn): + if self.last_transcript_message is not None: + self.last_transcript_message.is_end_of_turn = True + item.agent_response_tracker.set() + return + assert synthesis_result is not None # create an empty transcript message and attach it to the transcript transcript_message = Message( text="", sender=Sender.BOT, + is_backchannel=isinstance(message, BotBackchannel), ) - self.conversation.transcript.add_message( - message=transcript_message, - conversation_id=self.conversation.id, - publish_to_events_manager=False, - ) + if not isinstance(message, SilenceMessage): + self.conversation.transcript.add_message( + message=transcript_message, + conversation_id=self.conversation.id, + publish_to_events_manager=False, + ) + if isinstance(message, SilenceMessage): + logger.debug(f"Sending {message.trailing_silence_seconds} seconds of silence") + elif isinstance(message, BotBackchannel): + logger.debug(f"Sending backchannel: {message}") message_sent, cut_off = await self.conversation.send_speech_to_output( message.text, synthesis_result, @@ -343,25 +575,10 @@ async def process( conversation_id=self.conversation.id, ) item.agent_response_tracker.set() - self.conversation.logger.debug("Message sent: {}".format(message_sent)) + logger.debug("Message sent: {}".format(message_sent)) if cut_off: - self.conversation.agent.update_last_bot_message_on_cut_off( - message_sent - ) - if self.conversation.agent.agent_config.end_conversation_on_goodbye: - goodbye_detected_task = ( - self.conversation.agent.create_goodbye_detection_task( - message_sent - ) - ) - try: - if await asyncio.wait_for(goodbye_detected_task, 0.1): - self.conversation.logger.debug( - "Agent said goodbye, ending call" - ) - await self.conversation.terminate() - except asyncio.TimeoutError: - pass + self.conversation.agent.update_last_bot_message_on_cut_off(message_sent) + self.last_transcript_message = transcript_message except asyncio.CancelledError: pass @@ -371,16 +588,12 @@ def __init__( transcriber: BaseTranscriber[TranscriberConfig], agent: BaseAgent, synthesizer: BaseSynthesizer, + speed_coefficient: float = 1.0, conversation_id: Optional[str] = None, per_chunk_allowance_seconds: float = PER_CHUNK_ALLOWANCE_SECONDS, events_manager: Optional[EventsManager] = None, - logger: Optional[logging.Logger] = None, ): self.id = conversation_id or create_conversation_id() - self.logger = wrap_logger( - logger or logging.getLogger(__name__), - conversation_id=self.id, - ) self.output_device = output_device self.transcriber = transcriber self.agent = agent @@ -388,16 +601,16 @@ def __init__( self.synthesis_enabled = True self.interruptible_events: queue.Queue[InterruptibleEvent] = queue.Queue() - self.interruptible_event_factory = self.QueueingInterruptibleEventFactory( - conversation=self - ) + self.interruptible_event_factory = self.QueueingInterruptibleEventFactory(conversation=self) self.agent.set_interruptible_event_factory(self.interruptible_event_factory) self.synthesis_results_queue: asyncio.Queue[ - InterruptibleAgentResponseEvent[Tuple[BaseMessage, SynthesisResult]] - ] = asyncio.Queue() - self.filler_audio_queue: asyncio.Queue[ - InterruptibleAgentResponseEvent[FillerAudio] + InterruptibleAgentResponseEvent[ + Tuple[Union[BaseMessage, EndOfTurn], Optional[SynthesisResult]] + ] ] = asyncio.Queue() + self.filler_audio_queue: asyncio.Queue[InterruptibleAgentResponseEvent[FillerAudio]] = ( + asyncio.Queue() + ) self.state_manager = self.create_state_manager() self.transcriptions_worker = self.TranscriptionsWorker( input_queue=self.transcriber.output_queue, @@ -422,40 +635,41 @@ def __init__( ) self.actions_worker.attach_conversation_state_manager(self.state_manager) self.synthesis_results_worker = self.SynthesisResultsWorker( - input_queue=self.synthesis_results_queue, conversation=self + input_queue=self.synthesis_results_queue, + conversation=self, ) self.filler_audio_worker = None self.filler_audio_config: Optional[FillerAudioConfig] = None if self.agent.get_agent_config().send_filler_audio: self.filler_audio_worker = self.FillerAudioWorker( - input_queue=self.filler_audio_queue, conversation=self + input_queue=self.filler_audio_queue, + conversation=self, ) + self.speed_coefficient = speed_coefficient + self.speed_manager = SpeedManager( + speed_coefficient=self.speed_coefficient, + ) + self.transcriber.attach_speed_manager(self.speed_manager) + self.agent.attach_speed_manager(self.speed_manager) + self.events_manager = events_manager or EventsManager() self.events_task: Optional[asyncio.Task] = None self.per_chunk_allowance_seconds = per_chunk_allowance_seconds self.transcript = Transcript() self.transcript.attach_events_manager(self.events_manager) - self.bot_sentiment = None - if self.agent.get_agent_config().track_bot_sentiment: - self.sentiment_config = ( - self.synthesizer.get_synthesizer_config().sentiment_config - ) - if not self.sentiment_config: - self.sentiment_config = SentimentConfig() - self.bot_sentiment_analyser = BotSentimentAnalyser( - emotions=self.sentiment_config.emotions - ) self.is_human_speaking = False self.active = False self.mark_last_action_timestamp() self.check_for_idle_task: Optional[asyncio.Task] = None - self.track_bot_sentiment_task: Optional[asyncio.Task] = None + self.check_for_idle_paused = False self.current_transcription_is_interrupt: bool = False + self.initial_message_tracker = asyncio.Event() + # tracing self.start_time: Optional[float] = None self.end_time: Optional[float] = None @@ -477,77 +691,99 @@ async def start(self, mark_ready: Optional[Callable[[], Awaitable[None]]] = None if not is_ready: raise Exception("Transcriber startup failed") if self.agent.get_agent_config().send_filler_audio: - if not isinstance( - self.agent.get_agent_config().send_filler_audio, FillerAudioConfig - ): + if not isinstance(self.agent.get_agent_config().send_filler_audio, FillerAudioConfig): self.filler_audio_config = FillerAudioConfig() else: self.filler_audio_config = typing.cast( - FillerAudioConfig, self.agent.get_agent_config().send_filler_audio + FillerAudioConfig, + self.agent.get_agent_config().send_filler_audio, ) await self.synthesizer.set_filler_audios(self.filler_audio_config) self.agent.start() initial_message = self.agent.get_agent_config().initial_message if initial_message: - asyncio.create_task(self.send_initial_message(initial_message)) + asyncio_create_task_with_done_error_log( + self.send_initial_message(initial_message), + ) + else: + self.initial_message_tracker.set() self.agent.attach_transcript(self.transcript) if mark_ready: await mark_ready() - if self.synthesizer.get_synthesizer_config().sentiment_config: - await self.update_bot_sentiment() self.active = True - if self.synthesizer.get_synthesizer_config().sentiment_config: - self.track_bot_sentiment_task = asyncio.create_task( - self.track_bot_sentiment() - ) - self.check_for_idle_task = asyncio.create_task(self.check_for_idle()) + self.check_for_idle_task = asyncio_create_task_with_done_error_log( + self.check_for_idle(), + ) if len(self.events_manager.subscriptions) > 0: - self.events_task = asyncio.create_task(self.events_manager.start()) + self.events_task = asyncio_create_task_with_done_error_log( + self.events_manager.start(), + ) - async def send_initial_message(self, initial_message: BaseMessage): + def set_check_for_idle_paused(self, paused: bool): + logger.debug(f"Setting idle check paused to {paused}") + if not paused: + self.mark_last_action_timestamp() + self.check_for_idle_paused = paused + + async def send_initial_message( + self, + initial_message: BaseMessage, + ): # TODO: configure if initial message is interruptible - self.transcriber.mute() - initial_message_tracker = asyncio.Event() + delay = self.agent.get_agent_config().initial_message_delay + if delay > 0: + logger.info(f"Waiting {delay} seconds before initial message") + await asyncio.sleep(delay) + await self.send_single_message( + message=initial_message, + message_tracker=self.initial_message_tracker, + ) + await self.initial_message_tracker.wait() + + async def check_for_idle(self): + """Asks if human is still on the line if no activity is detected, and terminates the conversation if not.""" + await self.initial_message_tracker.wait() + check_human_present_count = 0 + check_human_present_threshold = self.agent.get_agent_config().num_check_human_present_times + idle_time_threshold = ( + self.agent.get_agent_config().allowed_idle_time_seconds or ALLOWED_IDLE_TIME + ) + while self.is_active(): + if ( + not self.check_for_idle_paused + ) and time.time() - self.last_action_timestamp > idle_time_threshold: + if check_human_present_count >= check_human_present_threshold: + # Stop the phone call after some retries to prevent infinitely long call where human is just silent. + logger.debug("Conversation idle for too long, terminating") + self.mark_terminated(bot_disconnect=True) + return + await self.send_single_message( + message=BaseMessage(text=random.choice(CHECK_HUMAN_PRESENT_MESSAGE_CHOICES)), + ) + check_human_present_count += 1 + # wait till the idle time would have passed the threshold if no action occurs + await asyncio.sleep(ALLOWED_IDLE_TIME) + + async def send_single_message( + self, + message: BaseMessage, + message_tracker: Optional[asyncio.Event] = None, + ): agent_response_event = ( self.interruptible_event_factory.create_interruptible_agent_response_event( - AgentResponseMessage(message=initial_message), + AgentResponseMessage(message=message, is_sole_text_chunk=True), is_interruptible=False, - agent_response_tracker=initial_message_tracker, + agent_response_tracker=message_tracker, ) ) self.agent_responses_worker.consume_nonblocking(agent_response_event) - await initial_message_tracker.wait() - self.transcriber.unmute() - - async def check_for_idle(self): - """Terminates the conversation after 15 seconds if no activity is detected""" - while self.is_active(): - if time.time() - self.last_action_timestamp > ( - self.agent.get_agent_config().allowed_idle_time_seconds - or ALLOWED_IDLE_TIME - ): - self.logger.debug("Conversation idle for too long, terminating") - await self.terminate() - return - await asyncio.sleep(15) - - async def track_bot_sentiment(self): - """Updates self.bot_sentiment every second based on the current transcript""" - prev_transcript = None - while self.is_active(): - await asyncio.sleep(1) - if self.transcript.to_string() != prev_transcript: - await self.update_bot_sentiment() - prev_transcript = self.transcript.to_string() - - async def update_bot_sentiment(self): - new_bot_sentiment = await self.bot_sentiment_analyser.analyse( - self.transcript.to_string() + self.agent_responses_worker.consume_nonblocking( + self.interruptible_event_factory.create_interruptible_agent_response_event( + AgentResponseMessage(message=EndOfTurn()), + is_interruptible=True, + ), ) - if new_bot_sentiment.emotion: - self.logger.debug("Bot sentiment: %s", new_bot_sentiment) - self.bot_sentiment = new_bot_sentiment def receive_message(self, message: str): transcription = Transcription( @@ -561,7 +797,7 @@ def receive_audio(self, chunk: bytes): self.transcriber.send_audio(chunk) def warmup_synthesizer(self): - self.synthesizer.ready_synthesizer() + self.synthesizer.ready_synthesizer(self._get_synthesizer_chunk_size()) def mark_last_action_timestamp(self): self.last_action_timestamp = time.time() @@ -577,12 +813,16 @@ def broadcast_interrupt(self): interruptible_event = self.interruptible_events.get_nowait() if not interruptible_event.is_interrupted(): if interruptible_event.interrupt(): - self.logger.debug("Interrupting event") + logger.debug( + f"Interrupting event {type(interruptible_event.payload)} {interruptible_event.payload}", + ) num_interrupts += 1 except queue.Empty: break self.agent.cancel_current_task() self.agent_responses_worker.cancel_current_task() + if self.actions_worker: + self.actions_worker.cancel_current_task() return num_interrupts > 0 def is_interrupt(self, transcription: Transcription): @@ -590,12 +830,43 @@ def is_interrupt(self, transcription: Transcription): self.transcriber.get_transcriber_config().min_interrupt_confidence or 0 ) + def _maybe_create_first_chunk_span(self, synthesis_result: SynthesisResult, message: str): + first_chunk_span: Optional[Span] = None + if synthesis_result.synthesis_total_span: + synthesis_result.synthesis_total_span.set_tag("message_length", len(message)) + if synthesis_result.ttft_span: + synthesis_result.ttft_span.set_tag("message_length", len(message)) + first_chunk_span = sentry_create_span( + sentry_callable=synthesis_result.ttft_span.start_child, + op=CustomSentrySpans.SYNTHESIS_GENERATE_FIRST_CHUNK, + ) + return first_chunk_span + + def _track_first_chunk(self, first_chunk_span: Span, synthesis_result: SynthesisResult): + complete_span_by_op(CustomSentrySpans.SYNTHESIS_TIME_TO_FIRST_TOKEN) + first_chunk_span.finish() + if synthesis_result.ttft_span: + synthesis_result.ttft_span.finish() + complete_span_by_op(CustomSentrySpans.LATENCY_OF_CONVERSATION) + + def _get_synthesizer_chunk_size( + self, + seconds_per_chunk: float = TEXT_TO_SPEECH_CHUNK_SIZE_SECONDS, + ): + return int( + seconds_per_chunk + * get_chunk_size_per_second( + self.synthesizer.get_synthesizer_config().audio_encoding, + self.synthesizer.get_synthesizer_config().sampling_rate, + ), + ) + async def send_speech_to_output( self, message: str, synthesis_result: SynthesisResult, stop_event: threading.Event, - seconds_per_chunk: int, + seconds_per_chunk: float, transcript_message: Optional[Message] = None, started_event: Optional[threading.Event] = None, ): @@ -611,30 +882,50 @@ async def send_speech_to_output( Returns the message that was sent up to, and a flag if the message was cut off """ + + async def get_chunks( + output_queue: asyncio.Queue[Optional[SynthesisResult.ChunkResult]], + chunk_generator: AsyncGenerator[SynthesisResult.ChunkResult, None], + ): + try: + async for chunk_result in chunk_generator: + await output_queue.put(chunk_result) + except asyncio.CancelledError: + pass + finally: + await output_queue.put(None) # sentinel + if self.transcriber.get_transcriber_config().mute_during_speech: - self.logger.debug("Muting transcriber") + logger.debug("Muting transcriber") self.transcriber.mute() message_sent = message cut_off = False - chunk_size = seconds_per_chunk * get_chunk_size_per_second( - self.synthesizer.get_synthesizer_config().audio_encoding, - self.synthesizer.get_synthesizer_config().sampling_rate, - ) + chunk_size = self._get_synthesizer_chunk_size(seconds_per_chunk) chunk_idx = 0 - seconds_spoken = 0 - async for chunk_result in synthesis_result.chunk_generator: + seconds_spoken = 0.0 + logger.debug(f"Start sending speech {message} to output") + + first_chunk_span = self._maybe_create_first_chunk_span(synthesis_result, message) + chunk_queue: asyncio.Queue[Optional[SynthesisResult.ChunkResult]] = asyncio.Queue() + get_chunks_task = asyncio_create_task_with_done_error_log( + get_chunks(chunk_queue, synthesis_result.chunk_generator), + ) + first = True + while True: + chunk_result = await chunk_queue.get() + if chunk_result is None: + break + if first and first_chunk_span: + self._track_first_chunk(first_chunk_span, synthesis_result) + first = False start_time = time.time() - speech_length_seconds = seconds_per_chunk * ( - len(chunk_result.chunk) / chunk_size - ) + speech_length_seconds = seconds_per_chunk * (len(chunk_result.chunk) / chunk_size) seconds_spoken = chunk_idx * seconds_per_chunk if stop_event.is_set(): - self.logger.debug( - "Interrupted, stopping text to speech after {} chunks".format( - chunk_idx - ) + logger.debug( + "Interrupted, stopping text to speech after {} chunks".format(chunk_idx), ) - message_sent = f"{synthesis_result.get_message_up_to(seconds_spoken)}-" + message_sent = synthesis_result.get_message_up_to(seconds_spoken) cut_off = True break if chunk_idx == 0: @@ -648,73 +939,70 @@ async def send_speech_to_output( - (end_time - start_time) - self.per_chunk_allowance_seconds, 0, - ) - ) - self.logger.debug( - "Sent chunk {} with size {}".format(chunk_idx, len(chunk_result.chunk)) + ), ) self.mark_last_action_timestamp() chunk_idx += 1 seconds_spoken += seconds_per_chunk if transcript_message: - transcript_message.text = synthesis_result.get_message_up_to( - seconds_spoken - ) + transcript_message.text = synthesis_result.get_message_up_to(seconds_spoken) + get_chunks_task.cancel() if self.transcriber.get_transcriber_config().mute_during_speech: - self.logger.debug("Unmuting transcriber") + logger.debug("Unmuting transcriber") self.transcriber.unmute() if transcript_message: transcript_message.text = message_sent + transcript_message.is_final = not cut_off + if synthesis_result.synthesis_total_span: + synthesis_result.synthesis_total_span.finish() return message_sent, cut_off - def mark_terminated(self): + def mark_terminated(self, bot_disconnect: bool = False): self.active = False async def terminate(self): self.mark_terminated() self.broadcast_interrupt() self.events_manager.publish_event( - TranscriptCompleteEvent(conversation_id=self.id, transcript=self.transcript) + TranscriptCompleteEvent( + conversation_id=self.id, + transcript=self.transcript, + ), ) if self.check_for_idle_task: - self.logger.debug("Terminating check_for_idle Task") + logger.debug("Terminating check_for_idle Task") self.check_for_idle_task.cancel() - if self.track_bot_sentiment_task: - self.logger.debug("Terminating track_bot_sentiment Task") - self.track_bot_sentiment_task.cancel() if self.events_manager and self.events_task: - self.logger.debug("Terminating events Task") + logger.debug("Terminating events Task") + self.events_task.cancel() await self.events_manager.flush() - self.logger.debug("Tearing down synthesizer") + logger.debug("Tearing down synthesizer") await self.synthesizer.tear_down() - self.logger.debug("Terminating agent") - if ( - isinstance(self.agent, ChatGPTAgent) - and self.agent.agent_config.vector_db_config - ): + logger.debug("Terminating agent") + if isinstance(self.agent, ChatGPTAgent) and self.agent.agent_config.vector_db_config: # Shutting down the vector db should be done in the agent's terminate method, # but it is done here because `vector_db.tear_down()` is async and # `agent.terminate()` is not async. - self.logger.debug("Terminating vector db") + logger.debug("Terminating vector db") await self.agent.vector_db.tear_down() self.agent.terminate() - self.logger.debug("Terminating output device") + logger.debug("Terminating output device") self.output_device.terminate() - self.logger.debug("Terminating speech transcriber") + logger.debug("Terminating speech transcriber") self.transcriber.terminate() - self.logger.debug("Terminating transcriptions worker") + logger.debug("Terminating transcriptions worker") self.transcriptions_worker.terminate() - self.logger.debug("Terminating final transcriptions worker") + logger.debug("Terminating final transcriptions worker") self.agent_responses_worker.terminate() - self.logger.debug("Terminating synthesis results worker") + logger.debug("Terminating synthesis results worker") self.synthesis_results_worker.terminate() if self.filler_audio_worker is not None: - self.logger.debug("Terminating filler audio worker") + logger.debug("Terminating filler audio worker") self.filler_audio_worker.terminate() if self.actions_worker is not None: - self.logger.debug("Terminating actions worker") + logger.debug("Terminating actions worker") self.actions_worker.terminate() - self.logger.debug("Successfully terminated") + logger.debug("Successfully terminated") def is_active(self): return self.active diff --git a/vocode/streaming/synthesizer/__init__.py b/vocode/streaming/synthesizer/__init__.py index 167c78574..e69de29bb 100644 --- a/vocode/streaming/synthesizer/__init__.py +++ b/vocode/streaming/synthesizer/__init__.py @@ -1,14 +0,0 @@ -from vocode.streaming.synthesizer.azure_synthesizer import AzureSynthesizer -from vocode.streaming.synthesizer.bark_synthesizer import BarkSynthesizer -from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer -from vocode.streaming.synthesizer.coqui_synthesizer import CoquiSynthesizer -from vocode.streaming.synthesizer.coqui_tts_synthesizer import CoquiTTSSynthesizer -from vocode.streaming.synthesizer.eleven_labs_synthesizer import ElevenLabsSynthesizer -from vocode.streaming.synthesizer.google_synthesizer import GoogleSynthesizer -from vocode.streaming.synthesizer.gtts_synthesizer import GTTSSynthesizer -from vocode.streaming.synthesizer.play_ht_synthesizer import PlayHtSynthesizer -from vocode.streaming.synthesizer.rime_synthesizer import RimeSynthesizer -from vocode.streaming.synthesizer.polly_synthesizer import PollySynthesizer -from vocode.streaming.synthesizer.stream_elements_synthesizer import ( - StreamElementsSynthesizer, -) diff --git a/vocode/streaming/synthesizer/abstract_factory.py b/vocode/streaming/synthesizer/abstract_factory.py new file mode 100644 index 000000000..864dabcef --- /dev/null +++ b/vocode/streaming/synthesizer/abstract_factory.py @@ -0,0 +1,15 @@ +from abc import ABC, abstractmethod + +from vocode.streaming.models.synthesizer import SynthesizerConfig +from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer +from vocode.streaming.utils.async_requester import AsyncRequestor + + +class AbstractSynthesizerFactory(ABC): + # TODO(DOW-48): Make this not require async_requestor + @abstractmethod + def create_synthesizer( + self, + synthesizer_config: SynthesizerConfig, + ) -> BaseSynthesizer: + pass diff --git a/vocode/streaming/synthesizer/audio_cache.py b/vocode/streaming/synthesizer/audio_cache.py new file mode 100644 index 000000000..6d767b5bb --- /dev/null +++ b/vocode/streaming/synthesizer/audio_cache.py @@ -0,0 +1,47 @@ +from typing import Optional + +from loguru import logger + +from vocode.streaming.utils.redis import initialize_redis_bytes +from vocode.streaming.utils.singleton import Singleton + + +class AudioCache(Singleton): + def __init__(self): + self.redis = initialize_redis_bytes() + self.disabled = False + + @staticmethod + async def safe_create(): + if AudioCache in Singleton._instances: + return Singleton._instances[AudioCache] + + audio_cache = AudioCache() + try: + await audio_cache.redis.ping() + except Exception: + logger.warning("Redis ping failed on startup, disabling audio cache") + audio_cache.disabled = True + return audio_cache + + def get_audio_key(self, voice_identifier: str, text: str) -> str: + return f"audio_cache:{voice_identifier}:{text}" + + async def get_audio(self, voice_identifier: str, text: str) -> Optional[bytes]: + audio_key = self.get_audio_key(voice_identifier, text) + if self.disabled: + return None + return await self.redis.get(audio_key) + + async def set_audio( + self, voice_identifier: str, text: str, audio: bytes, ttl: Optional[int] = None + ): + # TODO: cache eviction + if self.disabled: + logger.warning("Audio cache is disabled") + return + logger.info(f"Setting audio for {voice_identifier} {text}") + audio_key = self.get_audio_key(voice_identifier, text) + await self.redis.set(audio_key, audio) + if ttl is not None: + await self.redis.expire(audio_key, ttl) diff --git a/vocode/streaming/synthesizer/azure_synthesizer.py b/vocode/streaming/synthesizer/azure_synthesizer.py index ceb7dd6d5..7c9b60033 100644 --- a/vocode/streaming/synthesizer/azure_synthesizer.py +++ b/vocode/streaming/synthesizer/azure_synthesizer.py @@ -1,31 +1,25 @@ import asyncio -from concurrent.futures import ThreadPoolExecutor -import logging import os import re -from typing import Any, List, Optional, Tuple +from concurrent.futures import ThreadPoolExecutor +from typing import List, Optional from xml.etree import ElementTree -import aiohttp -from vocode import getenv -from opentelemetry.context.context import Context -from vocode.streaming.agent.bot_sentiment_analyser import BotSentiment -from vocode.streaming.models.message import BaseMessage, SSMLMessage +import azure.cognitiveservices.speech as speechsdk +from loguru import logger +from vocode import getenv +from vocode.streaming.models.audio import AudioEncoding, SamplingRate +from vocode.streaming.models.message import BaseMessage, SSMLMessage +from vocode.streaming.models.synthesizer import AzureSynthesizerConfig from vocode.streaming.synthesizer.base_synthesizer import ( - BaseSynthesizer, - SynthesisResult, - FILLER_PHRASES, FILLER_AUDIO_PATH, + FILLER_PHRASES, + BaseSynthesizer, FillerAudio, + SynthesisResult, encode_as_wav, - tracer, ) -from vocode.streaming.models.synthesizer import AzureSynthesizerConfig, SynthesizerType -from vocode.streaming.models.audio_encoding import AudioEncoding - -import azure.cognitiveservices.speech as speechsdk - NAMESPACES = { "mstts": "https://www.w3.org/2001/mstts", @@ -35,6 +29,8 @@ ElementTree.register_namespace("", NAMESPACES[""]) ElementTree.register_namespace("mstts", NAMESPACES["mstts"]) +_AZURE_INSIDE_VOICE_REGEX = r"]*>(.*?)<\/voice>" + class WordBoundaryEventPool: def __init__(self): @@ -60,12 +56,10 @@ class AzureSynthesizer(BaseSynthesizer[AzureSynthesizerConfig]): def __init__( self, synthesizer_config: AzureSynthesizerConfig, - logger: Optional[logging.Logger] = None, azure_speech_key: Optional[str] = None, azure_speech_region: Optional[str] = None, - aiohttp_session: Optional[aiohttp.ClientSession] = None, ): - super().__init__(synthesizer_config, aiohttp_session) + super().__init__(synthesizer_config) # Instantiates a client azure_speech_key = azure_speech_key or getenv("AZURE_SPEECH_KEY") azure_speech_region = azure_speech_region or getenv("AZURE_SPEECH_REGION") @@ -81,23 +75,23 @@ def __init__( subscription=azure_speech_key, region=azure_speech_region ) if self.synthesizer_config.audio_encoding == AudioEncoding.LINEAR16: - if self.synthesizer_config.sampling_rate == 44100: + if self.synthesizer_config.sampling_rate == SamplingRate.RATE_44100: speech_config.set_speech_synthesis_output_format( speechsdk.SpeechSynthesisOutputFormat.Raw44100Hz16BitMonoPcm ) - if self.synthesizer_config.sampling_rate == 48000: + if self.synthesizer_config.sampling_rate == SamplingRate.RATE_48000: speech_config.set_speech_synthesis_output_format( speechsdk.SpeechSynthesisOutputFormat.Raw48Khz16BitMonoPcm ) - if self.synthesizer_config.sampling_rate == 24000: + if self.synthesizer_config.sampling_rate == SamplingRate.RATE_24000: speech_config.set_speech_synthesis_output_format( speechsdk.SpeechSynthesisOutputFormat.Raw24Khz16BitMonoPcm ) - elif self.synthesizer_config.sampling_rate == 16000: + elif self.synthesizer_config.sampling_rate == SamplingRate.RATE_16000: speech_config.set_speech_synthesis_output_format( speechsdk.SpeechSynthesisOutputFormat.Raw16Khz16BitMonoPcm ) - elif self.synthesizer_config.sampling_rate == 8000: + elif self.synthesizer_config.sampling_rate == SamplingRate.RATE_8000: speech_config.set_speech_synthesis_output_format( speechsdk.SpeechSynthesisOutputFormat.Raw8Khz16BitMonoPcm ) @@ -113,7 +107,19 @@ def __init__( self.pitch = self.synthesizer_config.pitch self.rate = self.synthesizer_config.rate self.thread_pool_executor = ThreadPoolExecutor(max_workers=1) - self.logger = logger or logging.getLogger(__name__) + + @classmethod + def get_voice_identifier(cls, synthesizer_config: AzureSynthesizerConfig) -> str: + return ":".join( + ( + "azure", + synthesizer_config.voice_name, + str(synthesizer_config.pitch), + str(synthesizer_config.rate), + synthesizer_config.language_code, + synthesizer_config.audio_encoding, + ) + ) async def get_phrase_filler_audios(self) -> List[FillerAudio]: filler_phrase_audios = [] @@ -133,7 +139,7 @@ async def get_phrase_filler_audios(self) -> List[FillerAudio]: if os.path.exists(filler_audio_path): audio_data = open(filler_audio_path, "rb").read() else: - self.logger.debug(f"Generating filler audio for {filler_phrase.text}") + logger.debug(f"Generating filler audio for {filler_phrase.text}") ssml = self.create_ssml(filler_phrase.text) result = await asyncio.get_event_loop().run_in_executor( self.thread_pool_executor, self.synthesizer.speak_ssml, ssml @@ -166,9 +172,7 @@ def add_marks(self, message: str, index=0) -> str: def word_boundary_cb(self, evt, pool): pool.add(evt) - def create_ssml( - self, message: str, bot_sentiment: Optional[BotSentiment] = None - ) -> str: + def create_ssml(self, message: str) -> str: voice_language_code = self.synthesizer_config.voice_name[:5] ssml_root = ElementTree.fromstring( f'' @@ -181,38 +185,33 @@ def create_ssml( voice_root = lang else: voice_root = voice - if bot_sentiment and bot_sentiment.emotion: - styled = ElementTree.SubElement( - voice, "{%s}express-as" % NAMESPACES.get("mstts") - ) - styled.set("style", bot_sentiment.emotion) - styled.set( - "styledegree", str(bot_sentiment.degree * 2) - ) # Azure specific, it's a scale of 0-2 - voice_root = styled # this ugly hack is necessary so we can limit the gap between sentences # for normal sentences, it seems like the gap is > 500ms, so we're able to reduce it to 500ms # for very tiny sentences, the API hangs - so we heuristically only update the silence gap # if there is more than one word in the sentence if " " in message: - silence = ElementTree.SubElement( - voice_root, "{%s}silence" % NAMESPACES.get("mstts") - ) + silence = ElementTree.SubElement(voice_root, "{%s}silence" % NAMESPACES.get("mstts")) silence.set("value", "500ms") silence.set("type", "Tailing-exact") prosody = ElementTree.SubElement(voice_root, "prosody") prosody.set("pitch", f"{self.pitch}%") prosody.set("rate", f"{self.rate}%") prosody.text = message.strip() - return ElementTree.tostring(ssml_root, encoding="unicode") + ssml = ElementTree.tostring(ssml_root, encoding="unicode") + regmatch = re.search(_AZURE_INSIDE_VOICE_REGEX, ssml, re.DOTALL) + if regmatch: + self.total_chars += len(regmatch.group(1)) + return ssml def synthesize_ssml(self, ssml: str) -> speechsdk.AudioDataStream: result = self.synthesizer.start_speaking_ssml_async(ssml).get() return speechsdk.AudioDataStream(result) - def ready_synthesizer(self): - connection = speechsdk.Connection.from_speech_synthesizer(self.synthesizer) - connection.open(True) + def ready_synthesizer(self, chunk_size: int): + # TODO: remove warming up the synthesizer for now + # connection = speechsdk.Connection.from_speech_synthesizer(self.synthesizer) + # connection.open(True) + pass # given the number of seconds the message was allowed to go until, where did we get in the message? def get_message_up_to( @@ -234,11 +233,12 @@ async def create_speech( self, message: BaseMessage, chunk_size: int, - bot_sentiment: Optional[BotSentiment] = None, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, ) -> SynthesisResult: # offset = int(self.OFFSET_MS * (self.synthesizer_config.sampling_rate / 1000)) offset = 0 - self.logger.debug(f"Synthesizing message: {message}") + logger.debug(f"Synthesizing message: {message}") # Azure will return no audio for certain strings like "-", "[-", and "!" # which causes the `chunk_generator` below to hang. Return an empty @@ -258,15 +258,12 @@ async def chunk_generator( lambda: audio_data_stream.read_data(audio_buffer), ) if filled_size != chunk_size: - yield SynthesisResult.ChunkResult( - chunk_transform(audio_buffer[offset:]), True - ) + yield SynthesisResult.ChunkResult(chunk_transform(audio_buffer[offset:]), True) return else: - yield SynthesisResult.ChunkResult( - chunk_transform(audio_buffer[offset:]), False - ) + yield SynthesisResult.ChunkResult(chunk_transform(audio_buffer[offset:]), False) while True: + audio_buffer = bytes(chunk_size) filled_size = audio_data_stream.read_data(audio_buffer) if filled_size != chunk_size: yield SynthesisResult.ChunkResult( @@ -279,11 +276,7 @@ async def chunk_generator( self.synthesizer.synthesis_word_boundary.connect( lambda event: self.word_boundary_cb(event, word_boundary_event_pool) ) - ssml = ( - message.ssml - if isinstance(message, SSMLMessage) - else self.create_ssml(message.text, bot_sentiment=bot_sentiment) - ) + ssml = message.ssml if isinstance(message, SSMLMessage) else self.create_ssml(message.text) audio_data_stream = await asyncio.get_event_loop().run_in_executor( self.thread_pool_executor, self.synthesize_ssml, ssml ) @@ -301,3 +294,5 @@ async def chunk_generator( message.text, ssml, seconds, word_boundary_event_pool ), ) + + create_speech_uncached = create_speech diff --git a/vocode/streaming/synthesizer/bark_synthesizer.py b/vocode/streaming/synthesizer/bark_synthesizer.py index d8a79d5c6..e6f9058ba 100644 --- a/vocode/streaming/synthesizer/bark_synthesizer.py +++ b/vocode/streaming/synthesizer/bark_synthesizer.py @@ -1,36 +1,27 @@ import asyncio -from concurrent.futures import ThreadPoolExecutor import io +from concurrent.futures import ThreadPoolExecutor + import numpy as np -import logging -from typing import Optional +from bark import SAMPLE_RATE, generate_audio, preload_models +from loguru import logger from scipy.io.wavfile import write as write_wav -from vocode.streaming.synthesizer.base_synthesizer import ( - BaseSynthesizer, - SynthesisResult, - tracer, -) -from vocode.streaming.models.synthesizer import BarkSynthesizerConfig, SynthesizerType -from vocode.streaming.agent.bot_sentiment_analyser import BotSentiment -from vocode.streaming.models.message import BaseMessage -from opentelemetry.context.context import Context +from vocode.streaming.models.message import BaseMessage +from vocode.streaming.models.synthesizer import BarkSynthesizerConfig +from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer, SynthesisResult class BarkSynthesizer(BaseSynthesizer[BarkSynthesizerConfig]): def __init__( self, synthesizer_config: BarkSynthesizerConfig, - logger: Optional[logging.Logger] = None, ) -> None: super().__init__(synthesizer_config) - from bark import SAMPLE_RATE, generate_audio, preload_models - self.SAMPLE_RATE = SAMPLE_RATE self.generate_audio = generate_audio - self.logger = logger or logging.getLogger(__name__) - self.logger.info("Loading Bark models") + logger.info("Loading Bark models") preload_models(**self.synthesizer_config.preload_kwargs) self.thread_pool_executor = ThreadPoolExecutor(max_workers=1) @@ -38,22 +29,16 @@ async def create_speech( self, message: BaseMessage, chunk_size: int, - bot_sentiment: Optional[BotSentiment] = None, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, ) -> SynthesisResult: - create_speech_span = tracer.start_span( - f"synthesizer.{SynthesizerType.BARK.value.split('_', 1)[-1]}.create_total", - ) - self.logger.debug("Bark synthesizing audio") + logger.debug("Bark synthesizing audio") audio_array = await asyncio.get_event_loop().run_in_executor( self.thread_pool_executor, self.generate_audio, message.text, **self.synthesizer_config.generate_kwargs, ) - create_speech_span.end() - convert_span = tracer.start_span( - f"synthesizer.{SynthesizerType.BARK.value.split('_', 1)[-1]}.convert", - ) int_audio_arr = (audio_array * np.iinfo(np.int16).max).astype(np.int16) output_bytes_io = io.BytesIO() @@ -66,5 +51,4 @@ async def create_speech( chunk_size=chunk_size, ) - convert_span.end() return result diff --git a/vocode/streaming/synthesizer/base_synthesizer.py b/vocode/streaming/synthesizer/base_synthesizer.py index 0ca78464a..31a4928fb 100644 --- a/vocode/streaming/synthesizer/base_synthesizer.py +++ b/vocode/streaming/synthesizer/base_synthesizer.py @@ -1,33 +1,27 @@ import asyncio -import os -from typing import ( - Any, - AsyncGenerator, - Generator, - Callable, - Generic, - List, - Optional, - Tuple, - TypeVar, - Union, -) -import math +import audioop import io +import math +import os import wave +from typing import Any, AsyncGenerator, Callable, Generic, List, Optional, Tuple, TypeVar, Union + import aiohttp +from loguru import logger from nltk.tokenize import word_tokenize from nltk.tokenize.treebank import TreebankWordDetokenizer -from opentelemetry import trace -from opentelemetry.trace import Span +from sentry_sdk.tracing import Span as SentrySpan -from vocode.streaming.agent.bot_sentiment_analyser import BotSentiment from vocode.streaming.models.agent import FillerAudioConfig -from vocode.streaming.models.message import BaseMessage +from vocode.streaming.models.audio import AudioEncoding, SamplingRate +from vocode.streaming.models.message import BaseMessage, BotBackchannel, SilenceMessage +from vocode.streaming.models.synthesizer import SynthesizerConfig +from vocode.streaming.synthesizer.audio_cache import AudioCache from vocode.streaming.synthesizer.miniaudio_worker import MiniaudioWorker +from vocode.streaming.telephony.constants import MULAW_SILENCE_BYTE, PCM_SILENCE_BYTE from vocode.streaming.utils import convert_wav, get_chunk_size_per_second -from vocode.streaming.models.audio_encoding import AudioEncoding -from vocode.streaming.models.synthesizer import SynthesizerConfig +from vocode.streaming.utils.async_requester import AsyncRequestor +from vocode.streaming.utils.create_task import asyncio_create_task_with_done_error_log FILLER_PHRASES = [ BaseMessage(text="Um..."), @@ -55,9 +49,6 @@ def encode_as_wav(chunk: bytes, synthesizer_config: SynthesizerConfig) -> bytes: return output_bytes_io.read() -tracer = trace.get_tracer(__name__) - - class SynthesisResult: class ChunkResult: def __init__(self, chunk: bytes, is_last_chunk: bool): @@ -68,9 +59,17 @@ def __init__( self, chunk_generator: AsyncGenerator[ChunkResult, None], get_message_up_to: Callable[[float], str], + cached: bool = False, + is_first: bool = False, + synthesis_total_span: Optional[SentrySpan] = None, + ttft_span: Optional[SentrySpan] = None, ): self.chunk_generator = chunk_generator self.get_message_up_to = get_message_up_to + self.cached = cached + self.is_first = is_first + self.synthesis_total_span = synthesis_total_span + self.ttft_span = ttft_span class FillerAudio: @@ -100,9 +99,7 @@ def create_synthesis_result(self) -> SynthesisResult: async def chunk_generator(chunk_transform=lambda x: x): for i in range(0, len(self.audio_data), chunk_size): if i + chunk_size > len(self.audio_data): - yield SynthesisResult.ChunkResult( - chunk_transform(self.audio_data[i:]), True - ) + yield SynthesisResult.ChunkResult(chunk_transform(self.audio_data[i:]), True) else: yield SynthesisResult.ChunkResult( chunk_transform(self.audio_data[i : i + chunk_size]), False @@ -117,6 +114,104 @@ async def chunk_generator(chunk_transform=lambda x: x): return SynthesisResult(output_generator, lambda seconds: self.message.text) +class CachedAudio: + def __init__( + self, + message: BaseMessage, + audio_data: bytes, + synthesizer_config: SynthesizerConfig, + trailing_silence_seconds: float = 0.0, + ): + self.message = message + self.audio_data = audio_data + self.synthesizer_config = synthesizer_config + self.trailing_silence_seconds = trailing_silence_seconds + + def create_synthesis_result(self, chunk_size) -> SynthesisResult: + async def chunk_generator(): + if isinstance(self.message, BotBackchannel): + yield SynthesisResult.ChunkResult( + self.audio_data, self.trailing_silence_seconds == 0.0 + ) + else: + for i in range(0, len(self.audio_data), chunk_size): + if i + chunk_size > len(self.audio_data): + yield SynthesisResult.ChunkResult( + self.audio_data[i:], self.trailing_silence_seconds == 0.0 + ) + else: + yield SynthesisResult.ChunkResult( + self.audio_data[i : i + chunk_size], False + ) + if self.trailing_silence_seconds > 0: + silence_synthesis_result = self.create_silence_synthesis_result(chunk_size) + async for chunk_result in silence_synthesis_result.chunk_generator: + yield chunk_result + + if isinstance(self.message, BotBackchannel): + + def get_message_up_to(seconds): + return self.message.text + + else: + + def get_message_up_to(seconds): + return BaseSynthesizer.get_message_cutoff_from_total_response_length( + self.synthesizer_config, self.message, seconds, len(self.audio_data) + ) + + return SynthesisResult( + chunk_generator=chunk_generator(), + get_message_up_to=get_message_up_to, + cached=True, + ) + + def create_silence_synthesis_result(self, chunk_size) -> SynthesisResult: + async def chunk_generator(): + size_of_silence = int( + self.trailing_silence_seconds * self.synthesizer_config.sampling_rate + ) + silence_byte: bytes + if self.synthesizer_config.audio_encoding == AudioEncoding.LINEAR16: + silence_byte = PCM_SILENCE_BYTE + size_of_silence *= 2 + elif self.synthesizer_config.audio_encoding == AudioEncoding.MULAW: + silence_byte = MULAW_SILENCE_BYTE + + for _ in range( + 0, + size_of_silence, + chunk_size, + ): + yield SynthesisResult.ChunkResult(silence_byte * chunk_size, False) + yield SynthesisResult.ChunkResult(silence_byte * chunk_size, True) + + def get_message_up_to(seconds): + return "" + + return SynthesisResult( + chunk_generator(), + get_message_up_to, + ) + + +class SilenceAudio(CachedAudio): + def __init__( + self, + message: SilenceMessage, + synthesizer_config: SynthesizerConfig, + ): + super().__init__( + message, + b"", + synthesizer_config, + trailing_silence_seconds=message.trailing_silence_seconds, + ) + + def create_synthesis_result(self, chunk_size) -> SynthesisResult: + return self.create_silence_synthesis_result(chunk_size) + + SynthesizerConfigType = TypeVar("SynthesizerConfigType", bound=SynthesizerConfig) @@ -124,21 +219,20 @@ class BaseSynthesizer(Generic[SynthesizerConfigType]): def __init__( self, synthesizer_config: SynthesizerConfigType, - aiohttp_session: Optional[aiohttp.ClientSession] = None, ): self.synthesizer_config = synthesizer_config if synthesizer_config.audio_encoding == AudioEncoding.MULAW: assert ( - synthesizer_config.sampling_rate == 8000 + synthesizer_config.sampling_rate == SamplingRate.RATE_8000 ), "MuLaw encoding only supports 8kHz sampling rate" self.filler_audios: List[FillerAudio] = [] - if aiohttp_session: - # the caller is responsible for closing the session - self.aiohttp_session = aiohttp_session - self.should_close_session_on_tear_down = False - else: - self.aiohttp_session = aiohttp.ClientSession() - self.should_close_session_on_tear_down = True + self.async_requestor = AsyncRequestor() + self.total_chars: int = 0 + self.cost_per_char: Optional[float] = None + + @classmethod + def get_voice_identifier(cls, synthesizer_config: SynthesizerConfigType) -> str: + raise NotImplementedError async def empty_generator(self): yield SynthesisResult.ChunkResult(b"", True) @@ -159,6 +253,9 @@ def get_typing_noise_filler_audio(self) -> FillerAudio: seconds_per_chunk=2, ) + def get_cost(self) -> float: + raise NotImplementedError + async def set_filler_audios(self, filler_audio_config: FillerAudioConfig): if filler_audio_config.use_phrases: self.filler_audios = await self.get_phrase_filler_audios() @@ -168,7 +265,7 @@ async def set_filler_audios(self, filler_audio_config: FillerAudioConfig): async def get_phrase_filler_audios(self) -> List[FillerAudio]: return [] - def ready_synthesizer(self): + def ready_synthesizer(self, chunk_size: int): pass # given the number of seconds the message was allowed to go until, where did we get in the message? @@ -195,16 +292,69 @@ def get_message_cutoff_from_voice_speed( tokens = word_tokenize(message.text) return TreebankWordDetokenizer().detokenize(tokens[:estimated_words_spoken]) - # returns a chunk generator and a thunk that can tell you what part of the message was read given the number of seconds spoken - # chunk generator must return a ChunkResult, essentially a tuple (bytes of size chunk_size, flag if it is the last chunk) - async def create_speech( + async def get_cached_audio( + self, + message: BaseMessage, + ) -> Optional[CachedAudio]: + audio_cache = await AudioCache.safe_create() + cache_phrase = message.cache_phrase or message.text.strip() + audio_data = await audio_cache.get_audio( + self.get_voice_identifier(self.synthesizer_config), cache_phrase + ) + if audio_data is None: + return None + logger.info(f"Got cached audio for {cache_phrase}") + + trailing_silence_seconds = 0.0 + if isinstance(message, BotBackchannel): + trailing_silence_seconds = message.trailing_silence_seconds + return CachedAudio(message, audio_data, self.synthesizer_config, trailing_silence_seconds) + + async def create_speech_uncached( self, message: BaseMessage, chunk_size: int, - bot_sentiment: Optional[BotSentiment] = None, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, ) -> SynthesisResult: raise NotImplementedError + async def create_speech( + self, + message: BaseMessage, + chunk_size: int, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, + ) -> SynthesisResult: + if isinstance(message, SilenceMessage): + return SilenceAudio( + message, + self.synthesizer_config, + ).create_synthesis_result(chunk_size) + + maybe_cached_audio = await self.get_cached_audio(message) + if maybe_cached_audio is not None: + return maybe_cached_audio.create_synthesis_result(chunk_size) + return await self.create_speech_uncached( + message, + chunk_size, + is_first_text_chunk=is_first_text_chunk, + is_sole_text_chunk=is_sole_text_chunk, + ) + + async def chunk_result_generator_from_queue(self, chunk_queue: asyncio.Queue[Optional[bytes]]): + while True: + try: + chunk = await chunk_queue.get() + if chunk is None: + break + yield SynthesisResult.ChunkResult( + chunk=chunk, + is_last_chunk=False, + ) + except asyncio.CancelledError: + break + # @param file - a file-like object in wav format @staticmethod def create_synthesis_result_from_wav( @@ -220,16 +370,15 @@ def create_synthesis_result_from_wav( ) if synthesizer_config.should_encode_as_wav: - chunk_transform = lambda chunk: encode_as_wav(chunk, synthesizer_config) + chunk_transform = lambda chunk: encode_as_wav(chunk, synthesizer_config) # noqa: E731 + else: - chunk_transform = lambda chunk: chunk + chunk_transform = lambda chunk: chunk # noqa: E731 async def chunk_generator(output_bytes): for i in range(0, len(output_bytes), chunk_size): if i + chunk_size > len(output_bytes): - yield SynthesisResult.ChunkResult( - chunk_transform(output_bytes[i:]), True - ) + yield SynthesisResult.ChunkResult(chunk_transform(output_bytes[i:]), True) else: yield SynthesisResult.ChunkResult( chunk_transform(output_bytes[i : i + chunk_size]), False @@ -246,14 +395,9 @@ async def experimental_mp3_streaming_output_generator( self, response: aiohttp.ClientResponse, chunk_size: int, - create_speech_span: Optional[Span], ) -> AsyncGenerator[SynthesisResult.ChunkResult, None]: - miniaudio_worker_input_queue: asyncio.Queue[Union[bytes, None]] = ( - asyncio.Queue() - ) - miniaudio_worker_output_queue: asyncio.Queue[Tuple[bytes, bool]] = ( - asyncio.Queue() - ) + miniaudio_worker_input_queue: asyncio.Queue[Union[bytes, None]] = asyncio.Queue() + miniaudio_worker_output_queue: asyncio.Queue[Tuple[bytes, bool]] = asyncio.Queue() miniaudio_worker = MiniaudioWorker( self.synthesizer_config, chunk_size, @@ -270,7 +414,7 @@ async def send_chunks(): miniaudio_worker.consume_nonblocking(None) # sentinel try: - asyncio.create_task(send_chunks()) + asyncio_create_task_with_done_error_log(send_chunks(), reraise_cancelled=True) # Await the output queue of the MiniaudioWorker and yield the wav chunks in another loop while True: @@ -279,10 +423,12 @@ async def send_chunks(): if self.synthesizer_config.should_encode_as_wav: wav_chunk = encode_as_wav(wav_chunk, self.synthesizer_config) + if self.synthesizer_config.audio_encoding == AudioEncoding.MULAW: + wav_chunk = audioop.lin2ulaw(wav_chunk, 2) + yield SynthesisResult.ChunkResult(wav_chunk, is_last) # If this is the last chunk, break the loop - if is_last and create_speech_span is not None: - create_speech_span.end() + if is_last: break except asyncio.CancelledError: pass @@ -290,5 +436,4 @@ async def send_chunks(): miniaudio_worker.terminate() async def tear_down(self): - if self.should_close_session_on_tear_down: - await self.aiohttp_session.close() + pass diff --git a/vocode/streaming/synthesizer/coqui_synthesizer.py b/vocode/streaming/synthesizer/coqui_synthesizer.py index 8bd8093aa..2feedb10d 100644 --- a/vocode/streaming/synthesizer/coqui_synthesizer.py +++ b/vocode/streaming/synthesizer/coqui_synthesizer.py @@ -1,20 +1,15 @@ import io -from typing import Optional, Tuple, Dict +from typing import Dict, Tuple + import aiohttp -from pydub import AudioSegment from vocode import getenv -from vocode.streaming.synthesizer.base_synthesizer import ( - BaseSynthesizer, - SynthesisResult, - tracer, -) -from vocode.streaming.models.synthesizer import CoquiSynthesizerConfig, SynthesizerType -from vocode.streaming.agent.bot_sentiment_analyser import BotSentiment from vocode.streaming.models.message import BaseMessage +from vocode.streaming.models.synthesizer import CoquiSynthesizerConfig +from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer, SynthesisResult +from vocode.streaming.utils.async_requester import AsyncRequestor -from opentelemetry.context.context import Context - +raise DeprecationWarning("This Synthesizer is deprecated and will be removed in the future.") COQUI_BASE_URL = "https://app.coqui.ai/api/v2" @@ -60,14 +55,12 @@ async def create_speech( self, message: BaseMessage, chunk_size: int, - bot_sentiment: Optional[BotSentiment] = None, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, ) -> SynthesisResult: url, headers, body = self.get_request(message.text) - create_speech_span = tracer.start_span( - f"synthesizer.{SynthesizerType.COQUI.value.split('_', 1)[-1]}.create_total" - ) - async with self.aiohttp_session.request( + async with AsyncRequestor().get_session().request( "POST", url, json=body, @@ -75,15 +68,11 @@ async def create_speech( timeout=aiohttp.ClientTimeout(total=15), ) as response: sample = await response.json() - async with self.aiohttp_session.request( + async with AsyncRequestor().get_session().request( "GET", sample["audio_url"], ) as response: read_response = await response.read() - create_speech_span.end() - convert_span = tracer.start_span( - f"synthesizer.{SynthesizerType.COQUI.value.split('_', 1)[-1]}.convert", - ) result = self.create_synthesis_result_from_wav( synthesizer_config=self.synthesizer_config, @@ -91,5 +80,4 @@ async def create_speech( message=message, chunk_size=chunk_size, ) - convert_span.end() return result diff --git a/vocode/streaming/synthesizer/coqui_tts_synthesizer.py b/vocode/streaming/synthesizer/coqui_tts_synthesizer.py index 45bacb895..ad7d6b7de 100644 --- a/vocode/streaming/synthesizer/coqui_tts_synthesizer.py +++ b/vocode/streaming/synthesizer/coqui_tts_synthesizer.py @@ -1,39 +1,22 @@ import asyncio -from concurrent.futures import ThreadPoolExecutor -import logging -from typing import Optional -import aiohttp -from pydub import AudioSegment -import numpy as np import io -from vocode.streaming.agent.bot_sentiment_analyser import BotSentiment -from vocode.streaming.models.audio_encoding import AudioEncoding -from vocode.streaming.models.message import BaseMessage - -from vocode.streaming.synthesizer.base_synthesizer import ( - BaseSynthesizer, - SynthesisResult, - tracer, -) +from concurrent.futures import ThreadPoolExecutor -from vocode.streaming.models.synthesizer import ( - CoquiTTSSynthesizerConfig, - SynthesizerType, -) +import numpy as np +from pydub import AudioSegment +from TTS.api import TTS -from opentelemetry.context.context import Context +from vocode.streaming.models.message import BaseMessage +from vocode.streaming.models.synthesizer import CoquiTTSSynthesizerConfig +from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer, SynthesisResult class CoquiTTSSynthesizer(BaseSynthesizer[CoquiTTSSynthesizerConfig]): def __init__( self, synthesizer_config: CoquiTTSSynthesizerConfig, - logger: Optional[logging.Logger] = None, - aiohttp_session: Optional[aiohttp.ClientSession] = None, ): - super().__init__(synthesizer_config, aiohttp_session) - - from TTS.api import TTS + super().__init__(synthesizer_config) self.tts = TTS(**synthesizer_config.tts_kwargs) self.speaker = synthesizer_config.speaker @@ -44,11 +27,9 @@ async def create_speech( self, message: BaseMessage, chunk_size: int, - bot_sentiment: Optional[BotSentiment] = None, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, ) -> SynthesisResult: - create_speech_span = tracer.start_span( - f"synthesizer.{SynthesizerType.COQUI_TTS.value.split('_', 1)[-1]}.create_total", - ) tts = self.tts audio_data = await asyncio.get_event_loop().run_in_executor( self.thread_pool_executor, @@ -57,10 +38,6 @@ async def create_speech( self.speaker, self.language, ) - create_speech_span.end() - convert_span = tracer.start_span( - f"synthesizer.{SynthesizerType.COQUI_TTS.value.split('_', 1)[-1]}.convert", - ) audio_data = np.array(audio_data) # Convert the NumPy array to bytes @@ -83,5 +60,4 @@ async def create_speech( chunk_size=chunk_size, ) - convert_span.end() return result diff --git a/vocode/streaming/synthesizer/default_factory.py b/vocode/streaming/synthesizer/default_factory.py new file mode 100644 index 000000000..b5f8b654a --- /dev/null +++ b/vocode/streaming/synthesizer/default_factory.py @@ -0,0 +1,37 @@ +from vocode.streaming.models.synthesizer import ( + AzureSynthesizerConfig, + ElevenLabsSynthesizerConfig, + PlayHtSynthesizerConfig, + RimeSynthesizerConfig, + StreamElementsSynthesizerConfig, + SynthesizerConfig, +) +from vocode.streaming.synthesizer.abstract_factory import AbstractSynthesizerFactory +from vocode.streaming.synthesizer.azure_synthesizer import AzureSynthesizer +from vocode.streaming.synthesizer.eleven_labs_synthesizer import ElevenLabsSynthesizer +from vocode.streaming.synthesizer.play_ht_synthesizer import PlayHtSynthesizer +from vocode.streaming.synthesizer.play_ht_synthesizer_v2 import PlayHtSynthesizerV2 +from vocode.streaming.synthesizer.rime_synthesizer import RimeSynthesizer +from vocode.streaming.synthesizer.stream_elements_synthesizer import StreamElementsSynthesizer + + +class DefaultSynthesizerFactory(AbstractSynthesizerFactory): + def create_synthesizer( + self, + synthesizer_config: SynthesizerConfig, + ): + if isinstance(synthesizer_config, AzureSynthesizerConfig): + return AzureSynthesizer(synthesizer_config) + elif isinstance(synthesizer_config, ElevenLabsSynthesizerConfig): + return ElevenLabsSynthesizer(synthesizer_config) + elif isinstance(synthesizer_config, PlayHtSynthesizerConfig): + if synthesizer_config.version == "2": + return PlayHtSynthesizerV2(synthesizer_config) + else: + return PlayHtSynthesizer(synthesizer_config) + elif isinstance(synthesizer_config, RimeSynthesizerConfig): + return RimeSynthesizer(synthesizer_config) + elif isinstance(synthesizer_config, StreamElementsSynthesizerConfig): + return StreamElementsSynthesizer(synthesizer_config) + else: + raise Exception("Invalid synthesizer config") diff --git a/vocode/streaming/synthesizer/eleven_labs_synthesizer.py b/vocode/streaming/synthesizer/eleven_labs_synthesizer.py index 051d0900b..e4af50c22 100644 --- a/vocode/streaming/synthesizer/eleven_labs_synthesizer.py +++ b/vocode/streaming/synthesizer/eleven_labs_synthesizer.py @@ -1,72 +1,83 @@ import asyncio -import logging -import time -from typing import Any, AsyncGenerator, Optional, Tuple, Union -import wave -import aiohttp -from opentelemetry.trace import Span +import hashlib +from typing import Optional -from vocode import getenv -from vocode.streaming.synthesizer.base_synthesizer import ( - BaseSynthesizer, - SynthesisResult, - encode_as_wav, - tracer, -) -from vocode.streaming.models.synthesizer import ( - ElevenLabsSynthesizerConfig, - SynthesizerType, -) -from vocode.streaming.agent.bot_sentiment_analyser import BotSentiment -from vocode.streaming.models.message import BaseMessage -from vocode.streaming.utils.mp3_helper import decode_mp3 -from vocode.streaming.synthesizer.miniaudio_worker import MiniaudioWorker +from elevenlabs import Voice, VoiceSettings +from elevenlabs.client import AsyncElevenLabs +from loguru import logger +from vocode.streaming.models.audio import AudioEncoding, SamplingRate +from vocode.streaming.models.message import BaseMessage +from vocode.streaming.models.synthesizer import ElevenLabsSynthesizerConfig +from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer, SynthesisResult +from vocode.streaming.utils.create_task import asyncio_create_task_with_done_error_log -ADAM_VOICE_ID = "pNInz6obpgDQGcFmaJgB" ELEVEN_LABS_BASE_URL = "https://api.elevenlabs.io/v1/" +STREAMED_CHUNK_SIZE = 16000 * 2 // 4 # 1/8 of a second of 16kHz audio with 16-bit samples class ElevenLabsSynthesizer(BaseSynthesizer[ElevenLabsSynthesizerConfig]): def __init__( self, synthesizer_config: ElevenLabsSynthesizerConfig, - logger: Optional[logging.Logger] = None, - aiohttp_session: Optional[aiohttp.ClientSession] = None, ): - super().__init__(synthesizer_config, aiohttp_session) + super().__init__(synthesizer_config) - import elevenlabs + assert synthesizer_config.api_key is not None, "API key must be set" + assert synthesizer_config.voice_id is not None, "Voice ID must be set" + self.api_key = synthesizer_config.api_key - self.elevenlabs = elevenlabs + self.elevenlabs_client = AsyncElevenLabs( + api_key=self.api_key, + ) - self.api_key = synthesizer_config.api_key or getenv("ELEVEN_LABS_API_KEY") - self.voice_id = synthesizer_config.voice_id or ADAM_VOICE_ID + self.voice_id = synthesizer_config.voice_id self.stability = synthesizer_config.stability self.similarity_boost = synthesizer_config.similarity_boost self.model_id = synthesizer_config.model_id self.optimize_streaming_latency = synthesizer_config.optimize_streaming_latency self.words_per_minute = 150 - self.experimental_streaming = synthesizer_config.experimental_streaming - async def create_speech( + if self.synthesizer_config.audio_encoding == AudioEncoding.LINEAR16: + match self.synthesizer_config.sampling_rate: + case SamplingRate.RATE_16000: + self.output_format = "pcm_16000" + case SamplingRate.RATE_22050: + self.output_format = "pcm_22050" + case SamplingRate.RATE_24000: + self.output_format = "pcm_24000" + case SamplingRate.RATE_44100: + self.output_format = "pcm_44100" + case _: + raise ValueError( + f"Unsupported sampling rate: {self.synthesizer_config.sampling_rate}. Elevenlabs only supports 16000, 22050, 24000, and 44100 Hz." + ) + elif self.synthesizer_config.audio_encoding == AudioEncoding.MULAW: + self.output_format = "ulaw_8000" + else: + raise ValueError( + f"Unsupported audio encoding: {self.synthesizer_config.audio_encoding}" + ) + + async def create_speech_uncached( self, message: BaseMessage, chunk_size: int, - bot_sentiment: Optional[BotSentiment] = None, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, ) -> SynthesisResult: - voice = self.elevenlabs.Voice(voice_id=self.voice_id) + self.total_chars += len(message.text) + voice = Voice(voice_id=self.voice_id) if self.stability is not None and self.similarity_boost is not None: - voice.settings = self.elevenlabs.VoiceSettings( + voice.settings = VoiceSettings( stability=self.stability, similarity_boost=self.similarity_boost ) - url = ELEVEN_LABS_BASE_URL + f"text-to-speech/{self.voice_id}" - - if self.experimental_streaming: - url += "/stream" - + url = ( + ELEVEN_LABS_BASE_URL + + f"text-to-speech/{self.voice_id}/stream?output_format={self.output_format}" + ) if self.optimize_streaming_latency: - url += f"?optimize_streaming_latency={self.optimize_streaming_latency}" + url += f"&optimize_streaming_latency={self.optimize_streaming_latency}" headers = {"xi-api-key": self.api_key} body = { "text": message.text, @@ -75,44 +86,59 @@ async def create_speech( if self.model_id: body["model_id"] = self.model_id - create_speech_span = tracer.start_span( - f"synthesizer.{SynthesizerType.ELEVEN_LABS.value.split('_', 1)[-1]}.create_total", + chunk_queue: asyncio.Queue[Optional[bytes]] = asyncio.Queue() + asyncio_create_task_with_done_error_log( + self.get_chunks(url, headers, body, chunk_size, chunk_queue), ) - session = self.aiohttp_session - - response = await session.request( - "POST", - url, - json=body, - headers=headers, - timeout=aiohttp.ClientTimeout(total=15), + return SynthesisResult( + self.chunk_result_generator_from_queue(chunk_queue), + lambda seconds: self.get_message_cutoff_from_voice_speed(message, seconds, 150), ) - if not response.ok: - raise Exception(f"ElevenLabs API returned {response.status} status code") - if self.experimental_streaming: - return SynthesisResult( - self.experimental_mp3_streaming_output_generator( - response, chunk_size, create_speech_span - ), # should be wav - lambda seconds: self.get_message_cutoff_from_voice_speed( - message, seconds, self.words_per_minute - ), - ) - else: - audio_data = await response.read() - create_speech_span.end() - convert_span = tracer.start_span( - f"synthesizer.{SynthesizerType.ELEVEN_LABS.value.split('_', 1)[-1]}.convert", + + @classmethod + def get_voice_identifier(cls, synthesizer_config: ElevenLabsSynthesizerConfig): + hashed_api_key = hashlib.sha256(f"{synthesizer_config.api_key}".encode("utf-8")).hexdigest() + return ":".join( + ( + "eleven_labs", + hashed_api_key, + str(synthesizer_config.voice_id), + str(synthesizer_config.model_id), + str(synthesizer_config.stability), + str(synthesizer_config.similarity_boost), + str(synthesizer_config.optimize_streaming_latency), + synthesizer_config.audio_encoding, ) - output_bytes_io = decode_mp3(audio_data) + ) - result = self.create_synthesis_result_from_wav( - synthesizer_config=self.synthesizer_config, - file=output_bytes_io, - message=message, - chunk_size=chunk_size, + async def get_chunks( + self, + url: str, + headers: dict, + body: dict, + chunk_size: int, + chunk_queue: asyncio.Queue[Optional[bytes]], + ): + try: + async_client = self.async_requestor.get_client() + stream = await async_client.send( + async_client.build_request( + "POST", + url, + headers=headers, + json=body, + ), + stream=True, ) - convert_span.end() - return result + if not stream.is_success: + error = await stream.aread() + logger.error(f"ElevenLabs API failed: {stream.status_code} {error.decode('utf-8')}") + raise Exception(f"ElevenLabs API returned {stream.status_code} status code") + async for chunk in stream.aiter_bytes(chunk_size): + chunk_queue.put_nowait(chunk) + except asyncio.CancelledError: + pass + finally: + chunk_queue.put_nowait(None) # treated as sentinel diff --git a/vocode/streaming/synthesizer/eleven_labs_websocket_synthesizer.py b/vocode/streaming/synthesizer/eleven_labs_websocket_synthesizer.py new file mode 100644 index 000000000..0f0679713 --- /dev/null +++ b/vocode/streaming/synthesizer/eleven_labs_websocket_synthesizer.py @@ -0,0 +1,340 @@ +import asyncio +import audioop +import base64 +from typing import AsyncGenerator, List, Optional, Tuple + +import numpy as np +import websockets +from loguru import logger +from pydantic import BaseModel, conint + +from vocode.streaming.models.audio import AudioEncoding, SamplingRate +from vocode.streaming.models.message import BaseMessage, BotBackchannel, LLMToken +from vocode.streaming.models.synthesizer import ElevenLabsSynthesizerConfig +from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer, SynthesisResult +from vocode.streaming.synthesizer.eleven_labs_synthesizer import ElevenLabsSynthesizer +from vocode.streaming.synthesizer.input_streaming_synthesizer import InputStreamingSynthesizer + +NONCE = "071b5f21-3b24-4427-817e-62508007ae60" +ELEVEN_LABS_BASE_URL = "wss://api.elevenlabs.io/v1/" + + +# Based on https://github.com/elevenlabs/elevenlabs-python/blob/main/src/elevenlabs/tts.py +async def string_chunker(string: str) -> AsyncGenerator[str, None]: + splitters = (".", ",", "?", "!", ";", ":", "—", "-", "(", ")", "[", "]", "}", " ") + buffer = "" + for text in string: + if buffer.endswith(splitters): + yield buffer if buffer.endswith(" ") else buffer + " " + buffer = text + elif text.startswith(splitters): + output = buffer + text[0] + yield output if output.endswith(" ") else output + " " + buffer = text[1:] + else: + buffer += text + if buffer != "": + yield buffer + " " + + +class ElevenLabsWebsocketVoiceSettings(BaseModel): + stability: float + similarity_boost: float + + +class ElevenLabsWebsocketGenerationConfig(BaseModel): + chunk_length_schedule: list[conint(ge=50, le=500)] # type: ignore + # TODO: Replace above with below for pydantic 2.X + # chunk_length_schedule: list[Annotated[int, Field(strict=True, ge=50, le=500)]] + + +class ElevenLabsWebsocketMessage(BaseModel): + text: str + try_trigger_generation: bool = True + flush: bool = False + + +class ElevenLabsWebsocketFirstMessage(ElevenLabsWebsocketMessage, BaseModel): + voice_settings: ElevenLabsWebsocketVoiceSettings | None = None + generation_config: ElevenLabsWebsocketGenerationConfig | None = None + xi_api_key: str + + +class ElevenLabsWebsocketResponseAlignment(BaseModel): + chars: list[str] + charStartTimesMs: list[int] + charDurationsMs: list[int] + + +class ElevenLabsWebsocketResponse(BaseModel): + audio: Optional[str] = None + isFinal: Optional[bool] = None + normalizedAlignment: Optional[ElevenLabsWebsocketResponseAlignment] = None + alignment: Optional[ElevenLabsWebsocketResponseAlignment] = None + + def __str__(self): + return f"ElevenLabsWebsocketResponse(has_audio={self.audio is not None}, isFinal={self.isFinal}, alignment={self.alignment})" + + +class ElevenLabsWSSynthesizer( + BaseSynthesizer[ElevenLabsSynthesizerConfig], InputStreamingSynthesizer +): + def __init__( + self, + synthesizer_config: ElevenLabsSynthesizerConfig, + ): + super().__init__( + synthesizer_config, + ) + + assert synthesizer_config.api_key is not None, "API key must be set" + assert synthesizer_config.voice_id is not None, "Voice ID must be set" + self.api_key = synthesizer_config.api_key + self.voice_id = synthesizer_config.voice_id + self.stability = synthesizer_config.stability + self.similarity_boost = synthesizer_config.similarity_boost + self.model_id = synthesizer_config.model_id + self.optimize_streaming_latency = synthesizer_config.optimize_streaming_latency + self.words_per_minute = 150 + + self.text_chunk_queue: asyncio.Queue[Optional[BotBackchannel | LLMToken]] = asyncio.Queue() + self.voice_packet_queue: asyncio.Queue[Optional[bytes]] = asyncio.Queue() + self.current_turn_utterances_by_chunk: List[Tuple[str, float]] = [] + self.sample_width = 2 if synthesizer_config.audio_encoding == AudioEncoding.LINEAR16 else 1 + + self.websocket_listener: asyncio.Task | None = None + self.websocket_tasks: dict[str, asyncio.Task | None] = { + "listener": None, + "writer": None, + } + self.end_of_turn = False + + # While this looks useless, we need to assign the response of `asyncio.gather` + # to *something* or we risk garbage collection of the running coroutines spawned + # by `asyncio.gather`. + self.websocket_functions: list[None] | None = None + + if self.synthesizer_config.audio_encoding == AudioEncoding.LINEAR16: + match self.synthesizer_config.sampling_rate: + case SamplingRate.RATE_16000: + self.output_format = "pcm_16000" + case SamplingRate.RATE_22050: + self.output_format = "pcm_22050" + case SamplingRate.RATE_24000: + self.output_format = "pcm_24000" + case SamplingRate.RATE_44100: + self.output_format = "pcm_44100" + case _: + raise ValueError( + f"Unsupported sampling rate: {self.synthesizer_config.sampling_rate}. Elevenlabs only supports 16000, 22050, 24000, and 44100 Hz." + ) + elif self.synthesizer_config.audio_encoding == AudioEncoding.MULAW: + self.output_format = "ulaw_8000" + else: + raise ValueError( + f"Unsupported audio encoding: {self.synthesizer_config.audio_encoding}" + ) + + def get_eleven_labs_websocket_voice_settings(self): + if self.stability is None or self.similarity_boost is None: + return None + return ElevenLabsWebsocketVoiceSettings( + stability=self.stability, + similarity_boost=self.similarity_boost, + ) + + def reduce_chunk_amplitude(self, chunk: bytes, factor: float) -> bytes: + if self.synthesizer_config.audio_encoding == AudioEncoding.MULAW: + chunk = audioop.ulaw2lin(chunk, 2) + pcm = np.frombuffer(chunk, dtype=np.int16) + pcm = (pcm * factor).astype(np.int16) + pcm_bytes = pcm.tobytes() + if self.synthesizer_config.audio_encoding == AudioEncoding.MULAW: + return audioop.lin2ulaw(pcm_bytes, 2) + else: + return pcm_bytes + + async def establish_websocket_listeners(self, chunk_size): + url = ( + ELEVEN_LABS_BASE_URL + + f"text-to-speech/{self.voice_id}/stream-input?output_format={self.output_format}" + ) + if self.optimize_streaming_latency: + url += f"&optimize_streaming_latency={self.optimize_streaming_latency}" + if self.model_id: + url += f"&model_id={self.model_id}" + headers = {"xi-api-key": self.api_key} + + backchannelled = False + + async with websockets.connect( + url, + extra_headers=headers, + ) as ws: + + async def write() -> None: + nonlocal backchannelled + try: + first_message = True + while True: + message = await self.text_chunk_queue.get() + if not message: + break + if first_message and isinstance(message, BotBackchannel): + backchannelled = True + eleven_labs_ws_message = ( + ElevenLabsWebsocketMessage( + text=message.text, + flush=not isinstance(message, LLMToken), + ).json() + if not first_message + else ElevenLabsWebsocketFirstMessage( + text=message.text, + voice_settings=self.get_eleven_labs_websocket_voice_settings(), + generation_config=ElevenLabsWebsocketGenerationConfig( + chunk_length_schedule=[50], + ), + flush=not isinstance(message, LLMToken), + xi_api_key=self.api_key, + ).json(exclude_none=True) + ) + await ws.send(eleven_labs_ws_message) + first_message = False + finally: + await ws.send(ElevenLabsWebsocketMessage(text="").json()) + + async def listen() -> None: + """Listen to the websocket for audio data and stream it.""" + + first_message = True + buffer = bytearray() + while True: + message = await ws.recv() + if "audio" not in message: + continue + response = ElevenLabsWebsocketResponse.parse_raw(message) + if response.audio: + decoded = base64.b64decode(response.audio) + seconds = len(decoded) / ( + self.sample_width * self.synthesizer_config.sampling_rate + ) + if response.alignment: + utterance_chunk = "".join(response.alignment.chars) + " " + self.current_turn_utterances_by_chunk.append((utterance_chunk, seconds)) + # For backchannels, send them all as one chunk (so it can't be interrupted) and reduce the volume + # so that in the case of a false endpoint, the backchannel is not too loud. + if first_message and backchannelled: + buffer.extend(decoded) + logger.info("First message was a backchannel, reducing volume.") + reduced_amplitude_buffer = self.reduce_chunk_amplitude( + buffer, factor=self.synthesizer_config.backchannel_amplitude_factor + ) + await self.voice_packet_queue.put(reduced_amplitude_buffer) + buffer = bytearray() + first_message = False + else: + buffer.extend(decoded) + for chunk_idx in range(0, len(buffer) - chunk_size, chunk_size): + await self.voice_packet_queue.put( + buffer[chunk_idx : chunk_idx + chunk_size] + ) + buffer = buffer[len(buffer) - (len(buffer) % chunk_size) :] + + if response.isFinal: + await self.voice_packet_queue.put(None) + break + + self.websocket_tasks["listener"] = asyncio.create_task(listen()) + self.websocket_tasks["writer"] = asyncio.create_task(write()) + self.websocket_functions = await asyncio.gather(*self.websocket_tasks.values()) + + def get_current_utterance_synthesis_result(self): + return SynthesisResult( + self.chunk_result_generator_from_queue(self.voice_packet_queue), + lambda seconds: self.get_current_message_so_far(seconds), + ) + + async def create_speech_uncached( + self, + message: BaseMessage, + chunk_size: int, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, + ): + """ + Ran when doing utterance parsing. + ie: "Hello, my name is foo." + """ + if not self.websocket_listener: + self.websocket_listener = asyncio.create_task( + self.establish_websocket_listeners(chunk_size) + ) + + if isinstance(message, BotBackchannel): + if not message.text.endswith(" "): + message.text += " " + await self.text_chunk_queue.put(message) + self.total_chars += len(message.text) + else: + async for text in string_chunker(message.text): + await self.text_chunk_queue.put(LLMToken(text=text)) + self.total_chars += len(text) + + return self.get_current_utterance_synthesis_result() + + async def send_token_to_synthesizer(self, message: LLMToken, chunk_size: int): + """ + Ran when parsing a single chunk of text. + + ie: "Hello," + """ + self.total_chars += len(message.text) + + if not self.websocket_listener: + self.websocket_listener = asyncio.create_task( + self.establish_websocket_listeners(chunk_size) + ) + + await self.text_chunk_queue.put(message) + return None + + def _cleanup_websocket_tasks(self): + for task in self.websocket_tasks.values(): + if task is not None: + task.cancel() + self.text_chunk_queue = asyncio.Queue() + self.voice_packet_queue = asyncio.Queue() + if self.websocket_listener is not None: + self.websocket_listener.cancel() + + def ready_synthesizer(self, chunk_size: int): + self._cleanup_websocket_tasks() + self.websocket_listener = asyncio.create_task( + self.establish_websocket_listeners(chunk_size) + ) + + def get_current_message_so_far(self, seconds: float) -> str: + seconds_idx = 0.0 + buffer = "" + for utterance, duration in self.current_turn_utterances_by_chunk: + if seconds_idx > seconds: + return buffer + buffer += utterance + seconds_idx += duration + return buffer + + @classmethod + def get_voice_identifier(cls, synthesizer_config: ElevenLabsSynthesizerConfig): + return ElevenLabsSynthesizer.get_voice_identifier(synthesizer_config) + + async def handle_end_of_turn(self): + self.end_of_turn = True + await self.text_chunk_queue.put(None) + self.current_turn_utterances_by_chunk = [] + + async def cancel_websocket_tasks(self): + self._cleanup_websocket_tasks() + + async def tear_down(self): + await self.cancel_websocket_tasks() + await super().tear_down() diff --git a/vocode/streaming/synthesizer/factory.py b/vocode/streaming/synthesizer/factory.py deleted file mode 100644 index 24a4f3f9d..000000000 --- a/vocode/streaming/synthesizer/factory.py +++ /dev/null @@ -1,76 +0,0 @@ -import logging -from typing import Optional -import typing -import aiohttp - -from vocode.streaming.models.synthesizer import ( - AzureSynthesizerConfig, - CoquiTTSSynthesizerConfig, - ElevenLabsSynthesizerConfig, - GTTSSynthesizerConfig, - GoogleSynthesizerConfig, - PlayHtSynthesizerConfig, - RimeSynthesizerConfig, - PollySynthesizerConfig, - StreamElementsSynthesizerConfig, - SynthesizerConfig, - SynthesizerType, -) -from vocode.streaming.synthesizer.azure_synthesizer import AzureSynthesizer -from vocode.streaming.synthesizer.eleven_labs_synthesizer import ElevenLabsSynthesizer -from vocode.streaming.synthesizer.google_synthesizer import GoogleSynthesizer -from vocode.streaming.synthesizer.gtts_synthesizer import GTTSSynthesizer -from vocode.streaming.synthesizer.play_ht_synthesizer import PlayHtSynthesizer -from vocode.streaming.synthesizer.rime_synthesizer import RimeSynthesizer -from vocode.streaming.synthesizer.polly_synthesizer import PollySynthesizer -from vocode.streaming.synthesizer.stream_elements_synthesizer import ( - StreamElementsSynthesizer, -) -from vocode.streaming.synthesizer.coqui_tts_synthesizer import CoquiTTSSynthesizer - - -class SynthesizerFactory: - def create_synthesizer( - self, - synthesizer_config: SynthesizerConfig, - logger: Optional[logging.Logger] = None, - aiohttp_session: Optional[aiohttp.ClientSession] = None, - ): - if isinstance(synthesizer_config, GoogleSynthesizerConfig): - return GoogleSynthesizer( - synthesizer_config, logger=logger, aiohttp_session=aiohttp_session - ) - elif isinstance(synthesizer_config, AzureSynthesizerConfig): - return AzureSynthesizer( - synthesizer_config, logger=logger, aiohttp_session=aiohttp_session - ) - elif isinstance(synthesizer_config, ElevenLabsSynthesizerConfig): - return ElevenLabsSynthesizer( - synthesizer_config, logger=logger, aiohttp_session=aiohttp_session - ) - elif isinstance(synthesizer_config, PlayHtSynthesizerConfig): - return PlayHtSynthesizer( - synthesizer_config, logger=logger, aiohttp_session=aiohttp_session - ) - elif isinstance(synthesizer_config, RimeSynthesizerConfig): - return RimeSynthesizer( - synthesizer_config, logger=logger, aiohttp_session=aiohttp_session - ) - elif isinstance(synthesizer_config, GTTSSynthesizerConfig): - return GTTSSynthesizer( - synthesizer_config, logger=logger, aiohttp_session=aiohttp_session - ) - elif isinstance(synthesizer_config, StreamElementsSynthesizerConfig): - return StreamElementsSynthesizer( - synthesizer_config, logger=logger, aiohttp_session=aiohttp_session - ) - elif isinstance(synthesizer_config, CoquiTTSSynthesizerConfig): - return CoquiTTSSynthesizer( - synthesizer_config, logger=logger, aiohttp_session=aiohttp_session - ) - elif isinstance(synthesizer_config, PollySynthesizerConfig): - return PollySynthesizer( - synthesizer_config, logger=logger, aiohttp_session=aiohttp_session - ) - else: - raise Exception("Invalid synthesizer config") diff --git a/vocode/streaming/synthesizer/google_synthesizer.py b/vocode/streaming/synthesizer/google_synthesizer.py index d834eef27..225ab2d5d 100644 --- a/vocode/streaming/synthesizer/google_synthesizer.py +++ b/vocode/streaming/synthesizer/google_synthesizer.py @@ -1,45 +1,26 @@ import asyncio -from concurrent.futures import ThreadPoolExecutor import io -import logging -import os import wave -from typing import Any, Optional -import aiohttp +from concurrent.futures import ThreadPoolExecutor +from typing import Any -from vocode import getenv +import google.auth +from google.cloud import texttospeech as tts # type: ignore -from vocode.streaming.agent.bot_sentiment_analyser import BotSentiment from vocode.streaming.models.message import BaseMessage -from vocode.streaming.synthesizer.base_synthesizer import ( - BaseSynthesizer, - SynthesisResult, - encode_as_wav, - tracer, -) -from vocode.streaming.models.synthesizer import GoogleSynthesizerConfig, SynthesizerType -from vocode.streaming.models.audio_encoding import AudioEncoding -from vocode.streaming.utils import convert_wav - -from opentelemetry.context.context import Context +from vocode.streaming.models.synthesizer import GoogleSynthesizerConfig +from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer, SynthesisResult class GoogleSynthesizer(BaseSynthesizer[GoogleSynthesizerConfig]): def __init__( self, synthesizer_config: GoogleSynthesizerConfig, - logger: Optional[logging.Logger] = None, - aiohttp_session: Optional[aiohttp.ClientSession] = None, ): - super().__init__(synthesizer_config, aiohttp_session) - - from google.cloud import texttospeech as tts - import google.auth + super().__init__(synthesizer_config) google.auth.default() - self.tts = tts - # Instantiates a client self.client = tts.TextToSpeechClient() @@ -61,18 +42,16 @@ def __init__( self.thread_pool_executor = ThreadPoolExecutor(max_workers=1) def synthesize(self, message: str) -> Any: - synthesis_input = self.tts.SynthesisInput(text=message) + synthesis_input = tts.SynthesisInput(text=message) # Perform the text-to-speech request on the text input with the selected # voice parameters and audio file type return self.client.synthesize_speech( - request=self.tts.SynthesizeSpeechRequest( + request=tts.SynthesizeSpeechRequest( input=synthesis_input, voice=self.voice, audio_config=self.audio_config, - enable_time_pointing=[ - self.tts.SynthesizeSpeechRequest.TimepointType.SSML_MARK - ], + enable_time_pointing=[tts.SynthesizeSpeechRequest.TimepointType.SSML_MARK], ) ) @@ -81,20 +60,14 @@ async def create_speech( self, message: BaseMessage, chunk_size: int, - bot_sentiment: Optional[BotSentiment] = None, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, ) -> SynthesisResult: - create_speech_span = tracer.start_span( - f"synthesizer.{SynthesizerType.GOOGLE.value.split('_', 1)[-1]}.create_total", - ) - response: self.tts.SynthesizeSpeechResponse = ( # type: ignore + response: tts.SynthesizeSpeechResponse = ( # type: ignore await asyncio.get_event_loop().run_in_executor( self.thread_pool_executor, self.synthesize, message.text ) ) - create_speech_span.end() - convert_span = tracer.start_span( - f"synthesizer.{SynthesizerType.GOOGLE.value.split('_', 1)[-1]}.convert", - ) output_sample_rate = response.audio_config.sample_rate_hertz output_bytes_io = io.BytesIO() @@ -111,5 +84,4 @@ async def create_speech( message=message, chunk_size=chunk_size, ) - convert_span.end() return result diff --git a/vocode/streaming/synthesizer/gtts_synthesizer.py b/vocode/streaming/synthesizer/gtts_synthesizer.py index 5c49fb905..8ad8a31d5 100644 --- a/vocode/streaming/synthesizer/gtts_synthesizer.py +++ b/vocode/streaming/synthesizer/gtts_synthesizer.py @@ -1,58 +1,38 @@ import asyncio from concurrent.futures import ThreadPoolExecutor -import logging -import aiohttp -from pydub import AudioSegment -from typing import Optional from io import BytesIO -from vocode.streaming.agent.bot_sentiment_analyser import BotSentiment -from vocode.streaming.models.message import BaseMessage -from vocode.streaming.models.synthesizer import GTTSSynthesizerConfig, SynthesizerType -from vocode.streaming.synthesizer.base_synthesizer import ( - BaseSynthesizer, - SynthesisResult, - tracer, -) -from opentelemetry.context.context import Context +from gtts import gTTS +from pydub import AudioSegment + +from vocode.streaming.models.message import BaseMessage +from vocode.streaming.models.synthesizer import GTTSSynthesizerConfig +from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer, SynthesisResult class GTTSSynthesizer(BaseSynthesizer): def __init__( self, synthesizer_config: GTTSSynthesizerConfig, - logger: Optional[logging.Logger] = None, - aiohttp_session: Optional[aiohttp.ClientSession] = None, ): - super().__init__(synthesizer_config, aiohttp_session) + super().__init__(synthesizer_config) - from gtts import gTTS - - self.gTTS = gTTS self.thread_pool_executor = ThreadPoolExecutor(max_workers=1) async def create_speech( self, message: BaseMessage, chunk_size: int, - bot_sentiment: Optional[BotSentiment] = None, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, ) -> SynthesisResult: audio_file = BytesIO() def thread(): - tts = self.gTTS(message.text) + tts = gTTS(message.text) tts.write_to_fp(audio_file) - create_speech_span = tracer.start_span( - f"synthesizer.{SynthesizerType.GTTS.value.split('_', 1)[-1]}.create_total" - ) - await asyncio.get_event_loop().run_in_executor( - self.thread_pool_executor, thread - ) - create_speech_span.end() - convert_span = tracer.start_span( - f"synthesizer.{SynthesizerType.GTTS.value.split('_', 1)[-1]}.convert", - ) + await asyncio.get_event_loop().run_in_executor(self.thread_pool_executor, thread) audio_file.seek(0) # TODO: probably needs to be in a thread audio_segment: AudioSegment = AudioSegment.from_mp3(audio_file) # type: ignore @@ -65,5 +45,4 @@ def thread(): message=message, chunk_size=chunk_size, ) - convert_span.end() return result diff --git a/vocode/streaming/synthesizer/input_streaming_synthesizer.py b/vocode/streaming/synthesizer/input_streaming_synthesizer.py new file mode 100644 index 000000000..cb3d8d425 --- /dev/null +++ b/vocode/streaming/synthesizer/input_streaming_synthesizer.py @@ -0,0 +1,16 @@ +from vocode.streaming.models.message import LLMToken + + +class InputStreamingSynthesizer: + async def handle_end_of_turn(self): + pass + + def get_current_utterance_synthesis_result(self): + raise NotImplementedError + + async def send_token_to_synthesizer( + self, + message: LLMToken, + chunk_size: int, + ): + raise NotImplementedError diff --git a/vocode/streaming/synthesizer/miniaudio_worker.py b/vocode/streaming/synthesizer/miniaudio_worker.py index e6a05a6bd..92d33adc3 100644 --- a/vocode/streaming/synthesizer/miniaudio_worker.py +++ b/vocode/streaming/synthesizer/miniaudio_worker.py @@ -1,14 +1,16 @@ from __future__ import annotations -import queue -from typing import Optional, Tuple, Union import asyncio +import queue +from typing import Tuple, Union + import miniaudio +from loguru import logger from vocode.streaming.models.synthesizer import SynthesizerConfig from vocode.streaming.utils import convert_wav from vocode.streaming.utils.mp3_helper import decode_mp3 -from vocode.streaming.utils.worker import ThreadAsyncWorker, logger +from vocode.streaming.utils.worker import ThreadAsyncWorker class MiniaudioWorker(ThreadAsyncWorker[Union[bytes, None]]): @@ -41,9 +43,7 @@ def _run_loop(self): if mp3_chunk is None: current_mp3_buffer.clear() current_wav_buffer.clear() - self.output_janus_queue.sync_q.put( - (bytes(current_wav_output_buffer), True) - ) + self.output_janus_queue.sync_q.put((bytes(current_wav_output_buffer), True)) current_wav_output_buffer.clear() continue try: diff --git a/vocode/streaming/synthesizer/play_ht_synthesizer.py b/vocode/streaming/synthesizer/play_ht_synthesizer.py index d6deb49af..05405af9d 100644 --- a/vocode/streaming/synthesizer/play_ht_synthesizer.py +++ b/vocode/streaming/synthesizer/play_ht_synthesizer.py @@ -1,18 +1,13 @@ import asyncio -import logging -from typing import Optional +from typing import Literal -from aiohttp import ClientSession, ClientTimeout -from vocode import getenv -from vocode.streaming.agent.bot_sentiment_analyser import BotSentiment +import aiohttp +from aiohttp import ClientTimeout + +from vocode.streaming.models.audio import AudioEncoding from vocode.streaming.models.message import BaseMessage -from vocode.streaming.models.synthesizer import PlayHtSynthesizerConfig, SynthesizerType -from vocode.streaming.synthesizer.base_synthesizer import ( - BaseSynthesizer, - SynthesisResult, - tracer, -) -from vocode.streaming.utils.mp3_helper import decode_mp3 +from vocode.streaming.models.synthesizer import PlayHtSynthesizerConfig +from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer, SynthesisResult TTS_ENDPOINT = "https://play.ht/api/v2/tts/stream" @@ -21,15 +16,15 @@ class PlayHtSynthesizer(BaseSynthesizer[PlayHtSynthesizerConfig]): def __init__( self, synthesizer_config: PlayHtSynthesizerConfig, - logger: Optional[logging.Logger] = None, - aiohttp_session: Optional[ClientSession] = None, max_backoff_retries=3, backoff_retry_delay=2, ): - super().__init__(synthesizer_config, aiohttp_session) + super().__init__( + synthesizer_config, + ) self.synthesizer_config = synthesizer_config - self.api_key = synthesizer_config.api_key or getenv("PLAY_HT_API_KEY") - self.user_id = synthesizer_config.user_id or getenv("PLAY_HT_USER_ID") + self.api_key = synthesizer_config.api_key + self.user_id = synthesizer_config.user_id if not self.api_key or not self.user_id: raise ValueError( "You must set the PLAY_HT_API_KEY and PLAY_HT_USER_ID environment variables" @@ -39,23 +34,30 @@ def __init__( self.max_backoff_retries = max_backoff_retries self.backoff_retry_delay = backoff_retry_delay - async def create_speech( + async def create_speech_uncached( self, message: BaseMessage, chunk_size: int, - bot_sentiment: Optional[BotSentiment] = None, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, ) -> SynthesisResult: + self.total_chars += len(message.text) headers = { "AUTHORIZATION": f"Bearer {self.api_key}", "X-USER-ID": self.user_id, - "Accept": "audio/mpeg", "Content-Type": "application/json", } + output_format: Literal["wav", "mulaw"] + if self.synthesizer_config.audio_encoding == AudioEncoding.LINEAR16: + output_format = "wav" + elif self.synthesizer_config.audio_encoding == AudioEncoding.MULAW: + output_format = "mulaw" body = { "quality": "draft", "voice": self.synthesizer_config.voice_id, "text": message.text, "sample_rate": self.synthesizer_config.sampling_rate, + "output_format": output_format, } if self.synthesizer_config.speed: body["speed"] = self.synthesizer_config.speed @@ -63,22 +65,20 @@ async def create_speech( body["seed"] = self.synthesizer_config.seed if self.synthesizer_config.temperature: body["temperature"] = self.synthesizer_config.temperature - - create_speech_span = tracer.start_span( - f"synthesizer.{SynthesizerType.PLAY_HT.value.split('_', 1)[-1]}.create_total", - ) + if self.synthesizer_config.quality: + body["quality"] = self.synthesizer_config.quality backoff_retry_delay = self.backoff_retry_delay max_backoff_retries = self.max_backoff_retries - for attempt in range(max_backoff_retries): - response = await self.aiohttp_session.post( + response = await self.async_requestor.get_session().post( TTS_ENDPOINT, headers=headers, json=body, timeout=ClientTimeout(total=15), ) - + if not response.ok: + raise Exception(f"Play.ht API error status code {response.status}") if response.status == 429 and attempt < max_backoff_retries - 1: await asyncio.sleep(backoff_retry_delay) backoff_retry_delay *= 2 # Exponentially increase delay @@ -90,27 +90,56 @@ async def create_speech( if self.experimental_streaming: return SynthesisResult( self.experimental_mp3_streaming_output_generator( - response, chunk_size, create_speech_span - ), + response, chunk_size + ), # should be wav lambda seconds: self.get_message_cutoff_from_voice_speed( message, seconds, self.words_per_minute ), ) else: - read_response = await response.read() - create_speech_span.end() - convert_span = tracer.start_span( - f"synthesizer.{SynthesizerType.PLAY_HT.value.split('_', 1)[-1]}.convert", - ) - output_bytes_io = decode_mp3(read_response) - - result = self.create_synthesis_result_from_wav( - synthesizer_config=self.synthesizer_config, - file=output_bytes_io, - message=message, - chunk_size=chunk_size, + return SynthesisResult( + self._streaming_chunk_generator(response, chunk_size, output_format), + lambda seconds: self.get_message_cutoff_from_voice_speed(message, seconds, 150), ) - convert_span.end() - return result raise Exception("Max retries reached for Play.ht API") + + @classmethod + def get_voice_identifier(cls, synthesizer_config: PlayHtSynthesizerConfig): + return ":".join( + ( + "play_ht", + str(synthesizer_config.user_id), + synthesizer_config.voice_id, + str(synthesizer_config.speed), + str(synthesizer_config.seed), + str(synthesizer_config.temperature), + str(synthesizer_config.quality), + synthesizer_config.audio_encoding, + ) + ) + + @staticmethod + async def _streaming_chunk_generator( + response: aiohttp.ClientResponse, + chunk_size: int, + output_format: Literal["wav", "mulaw"], + ): + if output_format == "wav": + buffer = b"" + is_first_chunk = True + async for chunk in response.content.iter_any(): + if is_first_chunk: + is_first_chunk = False + buffer += chunk[88:] # size of the wav header + else: + buffer += chunk + i = 0 + while i < len(buffer) - chunk_size: + yield SynthesisResult.ChunkResult(buffer[i : i + chunk_size], False) + i += chunk_size + buffer = buffer[i:] + elif output_format == "mulaw": + async for chunk in response.content.iter_chunked(chunk_size): + yield SynthesisResult.ChunkResult(chunk, False) + await response.release() diff --git a/vocode/streaming/synthesizer/play_ht_synthesizer_v2.py b/vocode/streaming/synthesizer/play_ht_synthesizer_v2.py new file mode 100644 index 000000000..6db09ef7d --- /dev/null +++ b/vocode/streaming/synthesizer/play_ht_synthesizer_v2.py @@ -0,0 +1,300 @@ +import asyncio +import audioop +import os +from typing import AsyncGenerator, AsyncIterator, Optional + +import numpy as np +from loguru import logger +from pyht import AsyncClient +from pyht.client import CongestionCtrl, TTSOptions +from pyht.protos import api_pb2 + +from vocode.streaming.models.audio import AudioEncoding +from vocode.streaming.models.message import BaseMessage +from vocode.streaming.models.synthesizer import PlayHtSynthesizerConfig +from vocode.streaming.synthesizer.base_synthesizer import SynthesisResult +from vocode.streaming.synthesizer.play_ht_synthesizer import ( + PlayHtSynthesizer as VocodePlayHtSynthesizer, +) +from vocode.streaming.synthesizer.synthesizer_utils import split_text +from vocode.streaming.utils import generate_from_async_iter_with_lookahead, generate_with_is_last +from vocode.streaming.utils.create_task import asyncio_create_task_with_done_error_log + +PLAY_HT_ON_PREM_ADDR = os.environ.get("VOCODE_PLAYHT_ON_PREM_ADDR", None) +PLAY_HT_V2_MAX_CHARS = 200 +EXPERIMENTAL_VOICE_AMPLITUDE_THRESHOLD = 200 + + +class PlayHtSynthesizerV2(VocodePlayHtSynthesizer): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.playht_client_saas = AsyncClient( + user_id=self.user_id, + api_key=self.api_key, + ) + self.playht_client_on_prem = None + + if self.synthesizer_config.on_prem: + logger.info(f"Creating on-prem PlayHT with gRPC address {PLAY_HT_ON_PREM_ADDR}") + advanced_options = AsyncClient.AdvancedOptions( + grpc_addr=PLAY_HT_ON_PREM_ADDR, + fallback_enabled=True, + congestion_ctrl=CongestionCtrl.STATIC_MAR_2023, + ) + + self.playht_client_on_prem = AsyncClient( + user_id=self.user_id, + api_key=self.api_key, + advanced=advanced_options, + ) + + if self.synthesizer_config.audio_encoding == AudioEncoding.MULAW: + audio_format = api_pb2.FORMAT_MULAW + elif self.synthesizer_config.audio_encoding == AudioEncoding.LINEAR16: + audio_format = api_pb2.FORMAT_WAV + + sample_rate = self.synthesizer_config.sampling_rate + self.playht_options = TTSOptions( + voice=self.synthesizer_config.voice_id, + # PlayHT runs significantly slower when sampling rate is not 24KHz + # 24KHz is the default for PlayHT + sample_rate=sample_rate if sample_rate > 24000 else 24000, + speed=self.synthesizer_config.speed if self.synthesizer_config.speed else 1, + format=audio_format, + text_guidance=self.synthesizer_config.text_guidance, + voice_guidance=self.synthesizer_config.voice_guidance, + temperature=self.synthesizer_config.temperature, + top_p=self.synthesizer_config.top_p, + ) + if self.synthesizer_config.quality: + self.playht_options.quality = self.synthesizer_config.quality + + @property + def playht_client(self) -> AsyncClient: + if self.playht_client_on_prem is not None: + return self.playht_client_on_prem + return self.playht_client_saas + + async def create_speech_uncached( + self, + message: BaseMessage, + chunk_size: int, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, + ) -> SynthesisResult: + + self.total_chars += len(message.text) + chunk_queue: asyncio.Queue[Optional[bytes]] = asyncio.Queue() + asyncio_create_task_with_done_error_log( + self.get_chunks( + message, + chunk_size, + chunk_queue, + cut_leading_silence=not is_first_text_chunk + and self.synthesizer_config.experimental_remove_silence, + cut_trailing_silence=not is_sole_text_chunk + and self.synthesizer_config.experimental_remove_silence, + ), + ) + + return SynthesisResult( + self.chunk_result_generator_from_queue(chunk_queue), + lambda seconds: self.get_message_cutoff_from_voice_speed( + message, + seconds, + self.words_per_minute, + ), + ) + + def _contains_voice_experimental(self, chunk: bytes): + pcm = np.frombuffer( + ( + audioop.ulaw2lin(chunk, 2) + if self.synthesizer_config.audio_encoding == AudioEncoding.MULAW + else chunk + ), + dtype=np.int16, + ) + return np.max(np.abs(pcm)) > EXPERIMENTAL_VOICE_AMPLITUDE_THRESHOLD + + @staticmethod + def _enumerate_by_chunk_size(buffer: bytes, chunk_size: int): + for buffer_idx in range(0, len(buffer) - chunk_size, chunk_size): + yield buffer_idx, buffer[buffer_idx : buffer_idx + chunk_size] + + async def _downsample_from_24khz(self, chunk: bytes) -> bytes: + if self.synthesizer_config.audio_encoding == AudioEncoding.MULAW: + return await self._downsample_mulaw(chunk) + elif self.synthesizer_config.audio_encoding == AudioEncoding.LINEAR16: + return await self._downsample_pcm(chunk) + else: + raise Exception(f"Unsupported audio format: {self.synthesizer_config.audio_encoding}") + + async def _downsample_pcm(self, chunk: bytes) -> bytes: + downsampled_chunk, _ = audioop.ratecv( + chunk, + 2, + 1, + 24000, + self.synthesizer_config.sampling_rate, + None, + ) + + return downsampled_chunk + + async def _downsample_mulaw(self, chunk: bytes) -> bytes: + pcm_data = audioop.ulaw2lin(chunk, 2) + downsampled_pcm_data = await self._downsample_pcm(pcm_data) + downsampled_chunk = audioop.lin2ulaw(downsampled_pcm_data, 2) + return downsampled_chunk + + async def downsample_async_generator(self, async_gen: AsyncGenerator[bytes, None]): + async for play_ht_chunk in async_gen: + if self.synthesizer_config.sampling_rate >= 24000: + yield play_ht_chunk + else: + downsampled_chunk = await self._downsample_from_24khz(play_ht_chunk) + yield downsampled_chunk + + async def _cut_leading_trailing_silence( + self, + async_iter: AsyncIterator[bytes], + chunk_size: int, + cut_leading_silence: bool = True, + cut_trailing_silence: bool = True, + ) -> AsyncGenerator[bytes, None]: + buffer: bytearray = bytearray() + + async def generate_chunks( + play_ht_chunk: bytes, + cut_leading_silence=False, + ) -> AsyncGenerator[bytes, None]: + """Yields chunks of size chunk_size from play_ht_chunk and leaves the remainder in buffer. + + If cut_leading_silence is True, does not yield chunks until it detects voice. + """ + nonlocal buffer + + buffer.extend(play_ht_chunk) + detected_voice = False + for buffer_idx, chunk in self._enumerate_by_chunk_size(buffer, chunk_size): + if cut_leading_silence and not detected_voice: + if self._contains_voice_experimental(chunk): + detected_voice = True + yield chunk + if detected_voice: + logger.debug(f"Cut off {buffer_idx} bytes of leading silence") + else: + yield chunk + buffer = buffer[len(buffer) - (len(buffer) % chunk_size) :] + + async def _cut_out_trailing_silence( + trailing_chunk: bytes, + ) -> AsyncGenerator[bytes, None]: + """Yields chunks of size chunk_size from trailing_chunk until it detects silence.""" + for buffer_idx, chunk in self._enumerate_by_chunk_size(trailing_chunk, chunk_size): + if not self._contains_voice_experimental(chunk): + logger.debug( + f"Cutting off {len(trailing_chunk) - buffer_idx} bytes of trailing silence", + ) + break + yield chunk + + # Yield from the first audio chunk, no matter what, for latency + try: + play_ht_chunk = await async_iter.__anext__() + except StopAsyncIteration: + return + + async for chunk in generate_chunks(play_ht_chunk, cut_leading_silence=cut_leading_silence): + yield chunk + + async for lookahead_buffer, is_last in generate_with_is_last( + generate_from_async_iter_with_lookahead(async_iter, 2), + ): + if not is_last: + async for chunk in generate_chunks(lookahead_buffer[0]): + yield chunk + else: + trailing_chunk = b"".join(lookahead_buffer) + async for chunk in ( + _cut_out_trailing_silence(trailing_chunk) + if cut_trailing_silence + else generate_chunks(trailing_chunk) + ): + yield chunk + + async def get_chunks( + self, + message: BaseMessage, + chunk_size: int, + chunk_queue: asyncio.Queue[Optional[bytes]], + cut_leading_silence: bool, + cut_trailing_silence: bool, + ): + buffer = bytearray() + try: + playht_bytes_generators = [ + self.playht_client.tts( + text, + self.playht_options, + ) + for text in split_text( + string_to_split=message.text, + max_text_length=PLAY_HT_V2_MAX_CHARS, + ) + ] + downsampled_generators = [ + self.downsample_async_generator(gen) for gen in playht_bytes_generators + ] + + for async_gen in downsampled_generators: + async_iter = async_gen.__aiter__() + if ( + self.synthesizer_config.audio_encoding == AudioEncoding.LINEAR16 + ): # skip the first chunk, which contains wav header + await async_iter.__anext__() + if not cut_trailing_silence and not cut_leading_silence: + while True: + try: + play_ht_chunk = await async_iter.__anext__() + except StopAsyncIteration: + break + + buffer.extend(play_ht_chunk) + for _, chunk in self._enumerate_by_chunk_size(buffer, chunk_size): + chunk_queue.put_nowait(chunk) + buffer = buffer[len(buffer) - (len(buffer) % chunk_size) :] + if len(buffer) > 0: + chunk_queue.put_nowait(buffer) + else: + async for chunk in self._cut_leading_trailing_silence( + async_iter, + chunk_size, + cut_leading_silence=cut_leading_silence, + cut_trailing_silence=cut_trailing_silence, + ): + chunk_queue.put_nowait(chunk) + except asyncio.CancelledError: + pass + finally: + chunk_queue.put_nowait(None) # treated as sentinel + + @classmethod + def get_voice_identifier(cls, synthesizer_config: PlayHtSynthesizerConfig): + return ":".join( + ( + "play_ht_v2", + synthesizer_config.voice_id, + str(synthesizer_config.user_id), + str(synthesizer_config.speed), + str(synthesizer_config.seed), + str(synthesizer_config.temperature), + synthesizer_config.audio_encoding, + ), + ) + + async def tear_down(self): + await self.playht_client.close() + await super().tear_down() diff --git a/vocode/streaming/synthesizer/polly_synthesizer.py b/vocode/streaming/synthesizer/polly_synthesizer.py index da7bfc614..4f36cd905 100644 --- a/vocode/streaming/synthesizer/polly_synthesizer.py +++ b/vocode/streaming/synthesizer/polly_synthesizer.py @@ -1,32 +1,25 @@ import asyncio -from concurrent.futures import ThreadPoolExecutor -import logging -from typing import Any, Optional -import aiohttp import json +from concurrent.futures import ThreadPoolExecutor +from typing import Any + +import boto3 -from vocode.streaming.agent.bot_sentiment_analyser import BotSentiment from vocode.streaming.models.message import BaseMessage +from vocode.streaming.models.synthesizer import PollySynthesizerConfig from vocode.streaming.synthesizer.base_synthesizer import ( BaseSynthesizer, SynthesisResult, - tracer, encode_as_wav, ) -from vocode.streaming.models.synthesizer import PollySynthesizerConfig, SynthesizerType -from vocode.streaming.utils.mp3_helper import decode_mp3 - -import boto3 class PollySynthesizer(BaseSynthesizer[PollySynthesizerConfig]): def __init__( self, synthesizer_config: PollySynthesizerConfig, - logger: Optional[logging.Logger] = None, - aiohttp_session: Optional[aiohttp.ClientSession] = None, ): - super().__init__(synthesizer_config, aiohttp_session) + super().__init__(synthesizer_config) client = boto3.client("polly") @@ -83,11 +76,9 @@ async def create_speech( self, message: BaseMessage, chunk_size: int, - bot_sentiment: Optional[BotSentiment] = None, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, ) -> SynthesisResult: - create_speech_span = tracer.start_span( - f"synthesizer.{SynthesizerType.POLLY.value.split('_', 1)[-1]}.create_total", - ) audio_response = await asyncio.get_event_loop().run_in_executor( self.thread_pool_executor, self.synthesize, message.text ) @@ -102,8 +93,6 @@ async def create_speech( if v ] - create_speech_span.end() - async def chunk_generator(audio_data_stream, chunk_transform=lambda x: x): audio_buffer = await asyncio.get_event_loop().run_in_executor( self.thread_pool_executor, diff --git a/vocode/streaming/synthesizer/rime_synthesizer.py b/vocode/streaming/synthesizer/rime_synthesizer.py index 0d103d041..acb77480c 100644 --- a/vocode/streaming/synthesizer/rime_synthesizer.py +++ b/vocode/streaming/synthesizer/rime_synthesizer.py @@ -1,81 +1,171 @@ +import asyncio import audioop -import logging -import aiohttp -from pydub import AudioSegment import base64 +import io +import json +from typing import Optional + +import aiohttp +from loguru import logger + from vocode import getenv -from vocode.streaming.agent.bot_sentiment_analyser import BotSentiment -from vocode.streaming.models.audio_encoding import AudioEncoding +from vocode.streaming.models.audio import AudioEncoding from vocode.streaming.models.message import BaseMessage - -from vocode.streaming.synthesizer.base_synthesizer import ( - BaseSynthesizer, - SynthesisResult, - encode_as_wav, - tracer, +from vocode.streaming.models.synthesizer import ( + RIME_DEFAULT_REDUCE_LATENCY, + RIME_DEFAULT_SPEED_ALPHA, + RimeSynthesizerConfig, ) +from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer, SynthesisResult -from typing import Any, Optional -import io -import requests - -from vocode.streaming.models.synthesizer import RimeSynthesizerConfig, SynthesizerType - -from opentelemetry.context.context import Context +# TODO: [OSS] Remove call to internal library with Synthesizers refactor # https://rime.ai/docs/quickstart +WAV_HEADER_LENGTH = 44 + class RimeSynthesizer(BaseSynthesizer[RimeSynthesizerConfig]): def __init__( self, synthesizer_config: RimeSynthesizerConfig, - logger: Optional[logging.Logger] = None, - aiohttp_session: Optional[aiohttp.ClientSession] = None, ): - super().__init__(synthesizer_config, aiohttp_session) - self.api_key = getenv("RIME_API_KEY") + super().__init__(synthesizer_config) + + self.base_url = synthesizer_config.base_url + self.model_id = synthesizer_config.model_id self.speaker = synthesizer_config.speaker + self.speed_alpha = synthesizer_config.speed_alpha self.sampling_rate = synthesizer_config.sampling_rate - self.base_url = synthesizer_config.base_url + self.reduce_latency = synthesizer_config.reduce_latency + self.api_key = f"Bearer {getenv('RIME_API_KEY')}" - async def create_speech( + @classmethod + def get_voice_identifier(cls, synthesizer_config: RimeSynthesizerConfig): + return ":".join( + ( + "rime", + synthesizer_config.speaker, + str(synthesizer_config.speed_alpha), + synthesizer_config.audio_encoding, + ) + ) + + async def create_speech_uncached( self, message: BaseMessage, chunk_size: int, - bot_sentiment: Optional[BotSentiment] = None, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, ) -> SynthesisResult: + self.total_chars += len(message.text) headers = { - "Authorization": f"Bearer {self.api_key}", + "Authorization": self.api_key, "Content-Type": "application/json", } + body = self.get_request_body(message.text) + + async with self.async_requestor.get_session().post( + self.base_url, + headers=headers, + json=body, + timeout=aiohttp.ClientTimeout(total=15), + ) as response: + if not response.ok: + raise Exception(f"Rime API error: {response.status}, {await response.text()}") + data = json.loads(await response.text()) + + audio_content = data.get("audioContent") + output_bytes = base64.b64decode(audio_content)[WAV_HEADER_LENGTH:] + + if self.synthesizer_config.audio_encoding == AudioEncoding.MULAW: + output_bytes = audioop.lin2ulaw(output_bytes, 2) + + return SynthesisResult( + self._chunk_generator(output_bytes, chunk_size), + lambda seconds: self.get_message_cutoff_from_total_response_length( + self.synthesizer_config, message, seconds, len(output_bytes) + ), + ) + + @staticmethod + async def _chunk_generator(output_bytes, chunk_size): + for i in range(0, len(output_bytes), chunk_size): + if i + chunk_size > len(output_bytes): + yield SynthesisResult.ChunkResult(output_bytes[i:], True) + else: + yield SynthesisResult.ChunkResult(output_bytes[i : i + chunk_size], False) + + async def get_chunks( + self, + headers: dict, + body: dict, + chunk_size: int, + chunk_queue: asyncio.Queue[Optional[bytes]], + ): + try: + async_client = self.async_requestor.get_client() + stream = await async_client.send( + async_client.build_request( + "POST", + self.base_url, + headers=headers, + json=body, + ), + stream=True, + ) + if not stream.is_success: + error = await stream.aread() + logger.error(f"Rime API failed: {stream.status_code} {error.decode('utf-8')}") + raise Exception(f"Rime API returned {stream.status_code} status code") + async for chunk in stream.aiter_bytes(chunk_size): + chunk_queue.put_nowait(chunk) + except asyncio.CancelledError: + pass + finally: + chunk_queue.put_nowait(None) # treated as sentinel + + def get_request_body(self, text): + speed_alpha = self.speed_alpha if self.speed_alpha else RIME_DEFAULT_SPEED_ALPHA + reduce_latency = self.reduce_latency if self.reduce_latency else RIME_DEFAULT_REDUCE_LATENCY + body = { - "text": message.text, + "text": text, "speaker": self.speaker, "samplingRate": self.sampling_rate, + "speedAlpha": speed_alpha, + "reduceLatency": reduce_latency, } - if self.synthesizer_config.speed_alpha is not None: - body["speedAlpha"] = self.synthesizer_config.speed_alpha - create_speech_span = tracer.start_span( - f"synthesizer.{SynthesizerType.RIME.value.split('_', 1)[-1]}.create_total", - ) - async with self.aiohttp_session.post( + if self.model_id: + body["modelId"] = self.model_id + + return body + + async def create_speech( + self, + message: BaseMessage, + chunk_size: int, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, + ) -> SynthesisResult: + headers = { + "Authorization": self.api_key, + "Content-Type": "application/json", + } + + body = self.get_request_body(message.text) + + async with self.async_requestor.get_session().post( self.base_url, headers=headers, json=body, timeout=aiohttp.ClientTimeout(total=15), ) as response: if not response.ok: - raise Exception( - f"Rime API error: {response.status}, {await response.text()}" - ) + raise Exception(f"Rime API error: {response.status}, {await response.text()}") data = await response.json() - create_speech_span.end() - convert_span = tracer.start_span( - f"synthesizer.{SynthesizerType.RIME.value.split('_', 1)[-1]}.convert", - ) audio_file = io.BytesIO(base64.b64decode(data.get("audioContent"))) @@ -85,5 +175,5 @@ async def create_speech( message=message, chunk_size=chunk_size, ) - convert_span.end() + return result diff --git a/vocode/streaming/synthesizer/stream_elements_synthesizer.py b/vocode/streaming/synthesizer/stream_elements_synthesizer.py index b3a627b45..3d656f5cc 100644 --- a/vocode/streaming/synthesizer/stream_elements_synthesizer.py +++ b/vocode/streaming/synthesizer/stream_elements_synthesizer.py @@ -1,23 +1,11 @@ import io + import aiohttp from pydub import AudioSegment -import logging -from typing import Optional -import requests -from vocode.streaming.agent.bot_sentiment_analyser import BotSentiment from vocode.streaming.models.message import BaseMessage -from vocode.streaming.models.synthesizer import ( - StreamElementsSynthesizerConfig, - SynthesizerType, -) -from vocode.streaming.synthesizer.base_synthesizer import ( - BaseSynthesizer, - SynthesisResult, - tracer, -) - -from opentelemetry.context.context import Context +from vocode.streaming.models.synthesizer import StreamElementsSynthesizerConfig +from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer, SynthesisResult class StreamElementsSynthesizer(BaseSynthesizer[StreamElementsSynthesizerConfig]): @@ -26,35 +14,27 @@ class StreamElementsSynthesizer(BaseSynthesizer[StreamElementsSynthesizerConfig] def __init__( self, synthesizer_config: StreamElementsSynthesizerConfig, - logger: Optional[logging.Logger] = None, - aiohttp_session: Optional[aiohttp.ClientSession] = None, ): - super().__init__(synthesizer_config, aiohttp_session) + super().__init__(synthesizer_config) self.voice = synthesizer_config.voice async def create_speech( self, message: BaseMessage, chunk_size: int, - bot_sentiment: Optional[BotSentiment] = None, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, ) -> SynthesisResult: url_params = { "voice": self.voice, "text": message.text, } - create_speech_span = tracer.start_span( - f"synthesizer.{SynthesizerType.STREAM_ELEMENTS.value.split('_', 1)[-1]}.create_total", - ) - async with self.aiohttp_session.get( + async with self.async_requestor.get_session().get( self.TTS_ENDPOINT, params=url_params, timeout=aiohttp.ClientTimeout(total=15), ) as response: read_response = await response.read() - create_speech_span.end() - convert_span = tracer.start_span( - f"synthesizer.{SynthesizerType.STREAM_ELEMENTS.value.split('_', 1)[-1]}.convert", - ) # TODO: probably needs to be in a thread audio_segment: AudioSegment = AudioSegment.from_mp3( @@ -69,5 +49,5 @@ async def create_speech( message=message, chunk_size=chunk_size, ) - convert_span.end() + return result diff --git a/vocode/streaming/synthesizer/synthesizer_utils.py b/vocode/streaming/synthesizer/synthesizer_utils.py new file mode 100644 index 000000000..ac69633ad --- /dev/null +++ b/vocode/streaming/synthesizer/synthesizer_utils.py @@ -0,0 +1,50 @@ +from typing import List + + +def split_text(string_to_split: str, max_text_length: int) -> List[str]: + # Base case: if the string_to_split is less than or equal to max_text_length characters, return it as a single element array + if len(string_to_split) <= max_text_length: + return [string_to_split.strip()] + + # Recursive case: find the index of the last sentence ender in the first max_text_length characters of the string_to_split + sentence_enders = [".", "!", "?"] + index = -1 + for ender in sentence_enders: + i = string_to_split[:max_text_length].rfind(ender) + if i > index: + index = i + + # If there is a sentence ender, split the string_to_split at that index plus one and strip any spaces from both parts + if index != -1: + first_part = string_to_split[: index + 1].strip() + second_part = string_to_split[index + 1 :].strip() + + # If there is no sentence ender, find the index of the last comma in the first max_text_length characters of the string_to_split + else: + index = string_to_split[:max_text_length].rfind(",") + # If there is a comma, split the string_to_split at that index plus one and strip any spaces from both parts + if index != -1: + first_part = string_to_split[: index + 1].strip() + second_part = string_to_split[index + 1 :].strip() + # If there is no comma, find the index of the last space in the first max_text_length characters of the string_to_split + else: + index = string_to_split[:max_text_length].rfind(" ") + # If there is a space, split the string_to_split at that index and strip any spaces from both parts + if index != -1: + first_part = string_to_split[:index].strip() + second_part = string_to_split[index:].strip() + + # If there is no space, split the string_to_split at max_text_length characters and strip any spaces from both parts + else: + first_part = string_to_split[:max_text_length].strip() + second_part = string_to_split[max_text_length:].strip() + + # Append the first part to the result array + result = [first_part] + + # Call the function recursively on the remaining part of the string_to_split and extend the result array with it, unless it is empty + if second_part != "": + result.extend(split_text(string_to_split=second_part, max_text_length=max_text_length)) + + # Return the result array + return result diff --git a/vocode/streaming/telephony/client/abstract_telephony_client.py b/vocode/streaming/telephony/client/abstract_telephony_client.py new file mode 100644 index 000000000..2cdf92b84 --- /dev/null +++ b/vocode/streaming/telephony/client/abstract_telephony_client.py @@ -0,0 +1,29 @@ +from abc import ABC, abstractmethod +from typing import Dict, Optional + +from vocode.streaming.models.telephony import TelephonyProviderConfig + + +class AbstractTelephonyClient(ABC): + def __init__(self, base_url: str): + self.base_url = base_url + + @abstractmethod + def get_telephony_config(self) -> TelephonyProviderConfig: + pass + + @abstractmethod + async def create_call( + self, + conversation_id: str, + to_phone: str, + from_phone: str, + record: bool = False, + digits: Optional[str] = None, + telephony_params: Optional[Dict[str, str]] = None, + ) -> str: # returns identifier of the call on the telephony provider + pass + + @abstractmethod + async def end_call(self, id) -> bool: + raise NotImplementedError diff --git a/vocode/streaming/telephony/client/base_telephony_client.py b/vocode/streaming/telephony/client/base_telephony_client.py deleted file mode 100644 index 157e6e9e5..000000000 --- a/vocode/streaming/telephony/client/base_telephony_client.py +++ /dev/null @@ -1,32 +0,0 @@ -from typing import Optional - -from vocode.streaming.models.telephony import BaseCallConfig - - -class BaseTelephonyClient: - def __init__(self, base_url): - self.base_url = base_url - - def get_telephony_config(self): - raise NotImplementedError - - async def create_call( - self, - conversation_id: str, - to_phone: str, - from_phone: str, - record: bool = False, - digits: Optional[str] = None, - ) -> str: # identifier of the call on the telephony provider - raise NotImplementedError - - async def end_call(self, id) -> bool: - raise NotImplementedError - - def validate_outbound_call( - self, - to_phone: str, - from_phone: str, - mobile_only: bool = True, - ): - raise NotImplementedError diff --git a/vocode/streaming/telephony/client/twilio_client.py b/vocode/streaming/telephony/client/twilio_client.py index 7325a2f87..254318cf9 100644 --- a/vocode/streaming/telephony/client/twilio_client.py +++ b/vocode/streaming/telephony/client/twilio_client.py @@ -1,25 +1,34 @@ -from typing import Optional -from twilio.rest import Client +import os +from typing import Dict, Optional -from vocode.streaming.models.telephony import BaseCallConfig, TwilioConfig -from vocode.streaming.telephony.client.base_telephony_client import BaseTelephonyClient -from vocode.streaming.telephony.templater import Templater +import aiohttp +from loguru import logger +from vocode.streaming.models.telephony import TwilioConfig +from vocode.streaming.telephony.client.abstract_telephony_client import AbstractTelephonyClient +from vocode.streaming.telephony.templater import get_connection_twiml +from vocode.streaming.utils.async_requester import AsyncRequestor -class TwilioClient(BaseTelephonyClient): - def __init__(self, base_url: str, twilio_config: TwilioConfig): - super().__init__(base_url) - self.twilio_config = twilio_config - # TODO: this is blocking - self.twilio_client = Client(twilio_config.account_sid, twilio_config.auth_token) - try: - # Test credentials - self.twilio_client.api.accounts(twilio_config.account_sid).fetch() - except Exception as e: - raise RuntimeError( - "Could not create Twilio client. Invalid credentials" - ) from e - self.templater = Templater() + +class TwilioBadRequestException(ValueError): + pass + + +class TwilioClient(AbstractTelephonyClient): + def __init__( + self, + base_url: str, + maybe_twilio_config: Optional[TwilioConfig] = None, + ): + self.twilio_config = maybe_twilio_config or TwilioConfig( + account_sid=os.environ["TWILIO_ACCOUNT_SID"], + auth_token=os.environ["TWILIO_AUTH_TOKEN"], + ) + self.auth = aiohttp.BasicAuth( + login=self.twilio_config.account_sid, + password=self.twilio_config.auth_token, + ) + super().__init__(base_url=base_url) def get_telephony_config(self): return self.twilio_config @@ -29,48 +38,49 @@ async def create_call( conversation_id: str, to_phone: str, from_phone: str, - record: bool = False, - digits: Optional[str] = None, + record: bool = False, # currently no-op + digits: Optional[str] = None, # currently no-op + telephony_params: Optional[Dict[str, str]] = None, ) -> str: - # TODO: Make this async. This is blocking. - twiml = self.get_connection_twiml(conversation_id=conversation_id) - twilio_call = self.twilio_client.calls.create( - twiml=twiml.body.decode("utf-8"), - to=to_phone, - from_=from_phone, - send_digits=digits, - record=record, - **self.get_telephony_config().extra_params, - ) - return twilio_call.sid + data = { + "Twiml": self.get_connection_twiml(conversation_id=conversation_id).body.decode( + "utf-8" + ), + "To": f"+{to_phone}", + "From": f"+{from_phone}", + **(telephony_params or {}), + } + if digits: + data["SendDigits"] = digits + async with AsyncRequestor().get_session().post( + f"https://api.twilio.com/2010-04-01/Accounts/{self.twilio_config.account_sid}/Calls.json", + auth=self.auth, + data=data, + ) as response: + if not response.ok: + if response.status == 400: + logger.error( + f"Failed to create call: {response.status} {response.reason} {await response.json()}" + ) + raise TwilioBadRequestException( + "Telephony provider rejected call; this is usually due to a bad/malformed number. " + "If this persists, and you're sure that the number is well-formed, " + "please contact us." + ) + raise RuntimeError(f"Failed to create call: {response.status} {response.reason}") + response = await response.json() + return response["sid"] def get_connection_twiml(self, conversation_id: str): - return self.templater.get_connection_twiml( - base_url=self.base_url, call_id=conversation_id - ) + return get_connection_twiml(call_id=conversation_id, base_url=self.base_url) async def end_call(self, twilio_sid): - # TODO: Make this async. This is blocking. - response = self.twilio_client.calls(twilio_sid).update(status="completed") - return response.status == "completed" - - def validate_outbound_call( - self, - to_phone: str, - from_phone: str, - mobile_only: bool = True, - ): - if len(to_phone) < 8: - raise ValueError("Invalid 'to' phone") - - if not mobile_only: - return - line_type_intelligence = ( - self.twilio_client.lookups.v2.phone_numbers(to_phone) - .fetch(fields="line_type_intelligence") - .line_type_intelligence - ) - if not line_type_intelligence or ( - line_type_intelligence and line_type_intelligence["type"] != "mobile" - ): - raise ValueError("Can only call mobile phones") + async with AsyncRequestor().get_session().post( + f"https://api.twilio.com/2010-04-01/Accounts/{self.twilio_config.account_sid}/Calls/{twilio_sid}.json", + auth=self.auth, + data={"Status": "completed"}, + ) as response: + if not response.ok: + raise RuntimeError(f"Failed to end call: {response.status} {response.reason}") + response = await response.json() + return response["status"] == "completed" diff --git a/vocode/streaming/telephony/client/vonage_client.py b/vocode/streaming/telephony/client/vonage_client.py index d7582a149..3a7e76a06 100644 --- a/vocode/streaming/telephony/client/vonage_client.py +++ b/vocode/streaming/telephony/client/vonage_client.py @@ -1,69 +1,46 @@ +import os from typing import Any, Dict, List, Optional -import aiohttp -from vocode.streaming.models.telephony import VonageConfig -from vocode.streaming.telephony.client.base_telephony_client import BaseTelephonyClient + import vonage +from vocode.streaming.models.telephony import VonageConfig +from vocode.streaming.telephony.client.abstract_telephony_client import AbstractTelephonyClient from vocode.streaming.telephony.constants import VONAGE_CONTENT_TYPE +from vocode.streaming.utils.async_requester import AsyncRequestor + + +class VonageBadRequestException(ValueError): + pass -class VonageClient(BaseTelephonyClient): +class VonageClient(AbstractTelephonyClient): def __init__( self, - base_url, - vonage_config: VonageConfig, - aiohttp_session: Optional[aiohttp.ClientSession] = None, + base_url: str, + maybe_vonage_config: Optional[VonageConfig] = None, + record_calls: bool = False, ): - super().__init__(base_url) - self.vonage_config = vonage_config + super().__init__( + base_url=base_url, + ) + self.vonage_config = maybe_vonage_config or VonageConfig( + api_key=os.environ["VONAGE_API_KEY"], + api_secret=os.environ["VONAGE_API_SECRET"], + application_id=os.environ["VONAGE_APPLICATION_ID"], + private_key=os.environ["VONAGE_PRIVATE_KEY"], + record=record_calls, + ) + # Vonage's sync client: only used for authentication helpers self.client = vonage.Client( - key=vonage_config.api_key, - secret=vonage_config.api_secret, - application_id=vonage_config.application_id, - private_key=vonage_config.private_key, + key=self.vonage_config.api_key, + secret=self.vonage_config.api_secret, + application_id=self.vonage_config.application_id, + private_key=self.vonage_config.private_key, ) - self.voice = vonage.Voice(self.client) - self.maybe_aiohttp_session = aiohttp_session def get_telephony_config(self): return self.vonage_config - async def create_vonage_call( - self, - to_phone: str, - from_phone: str, - ncco: str, - digits: Optional[str] = None, - event_urls: List[str] = [], - **kwargs, - ) -> str: # returns the Vonage UUID - aiohttp_session = self.maybe_aiohttp_session or aiohttp.ClientSession() - vonage_call_uuid: str - async with aiohttp_session.post( - f"https://api.nexmo.com/v1/calls", - json={ - "to": [{"type": "phone", "number": to_phone, "dtmfAnswer": digits}], - "from": {"type": "phone", "number": from_phone}, - "ncco": ncco, - "event_url": event_urls, - **kwargs, - }, - headers={ - "Authorization": f"Bearer {self.client._generate_application_jwt().decode()}" - }, - ) as response: - if not response.ok: - raise RuntimeError( - f"Failed to start call: {response.status} {response.reason}" - ) - data = await response.json() - if not data["status"] == "started": - raise RuntimeError(f"Failed to start call: {response}") - vonage_call_uuid = data["uuid"] - if not self.maybe_aiohttp_session: - await aiohttp_session.close() - return vonage_call_uuid - async def create_call( self, conversation_id: str, @@ -71,63 +48,106 @@ async def create_call( from_phone: str, record: bool = False, digits: Optional[str] = None, + telephony_params: Optional[Dict[str, str]] = None, ) -> str: # identifier of the call on the telephony provider - return await self.create_vonage_call( + return await self._create_vonage_call( to_phone, from_phone, self.create_call_ncco( - self.base_url, conversation_id, record, is_outbound=True + conversation_id=conversation_id, + record=record, + is_outbound=True, ), digits, + event_urls=[], ) - @staticmethod - def create_call_ncco(base_url, conversation_id, record, is_outbound: bool = False): + async def end_call(self, id) -> bool: + async with AsyncRequestor().get_session().put( + f"https://api.nexmo.com/v1/calls/{id}", + json={"action": "hangup"}, + headers={"Authorization": f"Bearer {self.client._generate_application_jwt().decode()}"}, + ) as response: + if not response.ok: + raise RuntimeError(f"Failed to end call: {response.status} {response.reason}") + return True + + async def update_call(self, vonage_uuid, new_ncco): + async with AsyncRequestor().get_session().put( + f"https://api.nexmo.com/v1/calls/{vonage_uuid}", + json={ + "action": "transfer", + "destination": {"type": "ncco", "ncco": new_ncco}, + }, + headers={"Authorization": self.client._create_jwt_auth_string().decode()}, + ) as response: + if not response.ok: + raise RuntimeError(f"Failed to update call: {response.status} {response.reason}") + return True + + def create_call_ncco( + self, + conversation_id, + record, # currently no-op + is_outbound: bool = False, + ): ncco: List[Dict[str, Any]] = [] - if record: - ncco.append( - { - "action": "record", - "eventUrl": [f"https://{base_url}/recordings/{conversation_id}"], - } - ) ncco.append( { "action": "connect", "endpoint": [ { "type": "websocket", - "uri": f"wss://{base_url}/connect_call/{conversation_id}", + "uri": f"wss://{self.base_url}/connect_call/{conversation_id}", "content-type": VONAGE_CONTENT_TYPE, "headers": {}, } ], - } + }, ) return ncco - async def end_call(self, id) -> bool: - aiohttp_session = self.maybe_aiohttp_session or aiohttp.ClientSession() - async with aiohttp_session.put( - f"https://api.nexmo.com/v1/calls/{id}", - json={"action": "hangup"}, - headers={ - "Authorization": f"Bearer {self.client._generate_application_jwt().decode()}" + async def _create_vonage_call( + self, + to_phone: str, + from_phone: str, + ncco: str, + digits: Optional[str] = None, + event_urls: List[str] = [], + **kwargs, + ) -> str: # returns the Vonage UUID + vonage_call_uuid: str + async with AsyncRequestor().get_session().post( + "https://api.nexmo.com/v1/calls", + json={ + "to": [{"type": "phone", "number": to_phone, "dtmfAnswer": digits}], + "from": {"type": "phone", "number": from_phone}, + "ncco": ncco, + "event_url": event_urls, + **kwargs, }, + headers={"Authorization": f"Bearer {self.client._generate_application_jwt().decode()}"}, ) as response: if not response.ok: - raise RuntimeError( - f"Failed to end call: {response.status} {response.reason}" - ) - if not self.maybe_aiohttp_session: - await aiohttp_session.close() - return True + if response.status == 400: + raise VonageBadRequestException( + "Failed to start call; this is usually due to a bad/malformed number. " + "If this persists, and you're sure that the number is well-formed, " + "please contact us." + ) + raise RuntimeError(f"Failed to start call: {response.status} {response.reason}") + data = await response.json() + if not data["status"] == "started": + raise RuntimeError(f"Failed to start call: {response}") + vonage_call_uuid = data["uuid"] + return vonage_call_uuid - # TODO(EPD-186) - def validate_outbound_call( - self, - to_phone: str, - from_phone: str, - mobile_only: bool = True, - ): - pass + async def send_dtmf(self, vonage_uuid: str, digits: str): + async with AsyncRequestor().get_session().put( + f"https://api.nexmo.com/v1/calls/{vonage_uuid}/dtmf", + json={"digits": digits}, + headers={"Authorization": self.client._create_jwt_auth_string().decode()}, + ) as response: + if not response.ok: + raise RuntimeError(f"Failed to send DTMF: {response.status} {response.reason}") + await response.json() diff --git a/vocode/streaming/telephony/config_manager/in_memory_config_manager.py b/vocode/streaming/telephony/config_manager/in_memory_config_manager.py index 09d8ba94f..d71b9a351 100644 --- a/vocode/streaming/telephony/config_manager/in_memory_config_manager.py +++ b/vocode/streaming/telephony/config_manager/in_memory_config_manager.py @@ -1,8 +1,7 @@ from typing import Optional + from vocode.streaming.models.telephony import BaseCallConfig -from vocode.streaming.telephony.config_manager.base_config_manager import ( - BaseConfigManager, -) +from vocode.streaming.telephony.config_manager.base_config_manager import BaseConfigManager class InMemoryConfigManager(BaseConfigManager): diff --git a/vocode/streaming/telephony/config_manager/redis_config_manager.py b/vocode/streaming/telephony/config_manager/redis_config_manager.py index af3d9a2fb..33f4aabcf 100644 --- a/vocode/streaming/telephony/config_manager/redis_config_manager.py +++ b/vocode/streaming/telephony/config_manager/redis_config_manager.py @@ -1,37 +1,32 @@ -import logging -import os from typing import Optional -from redis.asyncio import Redis + +from loguru import logger +from redis import Redis from vocode.streaming.models.telephony import BaseCallConfig -from vocode.streaming.telephony.config_manager.base_config_manager import ( - BaseConfigManager, -) +from vocode.streaming.telephony.config_manager.base_config_manager import BaseConfigManager +from vocode.streaming.utils.redis import initialize_redis class RedisConfigManager(BaseConfigManager): - def __init__(self, logger: Optional[logging.Logger] = None): - self.redis: Redis = Redis( - host=os.environ.get("REDISHOST", "localhost"), - port=int(os.environ.get("REDISPORT", 6379)), - username=os.environ.get("REDISUSER", None), - password=os.environ.get("REDISPASSWORD", None), - db=0, - decode_responses=True, - ) - self.logger = logger or logging.getLogger(__name__) + def __init__(self): + self.redis: Redis = initialize_redis() + + async def _set_with_one_day_expiration(self, *args, **kwargs): + ONE_DAY_SECONDS = 60 * 60 * 24 + return await self.redis.set(*args, **{**kwargs, "ex": ONE_DAY_SECONDS}) async def save_config(self, conversation_id: str, config: BaseCallConfig): - self.logger.debug(f"Saving config for {conversation_id}") - await self.redis.set(conversation_id, config.json()) + logger.debug(f"Saving config for {conversation_id}") + await self._set_with_one_day_expiration(conversation_id, config.json()) async def get_config(self, conversation_id) -> Optional[BaseCallConfig]: - self.logger.debug(f"Getting config for {conversation_id}") - raw_config = await self.redis.get(conversation_id) + logger.debug(f"Getting config for {conversation_id}") + raw_config = await self.redis.get(conversation_id) # type: ignore if raw_config: return BaseCallConfig.parse_raw(raw_config) return None async def delete_config(self, conversation_id): - self.logger.debug(f"Deleting config for {conversation_id}") + logger.debug(f"Deleting config for {conversation_id}") await self.redis.delete(conversation_id) diff --git a/vocode/streaming/telephony/constants.py b/vocode/streaming/telephony/constants.py index c9647357f..889971bbf 100644 --- a/vocode/streaming/telephony/constants.py +++ b/vocode/streaming/telephony/constants.py @@ -1,11 +1,13 @@ -from vocode.streaming.models.audio_encoding import AudioEncoding +from vocode.streaming.models.audio import AudioEncoding, SamplingRate # TODO(EPD-186): namespace as Twilio -DEFAULT_SAMPLING_RATE = 8000 +DEFAULT_SAMPLING_RATE = SamplingRate.RATE_8000 DEFAULT_AUDIO_ENCODING = AudioEncoding.MULAW DEFAULT_CHUNK_SIZE = 20 * 160 +MULAW_SILENCE_BYTE = b"\xff" -VONAGE_SAMPLING_RATE = 16000 +VONAGE_SAMPLING_RATE = SamplingRate.RATE_16000 VONAGE_AUDIO_ENCODING = AudioEncoding.LINEAR16 VONAGE_CHUNK_SIZE = 640 # 20ms at 16kHz with 16bit samples VONAGE_CONTENT_TYPE = "audio/l16;rate=16000" +PCM_SILENCE_BYTE = b"\x00" diff --git a/vocode/streaming/telephony/conversation/abstract_phone_conversation.py b/vocode/streaming/telephony/conversation/abstract_phone_conversation.py new file mode 100644 index 000000000..308919a40 --- /dev/null +++ b/vocode/streaming/telephony/conversation/abstract_phone_conversation.py @@ -0,0 +1,90 @@ +from abc import abstractmethod +from typing import Literal, Optional, TypeVar, Union + +from fastapi import WebSocket +from loguru import logger + +from vocode import conversation_id as ctx_conversation_id +from vocode.streaming.agent.abstract_factory import AbstractAgentFactory +from vocode.streaming.models.agent import AgentConfig +from vocode.streaming.models.events import PhoneCallEndedEvent +from vocode.streaming.models.synthesizer import SynthesizerConfig +from vocode.streaming.models.telephony import PhoneCallDirection +from vocode.streaming.models.transcriber import TranscriberConfig +from vocode.streaming.output_device.twilio_output_device import TwilioOutputDevice +from vocode.streaming.output_device.vonage_output_device import VonageOutputDevice +from vocode.streaming.streaming_conversation import StreamingConversation +from vocode.streaming.synthesizer.abstract_factory import AbstractSynthesizerFactory +from vocode.streaming.telephony.config_manager.base_config_manager import BaseConfigManager +from vocode.streaming.transcriber.abstract_factory import AbstractTranscriberFactory +from vocode.streaming.utils import create_conversation_id +from vocode.streaming.utils.events_manager import EventsManager + +TelephonyOutputDeviceType = TypeVar( + "TelephonyOutputDeviceType", bound=Union[TwilioOutputDevice, VonageOutputDevice] +) + +LOW_INTERRUPT_SENSITIVITY_THRESHOLD = 0.9 + +TelephonyProvider = Literal["twilio", "vonage"] + + +class AbstractPhoneConversation(StreamingConversation[TelephonyOutputDeviceType]): + telephony_provider: TelephonyProvider + + def __init__( + self, + direction: PhoneCallDirection, + from_phone: str, + to_phone: str, + base_url: str, + config_manager: BaseConfigManager, + output_device: TelephonyOutputDeviceType, + agent_config: AgentConfig, + transcriber_config: TranscriberConfig, + synthesizer_config: SynthesizerConfig, + agent_factory: AbstractAgentFactory, + transcriber_factory: AbstractTranscriberFactory, + synthesizer_factory: AbstractSynthesizerFactory, + conversation_id: Optional[str] = None, + events_manager: Optional[EventsManager] = None, + speed_coefficient: float = 1.0, + per_chunk_allowance_seconds: float = 0.01, + ): + conversation_id = conversation_id or create_conversation_id() + ctx_conversation_id.set(conversation_id) + + self.direction = direction + self.from_phone = from_phone + self.to_phone = to_phone + self.base_url = base_url + super().__init__( + output_device, + transcriber_factory.create_transcriber(transcriber_config), + agent_factory.create_agent(agent_config), + synthesizer_factory.create_synthesizer(synthesizer_config), + conversation_id=conversation_id, + per_chunk_allowance_seconds=per_chunk_allowance_seconds, + events_manager=events_manager, + speed_coefficient=speed_coefficient, + ) + self.transcriptions_worker = self.TranscriptionsWorker( + input_queue=self.transcriber.output_queue, + output_queue=self.agent.get_input_queue(), + conversation=self, + interruptible_event_factory=self.interruptible_event_factory, + ) + self.config_manager = config_manager + + def attach_ws(self, ws: WebSocket): + logger.debug("Trying to attach WS to outbound call") + self.output_device.ws = ws + logger.debug("Attached WS to outbound call") + + @abstractmethod + async def attach_ws_and_start(self, ws: WebSocket): + pass + + async def terminate(self): + self.events_manager.publish_event(PhoneCallEndedEvent(conversation_id=self.id)) + await super().terminate() diff --git a/vocode/streaming/telephony/conversation/call.py b/vocode/streaming/telephony/conversation/call.py deleted file mode 100644 index 37fb44273..000000000 --- a/vocode/streaming/telephony/conversation/call.py +++ /dev/null @@ -1,83 +0,0 @@ -from fastapi import WebSocket -from enum import Enum -import logging -from typing import Optional, TypeVar, Union -from vocode.streaming.agent.factory import AgentFactory -from vocode.streaming.models.agent import AgentConfig -from vocode.streaming.models.events import PhoneCallEndedEvent -from vocode.streaming.output_device.vonage_output_device import VonageOutputDevice - -from vocode.streaming.streaming_conversation import StreamingConversation -from vocode.streaming.output_device.twilio_output_device import TwilioOutputDevice -from vocode.streaming.models.synthesizer import ( - SynthesizerConfig, -) -from vocode.streaming.models.transcriber import ( - TranscriberConfig, -) -from vocode.streaming.synthesizer.factory import SynthesizerFactory -from vocode.streaming.telephony.config_manager.base_config_manager import ( - BaseConfigManager, -) -from vocode.streaming.telephony.constants import DEFAULT_SAMPLING_RATE -from vocode.streaming.streaming_conversation import StreamingConversation -from vocode.streaming.transcriber.factory import TranscriberFactory -from vocode.streaming.utils.events_manager import EventsManager -from vocode.streaming.utils.conversation_logger_adapter import wrap_logger -from vocode.streaming.utils import create_conversation_id - -TelephonyOutputDeviceType = TypeVar( - "TelephonyOutputDeviceType", bound=Union[TwilioOutputDevice, VonageOutputDevice] -) - - -class Call(StreamingConversation[TelephonyOutputDeviceType]): - def __init__( - self, - from_phone: str, - to_phone: str, - base_url: str, - config_manager: BaseConfigManager, - output_device: TelephonyOutputDeviceType, - agent_config: AgentConfig, - transcriber_config: TranscriberConfig, - synthesizer_config: SynthesizerConfig, - conversation_id: Optional[str] = None, - transcriber_factory: TranscriberFactory = TranscriberFactory(), - agent_factory: AgentFactory = AgentFactory(), - synthesizer_factory: SynthesizerFactory = SynthesizerFactory(), - events_manager: Optional[EventsManager] = None, - logger: Optional[logging.Logger] = None, - ): - conversation_id = conversation_id or create_conversation_id() - logger = wrap_logger( - logger or logging.getLogger(__name__), - conversation_id=conversation_id, - ) - - self.from_phone = from_phone - self.to_phone = to_phone - self.base_url = base_url - self.config_manager = config_manager - super().__init__( - output_device, - transcriber_factory.create_transcriber(transcriber_config, logger=logger), - agent_factory.create_agent(agent_config, logger=logger), - synthesizer_factory.create_synthesizer(synthesizer_config, logger=logger), - conversation_id=conversation_id, - per_chunk_allowance_seconds=0.01, - events_manager=events_manager, - logger=logger, - ) - - def attach_ws(self, ws: WebSocket): - self.logger.debug("Trying to attach WS to outbound call") - self.output_device.ws = ws - self.logger.debug("Attached WS to outbound call") - - async def attach_ws_and_start(self, ws: WebSocket): - raise NotImplementedError - - async def tear_down(self): - self.events_manager.publish_event(PhoneCallEndedEvent(conversation_id=self.id)) - await self.terminate() diff --git a/vocode/streaming/telephony/conversation/mark_message_queue.py b/vocode/streaming/telephony/conversation/mark_message_queue.py new file mode 100644 index 000000000..c4b17b931 --- /dev/null +++ b/vocode/streaming/telephony/conversation/mark_message_queue.py @@ -0,0 +1,46 @@ +import asyncio +from typing import Dict, Union + +from pydantic.v1 import BaseModel + + +class ChunkFinishedMarkMessage(BaseModel): + chunk_idx: int + + +class UtteranceFinishedMarkMessage(BaseModel): + pass + + +MarkMessage = Union[ChunkFinishedMarkMessage, UtteranceFinishedMarkMessage] + + +class MarkMessageQueue: + """A keyed asyncio.Queue for MarkMessage objects""" + + def __init__(self): + self.utterance_queues: Dict[str, asyncio.Queue[MarkMessage]] = {} + + def create_utterance_queue(self, utterance_id: str): + if utterance_id in self.utterance_queues: + raise ValueError(f"utterance_id {utterance_id} already exists") + self.utterance_queues[utterance_id] = asyncio.Queue() + + def put_nowait( + self, + utterance_id: str, + mark_message: MarkMessage, + ): + if utterance_id in self.utterance_queues: + self.utterance_queues[utterance_id].put_nowait(mark_message) + + async def get( + self, + utterance_id: str, + ) -> MarkMessage: + if utterance_id not in self.utterance_queues: + raise ValueError(f"utterance_id {utterance_id} not found") + return await self.utterance_queues[utterance_id].get() + + def delete_utterance_queue(self, utterance_id: str): + del self.utterance_queues[utterance_id] diff --git a/vocode/streaming/telephony/conversation/outbound_call.py b/vocode/streaming/telephony/conversation/outbound_call.py index 88bc77ccb..5570ebdf7 100644 --- a/vocode/streaming/telephony/conversation/outbound_call.py +++ b/vocode/streaming/telephony/conversation/outbound_call.py @@ -1,27 +1,21 @@ -import logging -from typing import Optional, Union -from vocode import getenv +from typing import Dict, Optional + +from loguru import logger from vocode.streaming.models.agent import AgentConfig -from vocode.streaming.models.audio_encoding import AudioEncoding -from vocode.streaming.models.synthesizer import ( - SynthesizerConfig, -) +from vocode.streaming.models.synthesizer import SynthesizerConfig from vocode.streaming.models.telephony import ( + TelephonyConfig, TwilioCallConfig, TwilioConfig, VonageCallConfig, VonageConfig, ) -from vocode.streaming.models.transcriber import ( - TranscriberConfig, -) -from vocode.streaming.telephony.client.base_telephony_client import BaseTelephonyClient +from vocode.streaming.models.transcriber import TranscriberConfig +from vocode.streaming.telephony.client.abstract_telephony_client import AbstractTelephonyClient from vocode.streaming.telephony.client.twilio_client import TwilioClient from vocode.streaming.telephony.client.vonage_client import VonageClient -from vocode.streaming.telephony.config_manager.base_config_manager import ( - BaseConfigManager, -) +from vocode.streaming.telephony.config_manager.base_config_manager import BaseConfigManager from vocode.streaming.utils import create_conversation_id @@ -33,13 +27,12 @@ def __init__( from_phone: str, config_manager: BaseConfigManager, agent_config: AgentConfig, - twilio_config: Optional[TwilioConfig] = None, - vonage_config: Optional[VonageConfig] = None, + telephony_config: TelephonyConfig, + telephony_params: Optional[Dict[str, str]] = None, transcriber_config: Optional[TranscriberConfig] = None, synthesizer_config: Optional[SynthesizerConfig] = None, conversation_id: Optional[str] = None, - logger: Optional[logging.Logger] = None, - mobile_only: bool = True, + sentry_tags: Dict[str, str] = {}, digits: Optional[ str ] = None, # Keys to press when the call connects, see send_digits https://www.twilio.com/docs/voice/api/call-resource#create-a-call-resource @@ -47,52 +40,33 @@ def __init__( ): self.base_url = base_url self.to_phone = to_phone - self.digits = digits self.from_phone = from_phone - self.mobile_only = mobile_only self.config_manager = config_manager self.agent_config = agent_config self.conversation_id = conversation_id or create_conversation_id() - self.logger = logger or logging.getLogger(__name__) - self.twilio_config = twilio_config - self.vonage_config = vonage_config - if not self.twilio_config and not self.vonage_config: - self.logger.debug( - "No telephony config provided, defaulting to Twilio env vars" - ) - self.twilio_config = TwilioConfig( - account_sid=getenv("TWILIO_ACCOUNT_SID"), - auth_token=getenv("TWILIO_AUTH_TOKEN"), - ) + self.telephony_config = telephony_config + self.telephony_params = telephony_params or {} self.telephony_client = self.create_telephony_client() - assert not output_to_speaker or isinstance( - self.telephony_client, VonageClient - ), "Output to speaker is only supported for Vonage calls" self.transcriber_config = self.create_transcriber_config(transcriber_config) self.synthesizer_config = self.create_synthesizer_config(synthesizer_config) - self.telephony_id = None self.output_to_speaker = output_to_speaker + self.sentry_tags = sentry_tags + self.digits = digits - def create_telephony_client(self) -> BaseTelephonyClient: - if self.twilio_config is not None: - return TwilioClient( - base_url=self.base_url, twilio_config=self.twilio_config - ) - elif self.vonage_config is not None: - return VonageClient( - base_url=self.base_url, vonage_config=self.vonage_config - ) - else: - raise ValueError("No telephony config provided") + def create_telephony_client(self) -> AbstractTelephonyClient: + if isinstance(self.telephony_config, TwilioConfig): + return TwilioClient(base_url=self.base_url, maybe_twilio_config=self.telephony_config) + elif isinstance(self.telephony_config, VonageConfig): + return VonageClient(base_url=self.base_url, maybe_vonage_config=self.telephony_config) def create_transcriber_config( self, transcriber_config_override: Optional[TranscriberConfig] ) -> TranscriberConfig: if transcriber_config_override is not None: return transcriber_config_override - if self.twilio_config is not None: + if isinstance(self.telephony_config, TwilioConfig): return TwilioCallConfig.default_transcriber_config() - elif self.vonage_config is not None: + elif isinstance(self.telephony_config, VonageConfig): return VonageCallConfig.default_transcriber_config() else: raise ValueError("No telephony config provided") @@ -102,25 +76,21 @@ def create_synthesizer_config( ) -> SynthesizerConfig: if synthesizer_config_override is not None: return synthesizer_config_override - if self.twilio_config is not None: + if isinstance(self.telephony_config, TwilioConfig): return TwilioCallConfig.default_synthesizer_config() - elif self.vonage_config is not None: + elif isinstance(self.telephony_config, VonageConfig): return VonageCallConfig.default_synthesizer_config() else: raise ValueError("No telephony config provided") async def start(self): - self.logger.debug("Starting outbound call") - self.telephony_client.validate_outbound_call( - to_phone=self.to_phone, - from_phone=self.from_phone, - mobile_only=self.mobile_only, - ) + logger.debug("Starting outbound call") self.telephony_id = await self.telephony_client.create_call( conversation_id=self.conversation_id, to_phone=self.to_phone, from_phone=self.from_phone, - record=self.telephony_client.get_telephony_config().record, + record=self.telephony_client.get_telephony_config().record, # note twilio does not use this + telephony_params=self.telephony_params, digits=self.digits, ) if isinstance(self.telephony_client, TwilioClient): @@ -132,6 +102,9 @@ async def start(self): twilio_sid=self.telephony_id, from_phone=self.from_phone, to_phone=self.to_phone, + sentry_tags=self.sentry_tags, + telephony_params=self.telephony_params, + direction="outbound", ) elif isinstance(self.telephony_client, VonageClient): call_config = VonageCallConfig( @@ -142,7 +115,10 @@ async def start(self): vonage_uuid=self.telephony_id, from_phone=self.from_phone, to_phone=self.to_phone, - output_to_speaker=self.output_to_speaker, + output_to_speaker=False, + sentry_tags=self.sentry_tags, + telephony_params=self.telephony_params, + direction="outbound", ) else: raise ValueError("Unknown telephony client") diff --git a/vocode/streaming/telephony/conversation/twilio_call.py b/vocode/streaming/telephony/conversation/twilio_call.py deleted file mode 100644 index 6d436f30b..000000000 --- a/vocode/streaming/telephony/conversation/twilio_call.py +++ /dev/null @@ -1,161 +0,0 @@ -import asyncio -from fastapi import WebSocket -import base64 -from enum import Enum -import json -import logging -from typing import Optional -from vocode import getenv -from vocode.streaming.agent.factory import AgentFactory -from vocode.streaming.models.agent import AgentConfig -from vocode.streaming.models.events import PhoneCallConnectedEvent - -from vocode.streaming.models.telephony import TwilioConfig -from vocode.streaming.output_device.twilio_output_device import TwilioOutputDevice -from vocode.streaming.models.synthesizer import ( - SynthesizerConfig, -) -from vocode.streaming.models.transcriber import ( - TranscriberConfig, -) -from vocode.streaming.synthesizer.factory import SynthesizerFactory -from vocode.streaming.telephony.client.twilio_client import TwilioClient -from vocode.streaming.telephony.config_manager.base_config_manager import ( - BaseConfigManager, -) -from vocode.streaming.telephony.conversation.call import Call -from vocode.streaming.transcriber.factory import TranscriberFactory -from vocode.streaming.utils.events_manager import EventsManager -from vocode.streaming.utils.state_manager import TwilioCallStateManager - - -class PhoneCallWebsocketAction(Enum): - CLOSE_WEBSOCKET = 1 - - -class TwilioCall(Call[TwilioOutputDevice]): - def __init__( - self, - from_phone: str, - to_phone: str, - base_url: str, - config_manager: BaseConfigManager, - agent_config: AgentConfig, - transcriber_config: TranscriberConfig, - synthesizer_config: SynthesizerConfig, - twilio_sid: str, - twilio_config: Optional[TwilioConfig] = None, - conversation_id: Optional[str] = None, - transcriber_factory: TranscriberFactory = TranscriberFactory(), - agent_factory: AgentFactory = AgentFactory(), - synthesizer_factory: SynthesizerFactory = SynthesizerFactory(), - events_manager: Optional[EventsManager] = None, - logger: Optional[logging.Logger] = None, - ): - super().__init__( - from_phone, - to_phone, - base_url, - config_manager, - TwilioOutputDevice(), - agent_config, - transcriber_config, - synthesizer_config, - conversation_id=conversation_id, - events_manager=events_manager, - transcriber_factory=transcriber_factory, - agent_factory=agent_factory, - synthesizer_factory=synthesizer_factory, - logger=logger, - ) - self.base_url = base_url - self.config_manager = config_manager - self.twilio_config = twilio_config or TwilioConfig( - account_sid=getenv("TWILIO_ACCOUNT_SID"), - auth_token=getenv("TWILIO_AUTH_TOKEN"), - ) - self.telephony_client = TwilioClient( - base_url=base_url, twilio_config=self.twilio_config - ) - self.twilio_sid = twilio_sid - self.latest_media_timestamp = 0 - - def create_state_manager(self) -> TwilioCallStateManager: - return TwilioCallStateManager(self) - - async def attach_ws_and_start(self, ws: WebSocket): - super().attach_ws(ws) - - twilio_call_ref = self.telephony_client.twilio_client.calls(self.twilio_sid) - twilio_call = twilio_call_ref.fetch() - - if self.twilio_config.record: - recordings_create_params = ( - self.twilio_config.extra_params.get("recordings_create_params") - if self.twilio_config.extra_params - else None - ) - recording = ( - twilio_call_ref.recordings.create(**recordings_create_params) - if recordings_create_params - else twilio_call_ref.recordings.create() - ) - self.logger.info(f"Recording: {recording.sid}") - - if twilio_call.answered_by in ("machine_start", "fax"): - self.logger.info(f"Call answered by {twilio_call.answered_by}") - twilio_call.update(status="completed") - else: - await self.wait_for_twilio_start(ws) - await super().start() - self.events_manager.publish_event( - PhoneCallConnectedEvent( - conversation_id=self.id, - to_phone_number=self.to_phone, - from_phone_number=self.from_phone, - ) - ) - while self.active: - message = await ws.receive_text() - response = await self.handle_ws_message(message) - if response == PhoneCallWebsocketAction.CLOSE_WEBSOCKET: - break - await self.config_manager.delete_config(self.id) - await self.tear_down() - - async def wait_for_twilio_start(self, ws: WebSocket): - assert isinstance(self.output_device, TwilioOutputDevice) - while True: - message = await ws.receive_text() - if not message: - continue - data = json.loads(message) - if data["event"] == "start": - self.logger.debug( - f"Media WS: Received event '{data['event']}': {message}" - ) - self.output_device.stream_sid = data["start"]["streamSid"] - break - - async def handle_ws_message(self, message) -> Optional[PhoneCallWebsocketAction]: - if message is None: - return PhoneCallWebsocketAction.CLOSE_WEBSOCKET - - data = json.loads(message) - if data["event"] == "media": - media = data["media"] - chunk = base64.b64decode(media["payload"]) - if self.latest_media_timestamp + 20 < int(media["timestamp"]): - bytes_to_fill = 8 * ( - int(media["timestamp"]) - (self.latest_media_timestamp + 20) - ) - self.logger.debug(f"Filling {bytes_to_fill} bytes of silence") - # NOTE: 0xff is silence for mulaw audio - self.receive_audio(b"\xff" * bytes_to_fill) - self.latest_media_timestamp = int(media["timestamp"]) - self.receive_audio(chunk) - elif data["event"] == "stop": - self.logger.debug(f"Media WS: Received event 'stop': {message}") - self.logger.debug("Stopping...") - return PhoneCallWebsocketAction.CLOSE_WEBSOCKET - return None diff --git a/vocode/streaming/telephony/conversation/twilio_phone_conversation.py b/vocode/streaming/telephony/conversation/twilio_phone_conversation.py new file mode 100644 index 000000000..232efd41a --- /dev/null +++ b/vocode/streaming/telephony/conversation/twilio_phone_conversation.py @@ -0,0 +1,273 @@ +import asyncio +import base64 +import json +import os +import threading +from enum import Enum +from typing import AsyncGenerator, Optional + +from fastapi import WebSocket +from loguru import logger + +from vocode.streaming.agent.abstract_factory import AbstractAgentFactory +from vocode.streaming.models.agent import AgentConfig +from vocode.streaming.models.events import PhoneCallConnectedEvent +from vocode.streaming.models.synthesizer import SynthesizerConfig +from vocode.streaming.models.telephony import PhoneCallDirection, TwilioConfig +from vocode.streaming.models.transcriber import TranscriberConfig +from vocode.streaming.models.transcript import Message +from vocode.streaming.output_device.twilio_output_device import TwilioOutputDevice +from vocode.streaming.synthesizer.abstract_factory import AbstractSynthesizerFactory +from vocode.streaming.synthesizer.base_synthesizer import SynthesisResult +from vocode.streaming.synthesizer.input_streaming_synthesizer import InputStreamingSynthesizer +from vocode.streaming.telephony.client.twilio_client import TwilioClient +from vocode.streaming.telephony.config_manager.base_config_manager import BaseConfigManager +from vocode.streaming.telephony.conversation.abstract_phone_conversation import ( + AbstractPhoneConversation, +) +from vocode.streaming.telephony.conversation.mark_message_queue import ( + ChunkFinishedMarkMessage, + MarkMessage, + MarkMessageQueue, + UtteranceFinishedMarkMessage, +) +from vocode.streaming.transcriber.abstract_factory import AbstractTranscriberFactory +from vocode.streaming.utils import create_utterance_id +from vocode.streaming.utils.create_task import asyncio_create_task_with_done_error_log +from vocode.streaming.utils.events_manager import EventsManager +from vocode.streaming.utils.state_manager import TwilioPhoneConversationStateManager + + +class TwilioPhoneConversationWebsocketAction(Enum): + CLOSE_WEBSOCKET = 1 + + +class TwilioPhoneConversation(AbstractPhoneConversation[TwilioOutputDevice]): + telephony_provider = "twilio" + + def __init__( + self, + direction: PhoneCallDirection, + from_phone: str, + to_phone: str, + base_url: str, + config_manager: BaseConfigManager, + agent_config: AgentConfig, + transcriber_config: TranscriberConfig, + synthesizer_config: SynthesizerConfig, + twilio_sid: str, + agent_factory: AbstractAgentFactory, + transcriber_factory: AbstractTranscriberFactory, + synthesizer_factory: AbstractSynthesizerFactory, + twilio_config: Optional[TwilioConfig] = None, + conversation_id: Optional[str] = None, + events_manager: Optional[EventsManager] = None, + record_call: bool = False, + speed_coefficient: float = 1.0, + noise_suppression: bool = False, # is currently a no-op + ): + super().__init__( + direction=direction, + from_phone=from_phone, + to_phone=to_phone, + base_url=base_url, + config_manager=config_manager, + output_device=TwilioOutputDevice(), + agent_config=agent_config, + transcriber_config=transcriber_config, + synthesizer_config=synthesizer_config, + conversation_id=conversation_id, + events_manager=events_manager, + transcriber_factory=transcriber_factory, + agent_factory=agent_factory, + synthesizer_factory=synthesizer_factory, + speed_coefficient=speed_coefficient, + ) + self.mark_message_queue: MarkMessageQueue = MarkMessageQueue() + self.config_manager = config_manager + self.twilio_config = twilio_config or TwilioConfig( + account_sid=os.environ["TWILIO_ACCOUNT_SID"], + auth_token=os.environ["TWILIO_AUTH_TOKEN"], + ) + self.telephony_client = TwilioClient( + base_url=self.base_url, maybe_twilio_config=self.twilio_config + ) + self.twilio_sid = twilio_sid + self.record_call = record_call + + def create_state_manager(self) -> TwilioPhoneConversationStateManager: + return TwilioPhoneConversationStateManager(self) + + async def attach_ws_and_start(self, ws: WebSocket): + super().attach_ws(ws) + + await self._wait_for_twilio_start(ws) + await self.start() + self.events_manager.publish_event( + PhoneCallConnectedEvent( + conversation_id=self.id, + to_phone_number=self.to_phone, + from_phone_number=self.from_phone, + ) + ) + while self.active: + message = await ws.receive_text() + response = await self._handle_ws_message(message) + if response == TwilioPhoneConversationWebsocketAction.CLOSE_WEBSOCKET: + break + await self.terminate() + + async def _wait_for_twilio_start(self, ws: WebSocket): + assert isinstance(self.output_device, TwilioOutputDevice) + while True: + message = await ws.receive_text() + if not message: + continue + data = json.loads(message) + if data["event"] == "start": + logger.debug(f"Media WS: Received event '{data['event']}': {message}") + self.output_device.stream_sid = data["start"]["streamSid"] + break + + async def _handle_ws_message(self, message) -> Optional[TwilioPhoneConversationWebsocketAction]: + if message is None: + return TwilioPhoneConversationWebsocketAction.CLOSE_WEBSOCKET + + data = json.loads(message) + if data["event"] == "media": + media = data["media"] + chunk = base64.b64decode(media["payload"]) + self.receive_audio(chunk) + if data["event"] == "mark": + mark_name = data["mark"]["name"] + if mark_name.startswith("chunk-"): + utterance_id, chunk_idx = mark_name.split("-")[1:] + self.mark_message_queue.put_nowait( + utterance_id=utterance_id, + mark_message=ChunkFinishedMarkMessage(chunk_idx=int(chunk_idx)), + ) + elif mark_name.startswith("utterance"): + utterance_id = mark_name.split("-")[1] + self.mark_message_queue.put_nowait( + utterance_id=utterance_id, + mark_message=UtteranceFinishedMarkMessage(), + ) + elif data["event"] == "stop": + logger.debug(f"Media WS: Received event 'stop': {message}") + logger.debug("Stopping...") + return TwilioPhoneConversationWebsocketAction.CLOSE_WEBSOCKET + return None + + async def _send_chunks( + self, + utterance_id: str, + chunk_generator: AsyncGenerator[SynthesisResult.ChunkResult, None], + clear_message_lock: asyncio.Lock, + stop_event: threading.Event, + ): + chunk_idx = 0 + try: + async for chunk_result in chunk_generator: + async with clear_message_lock: + if stop_event.is_set(): + break + self.output_device.consume_nonblocking(chunk_result.chunk) + self.output_device.send_chunk_finished_mark(utterance_id, chunk_idx) + chunk_idx += 1 + except asyncio.CancelledError: + pass + finally: + logger.debug("Finished sending all chunks to Twilio") + self.output_device.send_utterance_finished_mark(utterance_id) + + async def send_speech_to_output( + self, + message: str, + synthesis_result: SynthesisResult, + stop_event: threading.Event, + seconds_per_chunk: float, + transcript_message: Optional[Message] = None, + started_event: Optional[threading.Event] = None, + ): + """In contrast with send_speech_to_output in the base class, this function uses mark messages + to support interruption - we send all chunks to the output device, and then wait for mark messages[0] + that indicate that each chunk has been played. This means that we don't need to depends on asyncio.sleep + to support interruptions. + + Once we receive an interruption signal: + - we send a clear message to Twilio to stop playing all queued audio + - based on the number of mark messages we've received back, we know how many chunks were played and can indicate on the transcript + + [0] https://www.twilio.com/docs/voice/twiml/stream#websocket-messages-to-twilio + """ + + if self.transcriber.get_transcriber_config().mute_during_speech: + logger.debug("Muting transcriber") + self.transcriber.mute() + message_sent = message + cut_off = False + chunk_idx = 0 + seconds_spoken = 0.0 + logger.debug(f"Start sending speech {message} to output") + + utterance_id = create_utterance_id() + self.mark_message_queue.create_utterance_queue(utterance_id) + + first_chunk_span = self._maybe_create_first_chunk_span(synthesis_result, message) + + clear_message_lock = asyncio.Lock() + + asyncio_create_task_with_done_error_log( + self._send_chunks( + utterance_id, + synthesis_result.chunk_generator, + clear_message_lock, + stop_event, + ), + ) + mark_event: MarkMessage + first = True + while True: + mark_event = await self.mark_message_queue.get(utterance_id) + if isinstance(mark_event, UtteranceFinishedMarkMessage): + break + if first and first_chunk_span: + self._track_first_chunk(first_chunk_span, synthesis_result) + first = False + seconds_spoken = mark_event.chunk_idx * seconds_per_chunk + # Lock here so that we check the stop event and send the clear message atomically + # w.r.t. the _send_chunks task which also checks the stop event + # Otherwise, we could send the clear message while _send_chunks is in the middle of sending a chunk + # and the synthesis wouldn't be cleared + async with clear_message_lock: + if stop_event.is_set(): + self.output_device.send_clear_message() + logger.debug( + "Interrupted, stopping text to speech after {} chunks".format(chunk_idx) + ) + message_sent = synthesis_result.get_message_up_to(seconds_spoken) + cut_off = True + break + if chunk_idx == 0: + if started_event: + started_event.set() + self.mark_last_action_timestamp() + chunk_idx += 1 + seconds_spoken += seconds_per_chunk + if transcript_message: + transcript_message.text = synthesis_result.get_message_up_to(seconds_spoken) + self.mark_message_queue.delete_utterance_queue(utterance_id) + if self.transcriber.get_transcriber_config().mute_during_speech: + logger.debug("Unmuting transcriber") + self.transcriber.unmute() + if transcript_message: + # For input streaming synthesizers, we have to buffer the message as it is streamed in + # What is said is federated fully by synthesis_result.get_message_up_to + if isinstance(self.synthesizer, InputStreamingSynthesizer): + message_sent = transcript_message.text + else: + transcript_message.text = message_sent + transcript_message.is_final = not cut_off + if synthesis_result.synthesis_total_span: + synthesis_result.synthesis_total_span.finish() + return message_sent, cut_off diff --git a/vocode/streaming/telephony/conversation/vonage_call.py b/vocode/streaming/telephony/conversation/vonage_call.py deleted file mode 100644 index 251c39950..000000000 --- a/vocode/streaming/telephony/conversation/vonage_call.py +++ /dev/null @@ -1,131 +0,0 @@ -from fastapi import WebSocket, WebSocketDisconnect -import logging -from typing import Optional -from vocode import getenv -from vocode.streaming.agent.factory import AgentFactory -from vocode.streaming.models.agent import AgentConfig -from vocode.streaming.models.events import PhoneCallConnectedEvent, PhoneCallEndedEvent -from vocode.streaming.output_device.vonage_output_device import VonageOutputDevice - -from vocode.streaming.models.telephony import VonageConfig -from vocode.streaming.models.synthesizer import ( - SynthesizerConfig, -) -from vocode.streaming.models.transcriber import ( - TranscriberConfig, -) -from vocode.streaming.synthesizer.factory import SynthesizerFactory -from vocode.streaming.telephony.client.vonage_client import VonageClient -from vocode.streaming.telephony.config_manager.base_config_manager import ( - BaseConfigManager, -) -from vocode.streaming.telephony.conversation.call import Call -from vocode.streaming.transcriber.factory import TranscriberFactory -from vocode.streaming.utils.events_manager import EventsManager - -from vocode.streaming.output_device.speaker_output import SpeakerOutput -from vocode.streaming.telephony.constants import VONAGE_CHUNK_SIZE, VONAGE_SAMPLING_RATE -from vocode.streaming.utils.state_manager import ( - ConversationStateManager, - VonageCallStateManager, -) - - -class VonageCall(Call[VonageOutputDevice]): - def __init__( - self, - from_phone: str, - to_phone: str, - base_url: str, - config_manager: BaseConfigManager, - agent_config: AgentConfig, - transcriber_config: TranscriberConfig, - synthesizer_config: SynthesizerConfig, - vonage_uuid: str, - vonage_config: Optional[VonageConfig] = None, - conversation_id: Optional[str] = None, - transcriber_factory: TranscriberFactory = TranscriberFactory(), - agent_factory: AgentFactory = AgentFactory(), - synthesizer_factory: SynthesizerFactory = SynthesizerFactory(), - events_manager: Optional[EventsManager] = None, - output_to_speaker: bool = False, - logger: Optional[logging.Logger] = None, - ): - super().__init__( - from_phone, - to_phone, - base_url, - config_manager, - VonageOutputDevice(output_to_speaker=output_to_speaker), - agent_config, - transcriber_config, - synthesizer_config, - conversation_id=conversation_id, - events_manager=events_manager, - transcriber_factory=transcriber_factory, - agent_factory=agent_factory, - synthesizer_factory=synthesizer_factory, - logger=logger, - ) - self.output_to_speaker = output_to_speaker - self.base_url = base_url - self.config_manager = config_manager - self.vonage_config = vonage_config or VonageConfig( - api_key=getenv("VONAGE_API_KEY"), - api_secret=getenv("VONAGE_API_SECRET"), - application_id=getenv("VONAGE_APPLICATION_ID"), - private_key=getenv("VONAGE_PRIVATE_KEY"), - ) - self.telephony_client = VonageClient( - base_url=base_url, vonage_config=self.vonage_config - ) - self.vonage_uuid = vonage_uuid - if output_to_speaker: - self.output_speaker = SpeakerOutput.from_default_device( - sampling_rate=VONAGE_SAMPLING_RATE, blocksize=VONAGE_CHUNK_SIZE // 2 - ) - - def create_state_manager(self) -> VonageCallStateManager: - return VonageCallStateManager(self) - - # TODO(EPD-186) - make this function async and use aiohttp with the vonage client - def send_dtmf(self, digits: str): - self.telephony_client.voice.send_dtmf(self.vonage_uuid, {"digits": digits}) - - async def attach_ws_and_start(self, ws: WebSocket): - # start message - await ws.receive() - self.logger.debug("Trying to attach WS to outbound call") - self.output_device.ws = ws - self.logger.debug("Attached WS to outbound call") - - await super().start() - self.events_manager.publish_event( - PhoneCallConnectedEvent( - conversation_id=self.id, - to_phone_number=self.to_phone, - from_phone_number=self.from_phone, - ) - ) - disconnected = False - while self.active: - try: - chunk = await ws.receive_bytes() - self.receive_audio(chunk) - except WebSocketDisconnect: - self.logger.debug("Websocket disconnected") - disconnected = True - break - if not disconnected: - await ws.close() - await self.config_manager.delete_config(self.id) - await self.tear_down() - - def receive_audio(self, chunk: bytes): - super().receive_audio(chunk) - if self.output_to_speaker: - self.output_speaker.consume_nonblocking(chunk) - - async def tear_down(self): - self.events_manager.publish_event(PhoneCallEndedEvent(conversation_id=self.id)) - await self.terminate() diff --git a/vocode/streaming/telephony/conversation/vonage_phone_conversation.py b/vocode/streaming/telephony/conversation/vonage_phone_conversation.py new file mode 100644 index 000000000..65adc73f4 --- /dev/null +++ b/vocode/streaming/telephony/conversation/vonage_phone_conversation.py @@ -0,0 +1,139 @@ +import os +from typing import Optional + +import numpy as np +import pvkoala +from fastapi import WebSocket, WebSocketDisconnect +from loguru import logger + +from vocode.streaming.agent.abstract_factory import AbstractAgentFactory +from vocode.streaming.models.agent import AgentConfig +from vocode.streaming.models.events import PhoneCallConnectedEvent +from vocode.streaming.models.synthesizer import SynthesizerConfig +from vocode.streaming.models.telephony import PhoneCallDirection, VonageConfig +from vocode.streaming.models.transcriber import TranscriberConfig +from vocode.streaming.output_device.vonage_output_device import VonageOutputDevice +from vocode.streaming.synthesizer.abstract_factory import AbstractSynthesizerFactory +from vocode.streaming.telephony.client.vonage_client import VonageClient +from vocode.streaming.telephony.config_manager.base_config_manager import BaseConfigManager +from vocode.streaming.telephony.conversation.abstract_phone_conversation import ( + AbstractPhoneConversation, +) +from vocode.streaming.transcriber.abstract_factory import AbstractTranscriberFactory +from vocode.streaming.utils.events_manager import EventsManager +from vocode.streaming.utils.state_manager import VonagePhoneConversationStateManager + +KOALA_CHUNK_SIZE = 512 # 16 bit samples, size 256 + + +class VonagePhoneConversation(AbstractPhoneConversation[VonageOutputDevice]): + telephony_provider = "vonage" + + def __init__( + self, + direction: PhoneCallDirection, + from_phone: str, + to_phone: str, + base_url: str, + config_manager: BaseConfigManager, + agent_config: AgentConfig, + transcriber_config: TranscriberConfig, + synthesizer_config: SynthesizerConfig, + vonage_uuid: str, + vonage_config: VonageConfig, + agent_factory: AbstractAgentFactory, + transcriber_factory: AbstractTranscriberFactory, + synthesizer_factory: AbstractSynthesizerFactory, + conversation_id: Optional[str] = None, + events_manager: Optional[EventsManager] = None, + output_to_speaker: bool = False, + speed_coefficient: float = 1.0, + per_chunk_allowance_seconds: float = 0.01, + noise_suppression: bool = False, + ): + self.speed_coefficient = speed_coefficient + super().__init__( + direction=direction, + speed_coefficient=speed_coefficient, + from_phone=from_phone, + to_phone=to_phone, + base_url=base_url, + config_manager=config_manager, + output_device=VonageOutputDevice(output_to_speaker=output_to_speaker), + agent_config=agent_config, + transcriber_config=transcriber_config, + synthesizer_config=synthesizer_config, + conversation_id=conversation_id, + events_manager=events_manager, + transcriber_factory=transcriber_factory, + agent_factory=agent_factory, + synthesizer_factory=synthesizer_factory, + per_chunk_allowance_seconds=per_chunk_allowance_seconds, + ) + self.vonage_config = vonage_config + self.telephony_client = VonageClient( + base_url=self.base_url, + maybe_vonage_config=self.vonage_config, + ) + self.vonage_uuid = vonage_uuid + self.noise_suppression = noise_suppression + if self.noise_suppression: + logger.info("Using PV koala noise suppression") + self.buffer = bytearray() + self.koala = pvkoala.create( + access_key=os.environ["KOALA_ACCESS_KEY"], + ) + + def create_state_manager(self) -> VonagePhoneConversationStateManager: + return VonagePhoneConversationStateManager(self) + + async def attach_ws_and_start(self, ws: WebSocket): + # start message + await ws.receive() + super().attach_ws(ws) + + await self.start() + self.events_manager.publish_event( + PhoneCallConnectedEvent( + conversation_id=self.id, + to_phone_number=self.to_phone, + from_phone_number=self.from_phone, + ) + ) + disconnected = False + while self.active: + try: + message = await ws.receive() + if message["type"] == "websocket.disconnect": + raise WebSocketDisconnect(message["code"]) + if "bytes" in message: + chunk = message["bytes"] + self.receive_audio(chunk) + else: + logger.debug(f"Received non-bytes message: {message}") + except WebSocketDisconnect as e: + logger.debug("Websocket disconnected") + if e.code != 1000: + logger.error(f"Websocket disconnected abnormally with code {e.code} {e.reason}") + disconnected = True + break + await self.terminate() + if not disconnected: + await ws.close() + + def receive_audio(self, chunk: bytes): + if self.noise_suppression: + self.buffer.extend(chunk) + + while len(self.buffer) >= KOALA_CHUNK_SIZE: + koala_chunk = np.frombuffer(self.buffer[:KOALA_CHUNK_SIZE], dtype=np.int16) + try: + denoised_chunk = np.array( + self.koala.process(koala_chunk), dtype=np.int16 + ).tobytes() + except Exception: + denoised_chunk = koala_chunk.tobytes() + super().receive_audio(denoised_chunk) + self.buffer = self.buffer[KOALA_CHUNK_SIZE:] + else: + super().receive_audio(chunk) diff --git a/vocode/streaming/telephony/conversation/zoom_dial_in.py b/vocode/streaming/telephony/conversation/zoom_dial_in.py index 5b29584c1..0e497b555 100644 --- a/vocode/streaming/telephony/conversation/zoom_dial_in.py +++ b/vocode/streaming/telephony/conversation/zoom_dial_in.py @@ -1,12 +1,10 @@ -import logging from typing import Optional + from vocode.streaming.models.agent import AgentConfig from vocode.streaming.models.synthesizer import SynthesizerConfig from vocode.streaming.models.telephony import TwilioConfig from vocode.streaming.models.transcriber import TranscriberConfig -from vocode.streaming.telephony.config_manager.base_config_manager import ( - BaseConfigManager, -) +from vocode.streaming.telephony.config_manager.base_config_manager import BaseConfigManager from vocode.streaming.telephony.conversation.outbound_call import OutboundCall @@ -20,11 +18,10 @@ def __init__( from_phone: str, config_manager: BaseConfigManager, agent_config: AgentConfig, + twilio_config: TwilioConfig, transcriber_config: Optional[TranscriberConfig] = None, synthesizer_config: Optional[SynthesizerConfig] = None, - twilio_config: Optional[TwilioConfig] = None, conversation_id: Optional[str] = None, - logger: Optional[logging.Logger] = None, ): digits = f"wwww{zoom_meeting_id}#" if zoom_meeting_password: @@ -38,10 +35,8 @@ def __init__( transcriber_config=transcriber_config, agent_config=agent_config, synthesizer_config=synthesizer_config, - twilio_config=twilio_config, + telephony_config=twilio_config, conversation_id=conversation_id, - logger=logger, - mobile_only=False, digits=digits, ) diff --git a/vocode/streaming/telephony/server/base.py b/vocode/streaming/telephony/server/base.py index 10c2b365a..5e04c3c05 100644 --- a/vocode/streaming/telephony/server/base.py +++ b/vocode/streaming/telephony/server/base.py @@ -1,40 +1,33 @@ import abc from functools import partial -import logging from typing import List, Optional + from fastapi import APIRouter, Form, Request, Response +from loguru import logger from pydantic.v1 import BaseModel, Field -from vocode.streaming.agent.factory import AgentFactory + +from vocode.streaming.agent.abstract_factory import AbstractAgentFactory +from vocode.streaming.agent.default_factory import DefaultAgentFactory from vocode.streaming.models.agent import AgentConfig from vocode.streaming.models.events import RecordingEvent from vocode.streaming.models.synthesizer import SynthesizerConfig -from vocode.streaming.models.transcriber import TranscriberConfig -from vocode.streaming.synthesizer.factory import SynthesizerFactory -from vocode.streaming.telephony.client.base_telephony_client import BaseTelephonyClient -from vocode.streaming.telephony.client.twilio_client import TwilioClient -from vocode.streaming.telephony.client.vonage_client import VonageClient -from vocode.streaming.telephony.config_manager.base_config_manager import ( - BaseConfigManager, -) -from vocode.streaming.telephony.constants import ( - DEFAULT_AUDIO_ENCODING, - DEFAULT_CHUNK_SIZE, - DEFAULT_SAMPLING_RATE, - VONAGE_AUDIO_ENCODING, - VONAGE_SAMPLING_RATE, -) - -from vocode.streaming.telephony.server.router.calls import CallsRouter from vocode.streaming.models.telephony import ( TwilioCallConfig, TwilioConfig, VonageCallConfig, VonageConfig, ) - -from vocode.streaming.telephony.templater import Templater -from vocode.streaming.transcriber.base_transcriber import BaseTranscriber -from vocode.streaming.transcriber.factory import TranscriberFactory +from vocode.streaming.models.transcriber import TranscriberConfig +from vocode.streaming.synthesizer.abstract_factory import AbstractSynthesizerFactory +from vocode.streaming.synthesizer.default_factory import DefaultSynthesizerFactory +from vocode.streaming.telephony.client.abstract_telephony_client import AbstractTelephonyClient +from vocode.streaming.telephony.client.twilio_client import TwilioClient +from vocode.streaming.telephony.client.vonage_client import VonageClient +from vocode.streaming.telephony.config_manager.base_config_manager import BaseConfigManager +from vocode.streaming.telephony.server.router.calls import CallsRouter +from vocode.streaming.telephony.templater import get_connection_twiml +from vocode.streaming.transcriber.abstract_factory import AbstractTranscriberFactory +from vocode.streaming.transcriber.default_factory import DefaultTranscriberFactory from vocode.streaming.utils import create_conversation_id from vocode.streaming.utils.events_manager import EventsManager @@ -66,17 +59,14 @@ def __init__( base_url: str, config_manager: BaseConfigManager, inbound_call_configs: List[AbstractInboundCallConfig] = [], - transcriber_factory: TranscriberFactory = TranscriberFactory(), - agent_factory: AgentFactory = AgentFactory(), - synthesizer_factory: SynthesizerFactory = SynthesizerFactory(), + transcriber_factory: AbstractTranscriberFactory = DefaultTranscriberFactory(), + agent_factory: AbstractAgentFactory = DefaultAgentFactory(), + synthesizer_factory: AbstractSynthesizerFactory = DefaultSynthesizerFactory(), events_manager: Optional[EventsManager] = None, - logger: Optional[logging.Logger] = None, ): self.base_url = base_url - self.logger = logger or logging.getLogger(__name__) self.router = APIRouter() self.config_manager = config_manager - self.templater = Templater() self.events_manager = events_manager self.router.include_router( CallsRouter( @@ -86,7 +76,6 @@ def __init__( agent_factory=agent_factory, synthesizer_factory=synthesizer_factory, events_manager=self.events_manager, - logger=self.logger, ).get_router() ) for config in inbound_call_configs: @@ -97,12 +86,12 @@ def __init__( ) # vonage requires an events endpoint self.router.add_api_route("/events", self.events, methods=["GET", "POST"]) - self.logger.info(f"Set up events endpoint at https://{self.base_url}/events") + logger.info(f"Set up events endpoint at https://{self.base_url}/events") self.router.add_api_route( "/recordings/{conversation_id}", self.recordings, methods=["GET", "POST"] ) - self.logger.info( + logger.info( f"Set up recordings endpoint at https://{self.base_url}/recordings/{{conversation_id}}" ) @@ -113,9 +102,7 @@ async def recordings(self, request: Request, conversation_id: str): recording_url = (await request.json())["recording_url"] if self.events_manager is not None and recording_url is not None: self.events_manager.publish_event( - RecordingEvent( - recording_url=recording_url, conversation_id=conversation_id - ) + RecordingEvent(recording_url=recording_url, conversation_id=conversation_id) ) return Response() @@ -139,17 +126,15 @@ async def twilio_route( twilio_sid=twilio_sid, from_phone=twilio_from, to_phone=twilio_to, + direction="inbound", ) conversation_id = create_conversation_id() await self.config_manager.save_config(conversation_id, call_config) - return self.templater.get_connection_twiml( - base_url=self.base_url, call_id=conversation_id - ) + return get_connection_twiml(base_url=self.base_url, call_id=conversation_id) - async def vonage_route( - vonage_config: VonageConfig, vonage_answer_request: VonageAnswerRequest - ): + async def vonage_route(vonage_config: VonageConfig, request: Request): + vonage_answer_request = VonageAnswerRequest.parse_obj(await request.json()) call_config = VonageCallConfig( transcriber_config=inbound_call_config.transcriber_config or VonageCallConfig.default_transcriber_config(), @@ -160,44 +145,47 @@ async def vonage_route( vonage_uuid=vonage_answer_request.uuid, to_phone=vonage_answer_request.from_, from_phone=vonage_answer_request.to, + direction="inbound", ) conversation_id = create_conversation_id() await self.config_manager.save_config(conversation_id, call_config) - return VonageClient.create_call_ncco( + vonage_client = VonageClient( base_url=self.base_url, + maybe_vonage_config=vonage_config, + record_calls=vonage_config.record, + ) + return vonage_client.create_call_ncco( conversation_id=conversation_id, record=vonage_config.record, ) if isinstance(inbound_call_config, TwilioInboundCallConfig): - self.logger.info( + logger.info( f"Set up inbound call TwiML at https://{self.base_url}{inbound_call_config.url}" ) return partial(twilio_route, inbound_call_config.twilio_config) elif isinstance(inbound_call_config, VonageInboundCallConfig): - self.logger.info( + logger.info( f"Set up inbound call NCCO at https://{self.base_url}{inbound_call_config.url}" ) return partial(vonage_route, inbound_call_config.vonage_config) else: - raise ValueError( - f"Unknown inbound call config type {type(inbound_call_config)}" - ) + raise ValueError(f"Unknown inbound call config type {type(inbound_call_config)}") async def end_outbound_call(self, conversation_id: str): # TODO validation via twilio_client call_config = await self.config_manager.get_config(conversation_id) if not call_config: raise ValueError(f"Could not find call config for {conversation_id}") - telephony_client: BaseTelephonyClient + telephony_client: AbstractTelephonyClient if isinstance(call_config, TwilioCallConfig): telephony_client = TwilioClient( - base_url=self.base_url, twilio_config=call_config.twilio_config + base_url=self.base_url, maybe_twilio_config=call_config.twilio_config ) await telephony_client.end_call(call_config.twilio_sid) elif isinstance(call_config, VonageCallConfig): telephony_client = VonageClient( - base_url=self.base_url, vonage_config=call_config.vonage_config + base_url=self.base_url, maybe_vonage_config=call_config.vonage_config ) await telephony_client.end_call(call_config.vonage_uuid) return {"id": conversation_id} diff --git a/vocode/streaming/telephony/server/router/calls.py b/vocode/streaming/telephony/server/router/calls.py index f62338531..486b697a3 100644 --- a/vocode/streaming/telephony/server/router/calls.py +++ b/vocode/streaming/telephony/server/router/calls.py @@ -1,22 +1,25 @@ from typing import Optional -import logging from fastapi import APIRouter, HTTPException, WebSocket -from vocode.streaming.agent.factory import AgentFactory -from vocode.streaming.models.telephony import ( - BaseCallConfig, - TwilioCallConfig, - VonageCallConfig, +from loguru import logger + +from vocode.streaming.agent.abstract_factory import AbstractAgentFactory +from vocode.streaming.agent.default_factory import DefaultAgentFactory +from vocode.streaming.models.telephony import BaseCallConfig, TwilioCallConfig, VonageCallConfig +from vocode.streaming.synthesizer.abstract_factory import AbstractSynthesizerFactory +from vocode.streaming.synthesizer.default_factory import DefaultSynthesizerFactory +from vocode.streaming.telephony.config_manager.base_config_manager import BaseConfigManager +from vocode.streaming.telephony.conversation.abstract_phone_conversation import ( + AbstractPhoneConversation, ) -from vocode.streaming.synthesizer.factory import SynthesizerFactory -from vocode.streaming.telephony.config_manager.base_config_manager import ( - BaseConfigManager, +from vocode.streaming.telephony.conversation.twilio_phone_conversation import ( + TwilioPhoneConversation, ) - -from vocode.streaming.telephony.conversation.call import Call -from vocode.streaming.telephony.conversation.twilio_call import TwilioCall -from vocode.streaming.telephony.conversation.vonage_call import VonageCall -from vocode.streaming.transcriber.factory import TranscriberFactory +from vocode.streaming.telephony.conversation.vonage_phone_conversation import ( + VonagePhoneConversation, +) +from vocode.streaming.transcriber.abstract_factory import AbstractTranscriberFactory +from vocode.streaming.transcriber.default_factory import DefaultTranscriberFactory from vocode.streaming.utils.base_router import BaseRouter from vocode.streaming.utils.events_manager import EventsManager @@ -26,11 +29,10 @@ def __init__( self, base_url: str, config_manager: BaseConfigManager, - transcriber_factory: TranscriberFactory = TranscriberFactory(), - agent_factory: AgentFactory = AgentFactory(), - synthesizer_factory: SynthesizerFactory = SynthesizerFactory(), + transcriber_factory: AbstractTranscriberFactory = DefaultTranscriberFactory(), + agent_factory: AbstractAgentFactory = DefaultAgentFactory(), + synthesizer_factory: AbstractSynthesizerFactory = DefaultSynthesizerFactory(), events_manager: Optional[EventsManager] = None, - logger: Optional[logging.Logger] = None, ): super().__init__() self.base_url = base_url @@ -39,7 +41,6 @@ def __init__( self.agent_factory = agent_factory self.synthesizer_factory = synthesizer_factory self.events_manager = events_manager - self.logger = logger or logging.getLogger(__name__) self.router = APIRouter() self.router.websocket("/connect_call/{id}")(self.connect_call) @@ -49,18 +50,16 @@ def _from_call_config( call_config: BaseCallConfig, config_manager: BaseConfigManager, conversation_id: str, - logger: logging.Logger, - transcriber_factory: TranscriberFactory = TranscriberFactory(), - agent_factory: AgentFactory = AgentFactory(), - synthesizer_factory: SynthesizerFactory = SynthesizerFactory(), + transcriber_factory: AbstractTranscriberFactory = DefaultTranscriberFactory(), + agent_factory: AbstractAgentFactory = DefaultAgentFactory(), + synthesizer_factory: AbstractSynthesizerFactory = DefaultSynthesizerFactory(), events_manager: Optional[EventsManager] = None, - ): + ) -> AbstractPhoneConversation: if isinstance(call_config, TwilioCallConfig): - return TwilioCall( + return TwilioPhoneConversation( to_phone=call_config.to_phone, from_phone=call_config.from_phone, base_url=base_url, - logger=logger, config_manager=config_manager, agent_config=call_config.agent_config, transcriber_config=call_config.transcriber_config, @@ -72,13 +71,13 @@ def _from_call_config( agent_factory=agent_factory, synthesizer_factory=synthesizer_factory, events_manager=events_manager, + direction=call_config.direction, ) elif isinstance(call_config, VonageCallConfig): - return VonageCall( + return VonagePhoneConversation( to_phone=call_config.to_phone, from_phone=call_config.from_phone, base_url=base_url, - logger=logger, config_manager=config_manager, agent_config=call_config.agent_config, transcriber_config=call_config.transcriber_config, @@ -91,18 +90,19 @@ def _from_call_config( synthesizer_factory=synthesizer_factory, events_manager=events_manager, output_to_speaker=call_config.output_to_speaker, + direction=call_config.direction, ) else: raise ValueError(f"Unknown call config type {call_config.type}") async def connect_call(self, websocket: WebSocket, id: str): await websocket.accept() - self.logger.debug("Phone WS connection opened for chat {}".format(id)) + logger.debug("Phone WS connection opened for chat {}".format(id)) call_config = await self.config_manager.get_config(id) if not call_config: raise HTTPException(status_code=400, detail="No active phone call") - call = self._from_call_config( + phone_conversation = self._from_call_config( base_url=self.base_url, call_config=call_config, config_manager=self.config_manager, @@ -111,11 +111,10 @@ async def connect_call(self, websocket: WebSocket, id: str): agent_factory=self.agent_factory, synthesizer_factory=self.synthesizer_factory, events_manager=self.events_manager, - logger=self.logger, ) - await call.attach_ws_and_start(websocket) - self.logger.debug("Phone WS connection closed for chat {}".format(id)) + await phone_conversation.attach_ws_and_start(websocket) + logger.debug("Phone WS connection closed for chat {}".format(id)) def get_router(self) -> APIRouter: return self.router diff --git a/vocode/streaming/telephony/templater.py b/vocode/streaming/telephony/templater.py index e6863f62e..a7019d2ea 100644 --- a/vocode/streaming/telephony/templater.py +++ b/vocode/streaming/telephony/templater.py @@ -1,20 +1,29 @@ import os -from jinja2 import Environment, FileSystemLoader + from fastapi import Response +from jinja2 import Environment, FileSystemLoader + +DEFAULT_TEMPLATE_ENVIRONMENT = Environment( + loader=FileSystemLoader("%s/templates/" % os.path.dirname(__file__)) +) -class Templater: - def __init__(self): - self.templates = Environment( - loader=FileSystemLoader("%s/templates/" % os.path.dirname(__file__)) - ) +def render_template(template_name: str, template_environment: Environment, **kwargs): + template = template_environment.get_template(template_name) + return template.render(**kwargs) - def render_template(self, template_name: str, **kwargs): - template = self.templates.get_template(template_name) - return template.render(**kwargs) - def get_connection_twiml(self, call_id: str, base_url: str): - return Response( - self.render_template("connect_call.xml", base_url=base_url, id=call_id), - media_type="application/xml", - ) +def get_connection_twiml( + call_id: str, + base_url: str, + template_environment: Environment = DEFAULT_TEMPLATE_ENVIRONMENT, +): + return Response( + render_template( + template_name="twilio_connect_call.xml", + template_environment=template_environment, + base_url=base_url, + id=call_id, + ), + media_type="application/xml", + ) diff --git a/vocode/streaming/telephony/templates/connect_call.xml b/vocode/streaming/telephony/templates/twilio_connect_call.xml similarity index 92% rename from vocode/streaming/telephony/templates/connect_call.xml rename to vocode/streaming/telephony/templates/twilio_connect_call.xml index 036ffe1bb..75d5036fd 100644 --- a/vocode/streaming/telephony/templates/connect_call.xml +++ b/vocode/streaming/telephony/templates/twilio_connect_call.xml @@ -3,4 +3,4 @@ - \ No newline at end of file + diff --git a/vocode/streaming/transcriber/__init__.py b/vocode/streaming/transcriber/__init__.py deleted file mode 100644 index 6e2eef40c..000000000 --- a/vocode/streaming/transcriber/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from vocode.streaming.transcriber.assembly_ai_transcriber import AssemblyAITranscriber -from vocode.streaming.transcriber.azure_transcriber import AzureTranscriber -from vocode.streaming.transcriber.base_transcriber import BaseTranscriber -from vocode.streaming.transcriber.deepgram_transcriber import DeepgramTranscriber -from vocode.streaming.transcriber.google_transcriber import GoogleTranscriber -from vocode.streaming.transcriber.rev_ai_transcriber import RevAITranscriber -from vocode.streaming.transcriber.whisper_cpp_transcriber import WhisperCPPTranscriber diff --git a/vocode/streaming/transcriber/abstract_factory.py b/vocode/streaming/transcriber/abstract_factory.py new file mode 100644 index 000000000..e89501476 --- /dev/null +++ b/vocode/streaming/transcriber/abstract_factory.py @@ -0,0 +1,16 @@ +from abc import ABC, abstractmethod + +from vocode.streaming.models.transcriber import TranscriberConfig +from vocode.streaming.transcriber.base_transcriber import ( + BaseAsyncTranscriber, + BaseThreadAsyncTranscriber, +) + + +class AbstractTranscriberFactory(ABC): + @abstractmethod + def create_transcriber( + self, + transcriber_config: TranscriberConfig, + ) -> BaseAsyncTranscriber[TranscriberConfig] | BaseThreadAsyncTranscriber[TranscriberConfig]: + pass diff --git a/vocode/streaming/transcriber/assembly_ai_transcriber.py b/vocode/streaming/transcriber/assembly_ai_transcriber.py index 9d18e0a26..47fa12c36 100644 --- a/vocode/streaming/transcriber/assembly_ai_transcriber.py +++ b/vocode/streaming/transcriber/assembly_ai_transcriber.py @@ -1,54 +1,32 @@ import asyncio +import audioop import json -import logging from typing import Optional -import websockets -import audioop -import numpy as np from urllib.parse import urlencode -from vocode import getenv +import numpy as np +import websockets +from loguru import logger + +from vocode import getenv +from vocode.streaming.models.audio import AudioEncoding from vocode.streaming.models.transcriber import ( AssemblyAITranscriberConfig, - TimeEndpointingConfig, PunctuationEndpointingConfig, -) -from vocode.streaming.models.websocket import AudioMessage -from vocode.streaming.transcriber.base_transcriber import ( - BaseAsyncTranscriber, + TimeEndpointingConfig, Transcription, - meter, ) -from vocode.streaming.models.audio_encoding import AudioEncoding - +from vocode.streaming.models.websocket import AudioMessage +from vocode.streaming.transcriber.base_transcriber import BaseAsyncTranscriber ASSEMBLY_AI_URL = "wss://api.assemblyai.com/v2/realtime/ws" -avg_latency_hist = meter.create_histogram( - name="transcriber.assemblyai.avg_latency", - unit="seconds", -) -max_latency_hist = meter.create_histogram( - name="transcriber.assemblyai.max_latency", - unit="seconds", -) -min_latency_hist = meter.create_histogram( - name="transcriber.assemblyai.min_latency", - unit="seconds", -) -duration_hist = meter.create_histogram( - name="transcriber.assemblyai.duration", - unit="seconds", -) - - class AssemblyAITranscriber(BaseAsyncTranscriber[AssemblyAITranscriberConfig]): def __init__( self, transcriber_config: AssemblyAITranscriberConfig, api_key: Optional[str] = None, - logger: Optional[logging.Logger] = None, ): super().__init__(transcriber_config) self.api_key = api_key or getenv("ASSEMBLY_AI_API_KEY") @@ -57,7 +35,6 @@ def __init__( "Please set ASSEMBLY_AI_API_KEY environment variable or pass it as a parameter" ) self._ended = False - self.logger = logger or logging.getLogger(__name__) self.buffer = bytearray() self.audio_cursor = 0 @@ -71,8 +48,7 @@ def __init__( self.terminate_msg = json.dumps({"terminate_session": True}) self.end_utterance_silence_threshold_msg = ( None - if self.transcriber_config.end_utterance_silence_threshold_milliseconds - is None + if self.transcriber_config.end_utterance_silence_threshold_milliseconds is None else json.dumps( { "end_utterance_silence_threshold": self.transcriber_config.end_utterance_silence_threshold_milliseconds @@ -109,9 +85,7 @@ def terminate(self): def get_assembly_ai_url(self): url_params = {"sample_rate": self.transcriber_config.sampling_rate} if self.transcriber_config.word_boost: - url_params.update( - {"word_boost": json.dumps(self.transcriber_config.word_boost)} - ) + url_params.update({"word_boost": json.dumps(self.transcriber_config.word_boost)}) return ASSEMBLY_AI_URL + f"?{urlencode(url_params)}" async def process(self): @@ -138,18 +112,13 @@ async def sender(ws): # sends audio to websocket num_channels = 1 sample_width = 2 self.audio_cursor += len(data) / ( - self.transcriber_config.sampling_rate - * num_channels - * sample_width - ) - await ws.send( - json.dumps({"audio_data": AudioMessage.from_bytes(data).data}) + self.transcriber_config.sampling_rate * num_channels * sample_width ) + await ws.send(json.dumps({"audio_data": AudioMessage.from_bytes(data).data})) await ws.send(self.terminate_msg) - self.logger.debug("Terminating AssemblyAI transcriber sender") + logger.debug("Terminating AssemblyAI transcriber sender") async def receiver(ws): - transcript_cursor = 0.0 while not self._ended: try: result_str = await ws.recv() @@ -157,30 +126,13 @@ async def receiver(ws): if "error" in data and data["error"]: raise Exception(data["error"]) except websockets.exceptions.ConnectionClosedError as e: - self.logger.debug(e) + logger.debug(e) break data = json.loads(result_str) - is_final = ( - "message_type" in data - and data["message_type"] == "FinalTranscript" - ) + is_final = "message_type" in data and data["message_type"] == "FinalTranscript" if "text" in data and data["text"]: - cur_max_latency = self.audio_cursor - transcript_cursor - transcript_cursor = data["audio_end"] / 1000 - cur_min_latency = self.audio_cursor - transcript_cursor - duration = data["audio_end"] / 1000 - data["audio_start"] / 1000 - - avg_latency_hist.record( - (cur_min_latency + cur_max_latency) / 2 * duration - ) - duration_hist.record(duration) - - # Log max and min latencies - max_latency_hist.record(cur_max_latency) - min_latency_hist.record(max(cur_min_latency, 0)) - self.output_queue.put_nowait( Transcription( message=data["text"], diff --git a/vocode/streaming/transcriber/azure_transcriber.py b/vocode/streaming/transcriber/azure_transcriber.py index cebf5d58f..6a804c02e 100644 --- a/vocode/streaming/transcriber/azure_transcriber.py +++ b/vocode/streaming/transcriber/azure_transcriber.py @@ -1,31 +1,28 @@ -import logging import queue +from datetime import datetime, timezone from typing import Optional +import sentry_sdk from azure.cognitiveservices.speech.audio import ( - PushAudioInputStream, AudioStreamFormat, AudioStreamWaveFormat, + PushAudioInputStream, ) +from loguru import logger from vocode import getenv - -from vocode.streaming.models.audio_encoding import AudioEncoding -from vocode.streaming.transcriber.base_transcriber import ( - BaseThreadAsyncTranscriber, - Transcription, -) -from vocode.streaming.models.transcriber import AzureTranscriberConfig +from vocode.streaming.models.audio import AudioEncoding +from vocode.streaming.models.transcriber import AzureTranscriberConfig, Transcription +from vocode.streaming.transcriber.base_transcriber import BaseThreadAsyncTranscriber +from vocode.utils.sentry_utils import CustomSentrySpans, sentry_create_span class AzureTranscriber(BaseThreadAsyncTranscriber[AzureTranscriberConfig]): def __init__( self, transcriber_config: AzureTranscriberConfig, - logger: Optional[logging.Logger] = None, ): super().__init__(transcriber_config) - self.logger = logger format = None if self.transcriber_config.audio_encoding == AudioEncoding.LINEAR16: @@ -67,9 +64,7 @@ def __init__( ) ) - speech_params["auto_detect_source_language_config"] = ( - auto_detect_source_language_config - ) + speech_params["auto_detect_source_language_config"] = auto_detect_source_language_config else: speech_params["language"] = self.transcriber_config.language @@ -79,6 +74,12 @@ def __init__( self.is_ready = False def recognized_sentence_final(self, evt): + + sentry_create_span( + sentry_callable=sentry_sdk.start_span, + op=CustomSentrySpans.LATENCY_OF_CONVERSATION, + start_timestamp=datetime.now(tz=timezone.utc), + ) self.output_janus_queue.sync_q.put_nowait( Transcription(message=evt.result.text, confidence=1.0, is_final=True) ) @@ -92,21 +93,19 @@ def _run_loop(self): stream = self.generator() def stop_cb(evt): - self.logger.debug("CLOSING on {}".format(evt)) + logger.debug("CLOSING on {}".format(evt)) self.speech.stop_continuous_recognition() self._ended = True self.speech.recognizing.connect(lambda x: self.recognized_sentence_stream(x)) self.speech.recognized.connect(lambda x: self.recognized_sentence_final(x)) self.speech.session_started.connect( - lambda evt: self.logger.debug("SESSION STARTED: {}".format(evt)) + lambda evt: logger.debug("SESSION STARTED: {}".format(evt)) ) self.speech.session_stopped.connect( - lambda evt: self.logger.debug("SESSION STOPPED {}".format(evt)) - ) - self.speech.canceled.connect( - lambda evt: self.logger.debug("CANCELED {}".format(evt)) + lambda evt: logger.debug("SESSION STOPPED {}".format(evt)) ) + self.speech.canceled.connect(lambda evt: logger.debug("CANCELED {}".format(evt))) self.speech.session_stopped.connect(stop_cb) self.speech.canceled.connect(stop_cb) diff --git a/vocode/streaming/transcriber/base_transcriber.py b/vocode/streaming/transcriber/base_transcriber.py index 9142be75b..4745b79a6 100644 --- a/vocode/streaming/transcriber/base_transcriber.py +++ b/vocode/streaming/transcriber/base_transcriber.py @@ -2,36 +2,27 @@ import asyncio import audioop -from opentelemetry import trace, metrics -from typing import Generic, TypeVar, Union -from vocode.streaming.models.audio_encoding import AudioEncoding -from vocode.streaming.models.model import BaseModel +from abc import ABC, abstractmethod +from typing import Generic, Optional, TypeVar, Union -from vocode.streaming.models.transcriber import TranscriberConfig +from vocode.streaming.models.audio import AudioEncoding +from vocode.streaming.models.transcriber import TranscriberConfig, Transcription +from vocode.streaming.utils.speed_manager import SpeedManager from vocode.streaming.utils.worker import AsyncWorker, ThreadAsyncWorker - -tracer = trace.get_tracer(__name__) -meter = metrics.get_meter(__name__) - - -class Transcription(BaseModel): - message: str - confidence: float - is_final: bool - is_interrupt: bool = False - - def __str__(self): - return f"Transcription({self.message}, {self.confidence}, {self.is_final})" - - TranscriberConfigType = TypeVar("TranscriberConfigType", bound=TranscriberConfig) -class AbstractTranscriber(Generic[TranscriberConfigType]): +class AbstractTranscriber(Generic[TranscriberConfigType], ABC): def __init__(self, transcriber_config: TranscriberConfigType): self.transcriber_config = transcriber_config self.is_muted = False + self.speed_manager: Optional[SpeedManager] = None + self.input_queue: asyncio.Queue[bytes] = asyncio.Queue() + self.output_queue: asyncio.Queue[Transcription] = asyncio.Queue() + + def attach_speed_manager(self, speed_manager: SpeedManager): + self.speed_manager = speed_manager def mute(self): self.is_muted = True @@ -52,19 +43,9 @@ def create_silent_chunk(self, chunk_size, sample_width=2): elif self.get_transcriber_config().audio_encoding == AudioEncoding.MULAW: return audioop.lin2ulaw(linear_audio, sample_width) - -class BaseAsyncTranscriber(AbstractTranscriber[TranscriberConfigType], AsyncWorker): - def __init__( - self, - transcriber_config: TranscriberConfigType, - ): - self.input_queue: asyncio.Queue[bytes] = asyncio.Queue() - self.output_queue: asyncio.Queue[Transcription] = asyncio.Queue() - AsyncWorker.__init__(self, self.input_queue, self.output_queue) - AbstractTranscriber.__init__(self, transcriber_config) - + @abstractmethod async def _run_loop(self): - raise NotImplementedError + pass def send_audio(self, chunk): if not self.is_muted: @@ -72,31 +53,31 @@ def send_audio(self, chunk): else: self.consume_nonblocking(self.create_silent_chunk(len(chunk))) + @abstractmethod + def terminate(self): + pass + + +class BaseAsyncTranscriber(AbstractTranscriber[TranscriberConfigType], AsyncWorker): + def __init__(self, transcriber_config: TranscriberConfigType): + AbstractTranscriber.__init__(self, transcriber_config) + AsyncWorker.__init__(self, self.input_queue, self.output_queue) + + async def _run_loop(self): + raise NotImplementedError + def terminate(self): AsyncWorker.terminate(self) -class BaseThreadAsyncTranscriber( - AbstractTranscriber[TranscriberConfigType], ThreadAsyncWorker -): - def __init__( - self, - transcriber_config: TranscriberConfigType, - ): - self.input_queue: asyncio.Queue[bytes] = asyncio.Queue() - self.output_queue: asyncio.Queue[Transcription] = asyncio.Queue() - ThreadAsyncWorker.__init__(self, self.input_queue, self.output_queue) +class BaseThreadAsyncTranscriber(AbstractTranscriber[TranscriberConfigType], ThreadAsyncWorker): + def __init__(self, transcriber_config: TranscriberConfigType): AbstractTranscriber.__init__(self, transcriber_config) + ThreadAsyncWorker.__init__(self, self.input_queue, self.output_queue) def _run_loop(self): raise NotImplementedError - def send_audio(self, chunk): - if not self.is_muted: - self.consume_nonblocking(chunk) - else: - self.consume_nonblocking(self.create_silent_chunk(len(chunk))) - def terminate(self): ThreadAsyncWorker.terminate(self) diff --git a/vocode/streaming/transcriber/deepgram_transcriber.py b/vocode/streaming/transcriber/deepgram_transcriber.py index ce91ec290..d602f0c8e 100644 --- a/vocode/streaming/transcriber/deepgram_transcriber.py +++ b/vocode/streaming/transcriber/deepgram_transcriber.py @@ -1,108 +1,123 @@ import asyncio import json -import logging -from typing import Optional +import os +from datetime import datetime, timezone +from typing import List, Optional, Tuple, Union +from urllib.parse import urlencode + +import sentry_sdk import websockets +from loguru import logger +from pydantic.v1 import BaseModel, Field from websockets.client import WebSocketClientProtocol -import audioop -from urllib.parse import urlencode -from vocode import getenv -from vocode.streaming.transcriber.base_transcriber import ( - BaseAsyncTranscriber, - Transcription, - meter, -) +from vocode.streaming.models.audio import AudioEncoding from vocode.streaming.models.transcriber import ( + DEEPGRAM_API_WS_URL, DeepgramTranscriberConfig, EndpointingConfig, - EndpointingType, PunctuationEndpointingConfig, TimeEndpointingConfig, + Transcription, ) -from vocode.streaming.models.audio_encoding import AudioEncoding - +from vocode.streaming.transcriber.base_transcriber import BaseAsyncTranscriber +from vocode.utils.sentry_utils import CustomSentrySpans, sentry_configured, sentry_create_span PUNCTUATION_TERMINATORS = [".", "!", "?"] NUM_RESTARTS = 5 +NUM_AUDIO_CHANNELS = 1 -avg_latency_hist = meter.create_histogram( - name="transcriber.deepgram.avg_latency", - unit="seconds", -) -max_latency_hist = meter.create_histogram( - name="transcriber.deepgram.max_latency", - unit="seconds", -) -min_latency_hist = meter.create_histogram( - name="transcriber.deepgram.min_latency", - unit="seconds", -) -duration_hist = meter.create_histogram( - name="transcriber.deepgram.duration", - unit="seconds", -) +def now(): + return datetime.now(tz=timezone.utc) + + +class TimeSilentConfig(BaseModel): + time_cutoff_seconds: float = 1 + post_punctuation_time_seconds: float = 0.5 + + +class InternalPunctuationEndpointingConfig( # type: ignore + EndpointingConfig, type="internal_punctuation_based" +): + time_silent_config: TimeSilentConfig = Field(default_factory=TimeSilentConfig) + use_single_utterance_endpointing_for_first_utterance: bool = False + + +class DeepgramEndpointingConfig(EndpointingConfig, type="deepgram"): # type: ignore + vad_threshold_ms: int = 500 + utterance_cutoff_ms: int = 1000 + time_silent_config: Optional[TimeSilentConfig] = Field(default_factory=TimeSilentConfig) + use_single_utterance_endpointing_for_first_utterance: bool = False + + +class DeepgramUtteranceEnd(BaseModel): + pass + + def __str__(self): + return "DeepgramUtteranceEnd()" + + +class DeepgramTranscriptionResult(BaseModel): + class TranscriptionChoice(BaseModel): + transcript: str + confidence: float + words: List[dict] + + is_final: bool + speech_final: bool + top_choice: TranscriptionChoice + start: float + duration: float + + def __str__(self): + return f"DeepgramTranscriptionResult(transcript={self.top_choice.transcript}, is_final={self.is_final}, speech_final={self.speech_final})" class DeepgramTranscriber(BaseAsyncTranscriber[DeepgramTranscriberConfig]): def __init__( self, transcriber_config: DeepgramTranscriberConfig, - api_key: Optional[str] = None, - logger: Optional[logging.Logger] = None, ): super().__init__(transcriber_config) - self.api_key = api_key or getenv("DEEPGRAM_API_KEY") - if not self.api_key: - raise Exception( - "Please set DEEPGRAM_API_KEY environment variable or pass it as a parameter" - ) + self.api_key = os.environ["DEEPGRAM_API_KEY"] self._ended = False self.is_ready = False - self.logger = logger or logging.getLogger(__name__) self.audio_cursor = 0.0 + self.transcript_cursor = 0.0 - async def _run_loop(self): - restarts = 0 - while not self._ended and restarts < NUM_RESTARTS: - await self.process() - restarts += 1 - self.logger.debug( - "Deepgram connection died, restarting, num_restarts: %s", restarts - ) + self.ws_url = getattr(transcriber_config, "ws_url", DEEPGRAM_API_WS_URL) - def send_audio(self, chunk): - if ( - self.transcriber_config.downsampling - and self.transcriber_config.audio_encoding == AudioEncoding.LINEAR16 - ): - chunk, _ = audioop.ratecv( - chunk, - 2, - 1, - self.transcriber_config.sampling_rate - * self.transcriber_config.downsampling, - self.transcriber_config.sampling_rate, - None, - ) - super().send_audio(chunk) + self.min_latency = 0.0 + self.max_latency = 0.0 + self.avg_latency = 0.0 - def terminate(self): - terminate_msg = json.dumps({"type": "CloseStream"}) - self.input_queue.put_nowait(terminate_msg) - self._ended = True - super().terminate() + self.avg_latency_numer = 0.0 + self.avg_latency_denom = 0.0 + + self.start_ts: Optional[datetime] = None + self.connected_ts: Optional[datetime] = None + self.start_sending_ts: Optional[datetime] = None + self.start_receiving_ts: Optional[datetime] = None + + self.is_first_transcription = True + + def _get_speed_coefficient(self): + return self.speed_manager.get_speed_coefficient() if self.speed_manager else 1.0 def get_deepgram_url(self): if self.transcriber_config.audio_encoding == AudioEncoding.LINEAR16: encoding = "linear16" elif self.transcriber_config.audio_encoding == AudioEncoding.MULAW: encoding = "mulaw" + else: + raise Exception( + f"Audio encoding not supported {self.transcriber_config.audio_encoding}" + ) url_params = { "encoding": encoding, "sample_rate": self.transcriber_config.sampling_rate, - "channels": 1, + "channels": NUM_AUDIO_CHANNELS, "interim_results": "true", } extra_params = {} @@ -116,150 +131,517 @@ def get_deepgram_url(self): extra_params["version"] = self.transcriber_config.version if self.transcriber_config.keywords: extra_params["keywords"] = self.transcriber_config.keywords - if ( - self.transcriber_config.endpointing_config - and self.transcriber_config.endpointing_config.type - == EndpointingType.PUNCTUATION_BASED + if self.transcriber_config.endpointing_config and ( + isinstance( + self.transcriber_config.endpointing_config, + PunctuationEndpointingConfig, + ) + or isinstance( + self.transcriber_config.endpointing_config, + InternalPunctuationEndpointingConfig, + ) + or isinstance( + self.transcriber_config.endpointing_config, + DeepgramEndpointingConfig, + ) ): extra_params["punctuate"] = "true" + if isinstance( + self.transcriber_config.endpointing_config, + DeepgramEndpointingConfig, + ): + extra_params["endpointing"] = int( + self.transcriber_config.endpointing_config.vad_threshold_ms + * (1 / self._get_speed_coefficient()) + ) + extra_params["utterance_end_ms"] = max( + int( + self.transcriber_config.endpointing_config.utterance_cutoff_ms + * (1 / self._get_speed_coefficient()) + ), + 1000, + ) # Deepgram recommends using at least 1000ms since the tick period is ~1s url_params.update(extra_params) - return f"wss://api.deepgram.com/v1/listen?{urlencode(url_params)}" + return f"{self.ws_url}/v1/listen?{urlencode(url_params)}" + + async def _run_loop(self): + restarts = 0 + while not self._ended and restarts < NUM_RESTARTS: + await self.process() + restarts += 1 + logger.debug(f"Deepgram connection died, restarting, num_restarts: {restarts}") + + logger.error("Deepgram connection died, not restarting") - def is_speech_final( - self, current_buffer: str, deepgram_response: dict, time_silent: float + def terminate(self): + self._track_latency_of_transcription_start() + # Put this in logs until we sentry metrics show up + # properly on dashboard + logger.info( + f"Transcription latency is {self.avg_latency:.4f}s", + extra={ + "avg_latency": self.avg_latency, + "min_latency": self.min_latency, + "max_latency": self.max_latency, + }, + ) + terminate_msg = json.dumps({"type": "CloseStream"}).encode("utf-8") + self.input_queue.put_nowait(terminate_msg) + self._ended = True + super().terminate() + + def get_input_sample_width(self): + encoding = self.transcriber_config.audio_encoding + if encoding == AudioEncoding.LINEAR16: + return 2 + elif encoding == AudioEncoding.MULAW: + return 1 + else: + raise Exception(f"Audio encoding not supported {encoding}") + + def get_byte_rate(self): + sample_width = self.get_input_sample_width() + sample_rate = self.transcriber_config.sampling_rate + return sample_width * sample_rate * NUM_AUDIO_CHANNELS + + def is_endpoint( + self, + current_buffer: str, + deepgram_response: Union[DeepgramUtteranceEnd, DeepgramTranscriptionResult], + time_silent: float, ): - transcript = deepgram_response["channel"]["alternatives"][0]["transcript"] + is_endpoint, log_params = self._compute_is_endpoint_and_log_params( + current_buffer, deepgram_response, time_silent + ) + if is_endpoint: + logger.info("Endpoint detected", extra=log_params) + return is_endpoint - # if it is not time based, then return true if speech is final and there is a transcript - if not self.transcriber_config.endpointing_config: - return transcript and deepgram_response["speech_final"] - elif isinstance( - self.transcriber_config.endpointing_config, TimeEndpointingConfig + @staticmethod + def _satisfies_time_cutoff( + *, + seconds: float, + deepgram_response: Union[DeepgramUtteranceEnd, DeepgramTranscriptionResult], + current_buffer: str, + time_silent: float, + ): + return ( + isinstance(deepgram_response, DeepgramTranscriptionResult) + and not deepgram_response.top_choice.transcript + and len(current_buffer) > 0 + and (time_silent + deepgram_response.duration) > seconds + ) + + def _compute_is_endpoint_and_update_log_params_based_on_time_silent( + self, + current_buffer: str, + deepgram_response: DeepgramTranscriptionResult, + time_silent: float, + time_silent_config: TimeSilentConfig, + existing_log_params: dict, + ) -> bool: + if current_buffer.strip(): + if current_buffer.strip()[ + -1 + ] in PUNCTUATION_TERMINATORS and self._satisfies_time_cutoff( + seconds=time_silent_config.post_punctuation_time_seconds + * (1.0 / self._get_speed_coefficient()), + deepgram_response=deepgram_response, + current_buffer=current_buffer, + time_silent=time_silent, + ): + existing_log_params["source"] = "punctuation" + return True + elif self._satisfies_time_cutoff( + seconds=time_silent_config.time_cutoff_seconds + * (1.0 / self._get_speed_coefficient()), + deepgram_response=deepgram_response, + current_buffer=current_buffer, + time_silent=time_silent, + ): + existing_log_params["source"] = "time_cutoff" + return True + return False + + def _compute_is_endpoint_and_log_params( + self, + current_buffer: str, + deepgram_response: Union[DeepgramUtteranceEnd, DeepgramTranscriptionResult], + time_silent: float, + ) -> Tuple[bool, dict]: + endpointing_config = self.transcriber_config.endpointing_config + assert endpointing_config is not None + + log_params = {"endpointing_type": endpointing_config.type} + + if isinstance( + endpointing_config, + TimeEndpointingConfig, ): # if it is time based, then return true if there is no transcript # and there is some speech to send # and the time_silent is greater than the cutoff return ( - not transcript - and current_buffer - and (time_silent + deepgram_response["duration"]) - > self.transcriber_config.endpointing_config.time_cutoff_seconds + self._satisfies_time_cutoff( + seconds=endpointing_config.time_cutoff_seconds, + deepgram_response=deepgram_response, + current_buffer=current_buffer, + time_silent=time_silent, + ), + log_params, ) elif isinstance( - self.transcriber_config.endpointing_config, PunctuationEndpointingConfig + endpointing_config, + DeepgramEndpointingConfig, ): - return ( - transcript - and deepgram_response["speech_final"] - and transcript.strip()[-1] in PUNCTUATION_TERMINATORS - ) or ( - not transcript - and current_buffer - and (time_silent + deepgram_response["duration"]) - > self.transcriber_config.endpointing_config.time_cutoff_seconds - ) - raise Exception("Endpointing config not supported") + if ( + isinstance(deepgram_response, DeepgramTranscriptionResult) + and self.is_first_transcription + and endpointing_config.use_single_utterance_endpointing_for_first_utterance + ): + if ( + deepgram_response.top_choice.transcript + and deepgram_response.top_choice.transcript.strip()[-1] + in PUNCTUATION_TERMINATORS + ): + log_params["source"] = "is_final" + return True, log_params + if isinstance(deepgram_response, DeepgramUtteranceEnd): + log_params["source"] = "utterance_end" + return True, log_params + elif isinstance(deepgram_response, DeepgramTranscriptionResult): + if deepgram_response.top_choice.transcript and deepgram_response.speech_final: + log_params["source"] = "speech_final" + return True, log_params + elif ( + endpointing_config.time_silent_config is not None + and self._compute_is_endpoint_and_update_log_params_based_on_time_silent( + current_buffer, + deepgram_response, + time_silent, + endpointing_config.time_silent_config, + log_params, + ) + ): + return True, log_params + return False, log_params + + if isinstance(deepgram_response, DeepgramTranscriptionResult): + if isinstance( + endpointing_config, + PunctuationEndpointingConfig, + ): + if ( + deepgram_response.top_choice.transcript + and deepgram_response.speech_final + and deepgram_response.top_choice.transcript.strip()[-1] + in PUNCTUATION_TERMINATORS + ): + log_params["source"] = "punctuation" + return True, log_params + elif self._satisfies_time_cutoff( + seconds=endpointing_config.time_cutoff_seconds + * (1.0 / self._get_speed_coefficient()), + deepgram_response=deepgram_response, + current_buffer=current_buffer, + time_silent=time_silent, + ): + log_params["source"] = "time_cutoff" + return True, log_params + elif isinstance( + endpointing_config, + InternalPunctuationEndpointingConfig, + ): + if ( + self.is_first_transcription + and endpointing_config.use_single_utterance_endpointing_for_first_utterance + ): + if deepgram_response.top_choice.transcript and deepgram_response.speech_final: + log_params["source"] = "speech_final" + return True, log_params + if self._compute_is_endpoint_and_update_log_params_based_on_time_silent( + current_buffer, + deepgram_response, + time_silent, + endpointing_config.time_silent_config, + log_params, + ): + return True, log_params + return False, log_params - def calculate_time_silent(self, data: dict): - end = data["start"] + data["duration"] - words = data["channel"]["alternatives"][0]["words"] + def calculate_time_silent(self, deepgram_transcription_result: DeepgramTranscriptionResult): + end = deepgram_transcription_result.start + deepgram_transcription_result.duration + words = deepgram_transcription_result.top_choice.words if words: return end - words[-1]["end"] - return data["duration"] + return deepgram_transcription_result.duration + + def calculate_duration(self, words: List[dict]) -> float: + if len(words) == 0: + return 0.0 + return words[-1]["end"] - words[0]["start"] async def process(self): self.audio_cursor = 0.0 + self.start_ts = now() + extra_headers = {"Authorization": f"Token {self.api_key}"} + deepgram_url = self.get_deepgram_url() + logger.info(f"Connecting to Deepgram at {deepgram_url}") - async with websockets.connect( - self.get_deepgram_url(), extra_headers=extra_headers - ) as ws: - - async def sender(ws: WebSocketClientProtocol): # sends audio to websocket - while not self._ended: - try: - data = await asyncio.wait_for(self.input_queue.get(), 5) - except asyncio.exceptions.TimeoutError: - break - num_channels = 1 - sample_width = 2 - self.audio_cursor += len(data) / ( - self.transcriber_config.sampling_rate - * num_channels - * sample_width - ) - await ws.send(data) - self.logger.debug("Terminating Deepgram transcriber sender") - - async def receiver(ws: WebSocketClientProtocol): - buffer = "" - buffer_avg_confidence = 0 - num_buffer_utterances = 1 - time_silent = 0 - transcript_cursor = 0.0 - while not self._ended: - try: - msg = await ws.recv() - except Exception as e: - self.logger.debug(f"Got error {e} in Deepgram receiver") - break - data = json.loads(msg) - if ( - not "is_final" in data - ): # means we've finished receiving transcriptions - break - cur_max_latency = self.audio_cursor - transcript_cursor - transcript_cursor = data["start"] + data["duration"] - cur_min_latency = self.audio_cursor - transcript_cursor - - avg_latency_hist.record( - (cur_min_latency + cur_max_latency) / 2 * data["duration"] - ) - duration_hist.record(data["duration"]) + try: + async with websockets.connect(deepgram_url, extra_headers=extra_headers) as ws: + self.connected_ts = now() + + async def sender( + ws: WebSocketClientProtocol, + ): # sends audio to websocket + byte_rate = self.get_byte_rate() - # Log max and min latencies - max_latency_hist.record(cur_max_latency) - min_latency_hist.record(max(cur_min_latency, 0)) + while not self._ended: + try: + data = await asyncio.wait_for(self.input_queue.get(), 5) + except asyncio.exceptions.TimeoutError: + break - is_final = data["is_final"] - speech_final = self.is_speech_final(buffer, data, time_silent) - top_choice = data["channel"]["alternatives"][0] - confidence = top_choice["confidence"] + self.audio_cursor += len(data) / byte_rate + + if not self.start_sending_ts: + self.start_sending_ts = now() + + await ws.send(data) + + logger.debug("Terminating Deepgram transcriber sender") + + async def receiver(ws: WebSocketClientProtocol): + buffer = "" + buffer_avg_confidence = 0.0 + num_buffer_utterances = 1 + time_silent = 0.0 + words_buffer = [] + is_final_ts: Optional[datetime] = None + + while not self._ended: + try: + msg = await ws.recv() + if not self.start_receiving_ts: + self.start_receiving_ts = now() + except Exception as e: + logger.debug(f"Got error {e} in Deepgram receiver") + break + data = json.loads(msg) + + if "start" in data and "duration" in data: + self._track_transcription_latency( + start=data["start"], + duration=data["duration"], + ) - if top_choice["transcript"] and confidence > 0.0 and is_final: - buffer = f"{buffer} {top_choice['transcript']}" - if buffer_avg_confidence == 0: - buffer_avg_confidence = confidence + deepgram_response: Union[DeepgramUtteranceEnd, DeepgramTranscriptionResult] + + if data["type"] == "Results": + deepgram_response = DeepgramTranscriptionResult( + is_final=data["is_final"], + speech_final=data["speech_final"], + top_choice=data["channel"]["alternatives"][0], + duration=data["duration"], + start=data["start"], + ) + elif data["type"] == "UtteranceEnd": + deepgram_response = DeepgramUtteranceEnd() else: - buffer_avg_confidence = ( - buffer_avg_confidence - + confidence / (num_buffer_utterances) - ) * (num_buffer_utterances / (num_buffer_utterances + 1)) - num_buffer_utterances += 1 - - if speech_final: - self.output_queue.put_nowait( - Transcription( - message=buffer, - confidence=buffer_avg_confidence, - is_final=True, + logger.info(f"Ignoring deepgram response type: {data['type']}") + continue + + if ( + isinstance(deepgram_response, DeepgramTranscriptionResult) + and deepgram_response.top_choice.transcript + and deepgram_response.top_choice.confidence > 0.0 + and deepgram_response.is_final + ): + words = deepgram_response.top_choice.words + if words: + words_buffer.extend(words) + buffer = f"{buffer} {deepgram_response.top_choice.transcript}" + if buffer_avg_confidence == 0: + buffer_avg_confidence = deepgram_response.top_choice.confidence + else: + buffer_avg_confidence = ( + buffer_avg_confidence + + deepgram_response.top_choice.confidence + / (num_buffer_utterances) + ) * (num_buffer_utterances / (num_buffer_utterances + 1)) + num_buffer_utterances += 1 + + is_final_ts = now() + + if buffer and self.is_endpoint(buffer, deepgram_response, time_silent): + output_ts = now() + self._track_latency_of_conversation( + is_final_ts=is_final_ts, + output_ts=output_ts, ) - ) - buffer = "" - buffer_avg_confidence = 0 - num_buffer_utterances = 1 - time_silent = 0 - elif top_choice["transcript"] and confidence > 0.0: - self.output_queue.put_nowait( - Transcription( - message=buffer, - confidence=confidence, - is_final=False, + self.output_queue.put_nowait( + Transcription( + message=buffer, + confidence=buffer_avg_confidence, + is_final=True, + duration_seconds=self.calculate_duration(words_buffer), + ) ) - ) - time_silent = self.calculate_time_silent(data) - else: - time_silent += data["duration"] - self.logger.debug("Terminating Deepgram transcriber receiver") + buffer = "" + buffer_avg_confidence = 0.0 + num_buffer_utterances = 1 + time_silent = 0.0 + words_buffer = [] + is_final_ts = None + + if isinstance(deepgram_response, DeepgramTranscriptionResult): + if ( + isinstance(deepgram_response, DeepgramTranscriptionResult) + and deepgram_response.top_choice.transcript + and deepgram_response.top_choice.confidence > 0.0 + ): + if not deepgram_response.is_final: + interim_message = ( + f"{buffer} {deepgram_response.top_choice.transcript}" + ) + else: + interim_message = buffer + + self.output_queue.put_nowait( + Transcription( + message=interim_message, + confidence=deepgram_response.top_choice.confidence, + is_final=False, + ) + ) + time_silent = self.calculate_time_silent(deepgram_response) + else: + time_silent += deepgram_response.duration + + logger.debug("Terminating Deepgram transcriber receiver") + + await asyncio.gather(sender(ws), receiver(ws)) + + except asyncio.exceptions.TimeoutError: + raise + + @sentry_configured + def _track_latency_of_transcription_start( + self, + ): + with sentry_create_span( + sentry_callable=sentry_sdk.start_span, + op=CustomSentrySpans.LATENCY_OF_TRANSCRIPTION_START, + start_timestamp=self.start_ts, + ) as transcription_span: + + with sentry_create_span( + sentry_callable=transcription_span.start_child, + op=CustomSentrySpans.START_TO_CONNECTION, + start_timestamp=self.start_ts, + ) as span: + span.finish(end_timestamp=self.connected_ts) + + with sentry_create_span( + sentry_callable=transcription_span.start_child, + op=CustomSentrySpans.CONNECTED_TO_FIRST_SEND, + start_timestamp=self.connected_ts, + ) as span: + span.finish(end_timestamp=self.start_sending_ts) + + with sentry_create_span( + sentry_callable=transcription_span.start_child, + op=CustomSentrySpans.FIRST_SEND_TO_FIRST_RECEIVE, + start_timestamp=self.start_sending_ts, + ) as span: + span.finish(end_timestamp=self.start_receiving_ts) + transcription_span.finish(end_timestamp=self.start_receiving_ts) + + def _track_transcription_latency(self, start: float, duration: float): + cur_max_latency = self.audio_cursor - self.transcript_cursor + transcript_cursor = start + duration + cur_min_latency = self.audio_cursor - transcript_cursor + + self.max_latency = max(self.max_latency or 0, cur_max_latency) + self.min_latency = min(self.min_latency or 10**6, cur_min_latency) + + self.avg_latency_numer += (cur_min_latency + cur_max_latency) / 2 * duration + self.avg_latency_denom += duration + self.avg_latency = self.avg_latency_numer / (self.avg_latency_denom or 1) + + def _track_latency_of_conversation( + self, + *, + # is_final_spoken_ts: Optional[datetime], + is_final_ts: Optional[datetime], + output_ts: datetime, + ): + if not ( + output_ts + and is_final_ts + # and is_final_spoken_ts + ): + logger.info("Skipping latency measurement when not all timestamps are set") + return + + if not (output_ts > is_final_ts): # > is_final_spoken_ts + logger.error("Skipping latency measurement when timestamps are not in order") + return + logger.debug( + f"Endpoint detected, tracking endpointing_latency={output_ts - is_final_ts}", + ) + + # Ideally, we want to start a latency measurement for the entire conversation delay: + # from when the user stopped speaking, to the time we start sending audio back. + # Currently we don't have a way to find from Deepgram what the timetamp is + # corresponding to their 0.0 in the transcript_cursor and we have observed that + # the audio_cursor is always less than the transcript cursor, which seems to + # indicate there is something off in our math for the audio cursor. The audio cursor + # should represent the total number of seconds of audio that we have submitted to + # Deepgram and should roughly line up with the transcript cursor. + # + # Until we can find a reliable way to find is_final_spoken_ts, we are skipping on + # sending the transcription_latency span, instead focus on the endpointing_latency + # + # There was previous work done using the last word "end" cursor offset from Deepgram + # in [EPD-926]. However, for similar reasons the logic for adding that to the + # start_receiving_ts created on our end resulted in times for that audio that were + # later than "is_final" which does not make sense temporally. We believe that is due + # to not having an accurate timestamp corresponding to deepgram's 0.0 audio_cursor offset. + + # Span: latency_of_conversation + + # Once we have reliable way to find is_final_spoken_ts we would use that + # here instead, and uncomment the transcription_latency span + # start_timestamp=is_final_spoken_ts, + latency_of_conversation_span = sentry_create_span( + sentry_callable=sentry_sdk.start_span, + op=CustomSentrySpans.LATENCY_OF_CONVERSATION, + start_timestamp=is_final_ts, + ) + + # Span: latency_of_conversation.transcription_latency + # Transcription latency is the time between audio was sent to deepgram for the + # last word in the buffer when we set `is_final_ts` and then start + # running + # Time from `is_final_spoken_ts` to `is_final_ts` + # with sentry_create_span( + # sentry_callable=latency_of_conversation_span.start_child, + # op="transcription_latency", + # start_timestamp=is_final_spoken_ts, + # ) as span: + # span.finish(end_timestamp=is_final_ts) - await asyncio.gather(sender(ws), receiver(ws)) + # Span: latency_of_conversation.endpointing_latency + # Endpointing latency is the time from when we receive the last is_final + # message from Deepgram and when we send output to the next stage. + # Time from `is_final_ts` to `output_ts` + if latency_of_conversation_span: + with sentry_create_span( + sentry_callable=latency_of_conversation_span.start_child, + op=CustomSentrySpans.ENDPOINTING_LATENCY, + start_timestamp=is_final_ts, + ) as span: + span.finish(end_timestamp=output_ts) diff --git a/vocode/streaming/transcriber/factory.py b/vocode/streaming/transcriber/default_factory.py similarity index 63% rename from vocode/streaming/transcriber/factory.py rename to vocode/streaming/transcriber/default_factory.py index 5974b266c..3a1044313 100644 --- a/vocode/streaming/transcriber/factory.py +++ b/vocode/streaming/transcriber/default_factory.py @@ -1,37 +1,37 @@ -import logging -from typing import Optional -import typing from vocode.streaming.models.transcriber import ( AssemblyAITranscriberConfig, AzureTranscriberConfig, DeepgramTranscriberConfig, + GladiaTranscriberConfig, GoogleTranscriberConfig, RevAITranscriberConfig, TranscriberConfig, - TranscriberType, ) +from vocode.streaming.transcriber.abstract_factory import AbstractTranscriberFactory from vocode.streaming.transcriber.assembly_ai_transcriber import AssemblyAITranscriber +from vocode.streaming.transcriber.azure_transcriber import AzureTranscriber from vocode.streaming.transcriber.deepgram_transcriber import DeepgramTranscriber +from vocode.streaming.transcriber.gladia_transcriber import GladiaTranscriber from vocode.streaming.transcriber.google_transcriber import GoogleTranscriber from vocode.streaming.transcriber.rev_ai_transcriber import RevAITranscriber -from vocode.streaming.transcriber.azure_transcriber import AzureTranscriber -class TranscriberFactory: +class DefaultTranscriberFactory(AbstractTranscriberFactory): def create_transcriber( self, transcriber_config: TranscriberConfig, - logger: Optional[logging.Logger] = None, ): if isinstance(transcriber_config, DeepgramTranscriberConfig): - return DeepgramTranscriber(transcriber_config, logger=logger) + return DeepgramTranscriber(transcriber_config) elif isinstance(transcriber_config, GoogleTranscriberConfig): - return GoogleTranscriber(transcriber_config, logger=logger) + return GoogleTranscriber(transcriber_config) elif isinstance(transcriber_config, AssemblyAITranscriberConfig): - return AssemblyAITranscriber(transcriber_config, logger=logger) + return AssemblyAITranscriber(transcriber_config) elif isinstance(transcriber_config, RevAITranscriberConfig): - return RevAITranscriber(transcriber_config, logger=logger) + return RevAITranscriber(transcriber_config) elif isinstance(transcriber_config, AzureTranscriberConfig): - return AzureTranscriber(transcriber_config, logger=logger) + return AzureTranscriber(transcriber_config) + elif isinstance(transcriber_config, GladiaTranscriberConfig): + return GladiaTranscriber(transcriber_config) else: raise Exception("Invalid transcriber config") diff --git a/vocode/streaming/transcriber/gladia_transcriber.py b/vocode/streaming/transcriber/gladia_transcriber.py index 7c76007d0..54366035a 100644 --- a/vocode/streaming/transcriber/gladia_transcriber.py +++ b/vocode/streaming/transcriber/gladia_transcriber.py @@ -1,22 +1,17 @@ import asyncio +import audioop import json -import base64 -import logging from typing import Optional -import websockets -import audioop + import numpy as np -from urllib.parse import urlencode -from vocode import getenv +import websockets +from loguru import logger -from vocode.streaming.models.transcriber import GladiaTranscriberConfig +from vocode import getenv +from vocode.streaming.models.audio import AudioEncoding +from vocode.streaming.models.transcriber import GladiaTranscriberConfig, Transcription from vocode.streaming.models.websocket import AudioMessage -from vocode.streaming.transcriber.base_transcriber import ( - BaseAsyncTranscriber, - Transcription, -) -from vocode.streaming.models.audio_encoding import AudioEncoding - +from vocode.streaming.transcriber.base_transcriber import BaseAsyncTranscriber GLADIA_URL = "wss://api.gladia.io/audio/text/audio-transcription" @@ -26,7 +21,6 @@ def __init__( self, transcriber_config: GladiaTranscriberConfig, api_key: Optional[str] = None, - logger: Optional[logging.Logger] = None, ): super().__init__(transcriber_config) self.api_key = api_key or getenv("GLADIA_API_KEY") @@ -35,7 +29,6 @@ def __init__( "Please set GLADIA_API_KEY environment variable or pass it as a parameter" ) self._ended = False - self.logger = logger or logging.getLogger(__name__) if self.transcriber_config.endpointing_config: raise Exception("Gladia endpointing config not supported yet") @@ -94,7 +87,7 @@ async def sender(ws): } ) ) - self.logger.debug("Terminating Gladia transcriber sender") + logger.debug("Terminating Gladia transcriber sender") async def receiver(ws): while not self._ended: @@ -104,7 +97,7 @@ async def receiver(ws): if "error" in data and data["error"]: raise Exception(data["error"]) except websockets.exceptions.ConnectionClosedError as e: - self.logger.debug(e) + logger.debug(e) break if data: diff --git a/vocode/streaming/transcriber/google_transcriber.py b/vocode/streaming/transcriber/google_transcriber.py index 7205f74a3..5f3da9a68 100644 --- a/vocode/streaming/transcriber/google_transcriber.py +++ b/vocode/streaming/transcriber/google_transcriber.py @@ -1,19 +1,8 @@ -import asyncio -import logging -import os -import time import queue -from typing import Optional -import threading -from vocode import getenv -from vocode.streaming.models.audio_encoding import AudioEncoding -from vocode.streaming.transcriber.base_transcriber import ( - BaseThreadAsyncTranscriber, - Transcription, -) -from vocode.streaming.models.transcriber import GoogleTranscriberConfig -from vocode.streaming.utils import create_loop_in_thread +from vocode.streaming.models.audio import AudioEncoding +from vocode.streaming.models.transcriber import GoogleTranscriberConfig, Transcription +from vocode.streaming.transcriber.base_transcriber import BaseThreadAsyncTranscriber # TODO: make this nonblocking so it can run in the main thread, see speech.async_client.SpeechAsyncClient @@ -21,12 +10,11 @@ class GoogleTranscriber(BaseThreadAsyncTranscriber[GoogleTranscriberConfig]): def __init__( self, transcriber_config: GoogleTranscriberConfig, - logger: Optional[logging.Logger] = None, ): super().__init__(transcriber_config) - from google.cloud import speech import google.auth + from google.cloud import speech google.auth.default() self.speech = speech @@ -64,12 +52,9 @@ def create_google_streaming_config(self): def _run_loop(self): stream = self.generator() requests = ( - self.speech.StreamingRecognizeRequest(audio_content=content) - for content in stream - ) - responses = self.client.streaming_recognize( - self.google_streaming_config, requests + self.speech.StreamingRecognizeRequest(audio_content=content) for content in stream ) + responses = self.client.streaming_recognize(self.google_streaming_config, requests) self.process_responses_loop(responses) def terminate(self): @@ -96,9 +81,7 @@ def _on_response(self, response): confidence = top_choice.confidence self.output_janus_queue.sync_q.put_nowait( - Transcription( - message=message, confidence=confidence, is_final=result.is_final - ) + Transcription(message=message, confidence=confidence, is_final=result.is_final) ) def generator(self): diff --git a/vocode/streaming/transcriber/rev_ai_transcriber.py b/vocode/streaming/transcriber/rev_ai_transcriber.py index 075ddf633..856768695 100644 --- a/vocode/streaming/transcriber/rev_ai_transcriber.py +++ b/vocode/streaming/transcriber/rev_ai_transcriber.py @@ -1,22 +1,19 @@ import asyncio import json -import logging +import time from typing import Optional + import websockets +from loguru import logger from websockets.client import WebSocketClientProtocol -from vocode import getenv -import time -from vocode.streaming.transcriber.base_transcriber import ( - BaseAsyncTranscriber, - Transcription, -) +from vocode import getenv from vocode.streaming.models.transcriber import ( RevAITranscriberConfig, - EndpointingType, TimeEndpointingConfig, + Transcription, ) - +from vocode.streaming.transcriber.base_transcriber import BaseAsyncTranscriber NUM_RESTARTS = 5 @@ -30,7 +27,6 @@ def __init__( self, transcriber_config: RevAITranscriberConfig, api_key: Optional[str] = None, - logger: Optional[logging.Logger] = None, ): super().__init__(transcriber_config) self.api_key = api_key or getenv("REV_AI_API_KEY") @@ -40,7 +36,6 @@ def __init__( ) self.closed = False self.is_ready = True - self.logger = logger or logging.getLogger(__name__) self.last_signal_seconds = 0 async def ready(self): @@ -53,7 +48,9 @@ def get_rev_ai_url(self): audio_format = "S16LE" channels = 1 - content_type = f"{codec};layout={layout};rate={rate};format={audio_format};channels={channels}" + content_type = ( + f"{codec};layout={layout};rate={rate};format={audio_format};channels={channels}" + ) url_params_dict = { "access_token": self.api_key, @@ -61,7 +58,7 @@ def get_rev_ai_url(self): } url_params_arr = [f"{key}={value}" for (key, value) in url_params_dict.items()] - url = f"wss://api.rev.ai/speechtotext/v1/stream?" + "&".join(url_params_arr) + url = "wss://api.rev.ai/speechtotext/v1/stream?" + "&".join(url_params_arr) return url async def _run_loop(self): @@ -69,9 +66,7 @@ async def _run_loop(self): while not self.closed and restarts < NUM_RESTARTS: await self.process() restarts += 1 - self.logger.debug( - "Rev AI connection died, restarting, num_restarts: %s", restarts - ) + logger.debug(f"Rev AI connection died, restarting, num_restarts: {restarts}") async def process(self): async with websockets.connect(self.get_rev_ai_url()) as ws: @@ -84,7 +79,7 @@ async def sender(ws: WebSocketClientProtocol): break await ws.send(data) await ws.close() - self.logger.debug("Terminating Rev.AI transcriber sender") + logger.debug("Terminating Rev.AI transcriber sender") async def receiver(ws: WebSocketClientProtocol): buffer = "" @@ -93,7 +88,7 @@ async def receiver(ws: WebSocketClientProtocol): try: msg = await ws.recv() except Exception as e: - self.logger.debug(f"Got error {e} in Rev.AI receiver") + logger.debug(f"Got error {e} in Rev.AI receiver") break data = json.loads(msg) @@ -124,9 +119,7 @@ async def receiver(ws: WebSocketClientProtocol): confidence = 1.0 if is_done: self.output_queue.put_nowait( - Transcription( - message=buffer, confidence=confidence, is_final=True - ) + Transcription(message=buffer, confidence=confidence, is_final=True) ) buffer = "" else: @@ -138,7 +131,7 @@ async def receiver(ws: WebSocketClientProtocol): ) ) - self.logger.debug("Terminating Rev.AI transcriber receiver") + logger.debug("Terminating Rev.AI transcriber receiver") await asyncio.gather(sender(ws), receiver(ws)) diff --git a/vocode/streaming/transcriber/whisper_cpp_transcriber.py b/vocode/streaming/transcriber/whisper_cpp_transcriber.py index 96a12ed47..6f1967de5 100644 --- a/vocode/streaming/transcriber/whisper_cpp_transcriber.py +++ b/vocode/streaming/transcriber/whisper_cpp_transcriber.py @@ -1,19 +1,15 @@ -import asyncio -from concurrent.futures import ThreadPoolExecutor import ctypes import io import pathlib import wave -from pydub import AudioSegment +from concurrent.futures import ThreadPoolExecutor import numpy as np -from vocode.streaming.agent.utils import SENTENCE_ENDINGS -from vocode.streaming.models.transcriber import WhisperCPPTranscriberConfig -from vocode.streaming.transcriber.base_transcriber import ( - BaseAsyncTranscriber, - BaseThreadAsyncTranscriber, - Transcription, -) +from pydub import AudioSegment + +from vocode.streaming.constants import SENTENCE_ENDINGS +from vocode.streaming.models.transcriber import Transcription, WhisperCPPTranscriberConfig +from vocode.streaming.transcriber.base_transcriber import BaseThreadAsyncTranscriber from vocode.utils.whisper_cpp.helpers import transcribe from vocode.utils.whisper_cpp.whisper_params import WhisperFullParams @@ -72,18 +68,12 @@ def _run_loop(self): if audio_buffer.tell() >= self.buffer_size * 2: audio_buffer.seek(0) audio_segment = AudioSegment.from_wav(audio_buffer) - message, confidence = transcribe( - self.whisper, self.params, self.ctx, audio_segment - ) + message, confidence = transcribe(self.whisper, self.params, self.ctx, audio_segment) message_buffer += message - is_final = any( - message_buffer.endswith(ending) for ending in SENTENCE_ENDINGS - ) + is_final = any(message_buffer.endswith(ending) for ending in SENTENCE_ENDINGS) in_memory_wav, audio_buffer = self.create_new_buffer() self.output_queue.put_nowait( - Transcription( - message=message_buffer, confidence=confidence, is_final=is_final - ) + Transcription(message=message_buffer, confidence=confidence, is_final=is_final) ) if is_final: message_buffer = "" diff --git a/vocode/streaming/user_implemented_agent/base_agent.py b/vocode/streaming/user_implemented_agent/base_agent.py index 8009be2d8..166bf9d14 100644 --- a/vocode/streaming/user_implemented_agent/base_agent.py +++ b/vocode/streaming/user_implemented_agent/base_agent.py @@ -1,5 +1,5 @@ -from fastapi import FastAPI import uvicorn +from fastapi import FastAPI class BaseAgent: diff --git a/vocode/streaming/user_implemented_agent/restful_agent.py b/vocode/streaming/user_implemented_agent/restful_agent.py index 0d13fff3d..e8c36f14a 100644 --- a/vocode/streaming/user_implemented_agent/restful_agent.py +++ b/vocode/streaming/user_implemented_agent/restful_agent.py @@ -1,16 +1,10 @@ # type: ignore # to be deprecated -from .base_agent import BaseAgent -from ..models.agent import ( - RESTfulAgentInput, - RESTfulAgentOutput, - RESTfulAgentText, - RESTfulAgentEnd, -) -from pydantic.v1 import BaseModel from typing import Union -from fastapi import APIRouter + +from ..models.agent import RESTfulAgentEnd, RESTfulAgentInput, RESTfulAgentOutput, RESTfulAgentText +from .base_agent import BaseAgent class RESTfulAgent(BaseAgent): diff --git a/vocode/streaming/utils/__init__.py b/vocode/streaming/utils/__init__.py index 44ae3f1e5..6f2585e09 100644 --- a/vocode/streaming/utils/__init__.py +++ b/vocode/streaming/utils/__init__.py @@ -1,14 +1,17 @@ import asyncio import audioop +import random import secrets -from typing import Any import wave from string import ascii_letters, digits +from typing import Any, AsyncGenerator, AsyncIterator, Callable, List, Tuple, TypeVar -from ..models.audio_encoding import AudioEncoding +from vocode.streaming.models.audio import AudioEncoding custom_alphabet = ascii_letters + digits + ".-_" +ChoiceType = TypeVar("ChoiceType") + def create_loop_in_thread(loop: asyncio.AbstractEventLoop, long_running_task=None): asyncio.set_event_loop(loop) @@ -27,9 +30,7 @@ def convert_linear_audio( ): # downsample if input_sample_rate != output_sample_rate: - raw_wav, _ = audioop.ratecv( - raw_wav, 2, 1, input_sample_rate, output_sample_rate, None - ) + raw_wav, _ = audioop.ratecv(raw_wav, 2, 1, input_sample_rate, output_sample_rate, None) if output_encoding == AudioEncoding.LINEAR16: return raw_wav @@ -66,5 +67,71 @@ def create_conversation_id() -> str: return secrets.token_urlsafe(16) +def create_utterance_id() -> str: + return secrets.token_hex(16) + + def remove_non_letters_digits(text): return "".join(i for i in text if i in custom_alphabet) + + +def unrepeating_randomizer(l: List[ChoiceType]) -> Callable[[], ChoiceType]: + last_choice = None + + def next() -> ChoiceType: + nonlocal last_choice + choice = random.choice(l) + while choice == last_choice: + choice = random.choice(l) + last_choice = choice + return choice + + return next + + +AsyncIteratorGenericType = TypeVar("AsyncIteratorGenericType") + + +async def generate_with_is_last( + async_gen: AsyncGenerator[AsyncIteratorGenericType, None], +) -> AsyncGenerator[Tuple[AsyncIteratorGenericType, bool], None]: + async_iter = async_gen.__aiter__() + try: + next_item = await async_iter.__anext__() + except StopAsyncIteration: + assert False, "Cannot generate with is_last from an empty async generator" + while True: + try: + item = await async_iter.__anext__() + yield next_item, False + next_item = item + except StopAsyncIteration: + yield next_item, True + break + + +async def generate_from_async_iter_with_lookahead( + async_iter: AsyncIterator[AsyncIteratorGenericType], + lookahead: int, +) -> AsyncGenerator[List[AsyncIteratorGenericType], None]: + """Yield sliding window lists of length `lookahead + 1` from an async iterator. + + If the length of async iterator < lookahead + 1, then it should just yield the whole + async iterator as a list. + """ + assert lookahead > 0 + buffer = [] + + stream_length = 0 + while True: + try: + next_item = await async_iter.__anext__() + stream_length += 1 + buffer.append(next_item) + if len(buffer) == lookahead + 1: + yield buffer + buffer = buffer[1:] + except StopAsyncIteration: + if buffer and stream_length <= lookahead: + yield buffer + return diff --git a/vocode/streaming/utils/async_requester.py b/vocode/streaming/utils/async_requester.py new file mode 100644 index 000000000..5b23875cc --- /dev/null +++ b/vocode/streaming/utils/async_requester.py @@ -0,0 +1,25 @@ +import aiohttp +import httpx + +from vocode.streaming.utils.singleton import Singleton + + +class AsyncRequestor(Singleton): + def __init__(self): + self.session = aiohttp.ClientSession() + self.async_client = httpx.AsyncClient() + + def get_session(self): + if self.session.closed: + self.session = aiohttp.ClientSession() + return self.session + + def get_client(self): + return self.async_client + + async def close_session(self): + if not self.session.closed: + await self.session.close() + + async def close_client(self): + await self.async_client.aclose() diff --git a/vocode/streaming/utils/conversation_logger_adapter.py b/vocode/streaming/utils/conversation_logger_adapter.py deleted file mode 100644 index 16c4cd1cf..000000000 --- a/vocode/streaming/utils/conversation_logger_adapter.py +++ /dev/null @@ -1,15 +0,0 @@ -# A logger adapter that adds a conversation_id to the log message. - -import logging - - -class ConversationLoggerAdapter(logging.LoggerAdapter): - def process(self, msg, kwargs): - return "[%s] %s" % (self.extra["conversation_id"], msg), kwargs - - -def wrap_logger(logger, conversation_id): - if isinstance(logger, ConversationLoggerAdapter): - return logger - else: - return ConversationLoggerAdapter(logger, {"conversation_id": conversation_id}) diff --git a/vocode/streaming/utils/create_task.py b/vocode/streaming/utils/create_task.py new file mode 100644 index 000000000..9554734d0 --- /dev/null +++ b/vocode/streaming/utils/create_task.py @@ -0,0 +1,30 @@ +import asyncio +import functools + +from loguru import logger + +tasks_registry = [] + + +def log_if_exception(reraise_cancelled: bool, future: asyncio.Future) -> None: + try: + if exc := future.exception(): + logger.exception( + f"Vocode wrapped logger; exception raised by task {future}: {exc}", + exc_info=exc, + ) + except asyncio.CancelledError: + if reraise_cancelled: + raise + + +def asyncio_create_task_with_done_error_log( + *args, + reraise_cancelled: bool = False, + **kwargs, +) -> asyncio.Task: + task = asyncio.create_task(*args, **kwargs) + tasks_registry.append(task) + task.add_done_callback(functools.partial(log_if_exception, reraise_cancelled)) + task.add_done_callback(lambda t: tasks_registry.remove(t)) + return task diff --git a/vocode/streaming/utils/events_manager.py b/vocode/streaming/utils/events_manager.py index 818ab80ac..420760ac1 100644 --- a/vocode/streaming/utils/events_manager.py +++ b/vocode/streaming/utils/events_manager.py @@ -1,25 +1,21 @@ from __future__ import annotations -import asyncio - -from vocode.streaming.models.events import Event +import asyncio +from typing import List +from loguru import logger -async def flush_event(event): - if event: - del event +from vocode.streaming.models.events import Event, EventType class EventsManager: - def __init__(self, subscriptions=None): - if subscriptions is None: - subscriptions = [] + def __init__(self, subscriptions: List[EventType] = []): self.queue: asyncio.Queue[Event] = asyncio.Queue() self.subscriptions = set(subscriptions) self.active = False def publish_event(self, event: Event): - if event.type in self.subscriptions: + if event and event.type in self.subscriptions: self.queue.put_nowait(event) async def start(self): @@ -27,19 +23,27 @@ async def start(self): while self.active: try: event = await self.queue.get() - await self.handle_event(event) except asyncio.QueueEmpty: await asyncio.sleep(1) + except asyncio.CancelledError: + break + await self.handle_event(event) async def handle_event(self, event: Event): - pass # Default implementation, can be overridden + pass - async def flush(self, timeout=30): + async def flush(self): + self.active = False while True: try: - event = await asyncio.wait_for(self.queue.get(), timeout) - await flush_event(event) - except asyncio.TimeoutError: - break + event = self.queue.get_nowait() + await self.handle_event(event) except asyncio.QueueEmpty: break + except TypeError as e: + if "NoneType can't be used in 'await' expression" in str(e): + logger.error( + "Handle event was overridden with non-async function. Please override with async function." + ) + else: + raise e from e diff --git a/vocode/streaming/utils/goodbye_model.py b/vocode/streaming/utils/goodbye_model.py deleted file mode 100644 index c500158d6..000000000 --- a/vocode/streaming/utils/goodbye_model.py +++ /dev/null @@ -1,93 +0,0 @@ -import os -import asyncio -from typing import Optional -import openai -import numpy as np -import requests - -from vocode import getenv - -SIMILARITY_THRESHOLD = 0.9 -EMBEDDING_SIZE = 1536 -GOODBYE_PHRASES = [ - "bye", - "goodbye", - "see you", - "see you later", - "talk to you later", - "talk to you soon", - "have a good day", - "have a good night", -] - - -class GoodbyeModel: - def __init__( - self, - embeddings_cache_path=os.path.join( - os.path.dirname(__file__), "goodbye_embeddings" - ), - openai_api_key: Optional[str] = None, - ): - openai.api_key = openai_api_key or getenv("OPENAI_API_KEY") - if not openai.api_key: - raise ValueError("OPENAI_API_KEY must be set in environment or passed in") - self.embeddings_cache_path = embeddings_cache_path - self.goodbye_embeddings: Optional[np.ndarray] = None - - async def initialize_embeddings(self): - self.goodbye_embeddings = await self.load_or_create_embeddings( - f"{self.embeddings_cache_path}/goodbye_embeddings.npy" - ) - - async def load_or_create_embeddings(self, path): - if os.path.exists(path): - return np.load(path) - else: - embeddings = await self.create_embeddings() - np.save(path, embeddings) - return embeddings - - async def create_embeddings(self): - print("Creating embeddings...") - size = EMBEDDING_SIZE - embeddings = np.empty((size, len(GOODBYE_PHRASES))) - for i, goodbye_phrase in enumerate(GOODBYE_PHRASES): - embeddings[:, i] = await self.create_embedding(goodbye_phrase) - return embeddings - - async def is_goodbye(self, text: str) -> bool: - assert self.goodbye_embeddings is not None, "Embeddings not initialized" - if "bye" in text.lower(): - return True - embedding = await self.create_embedding(text.strip().lower()) - similarity_results = embedding @ self.goodbye_embeddings - return np.max(similarity_results) > SIMILARITY_THRESHOLD - - async def create_embedding(self, text) -> np.ndarray: - params = { - "input": text, - } - - engine = getenv("AZURE_OPENAI_TEXT_EMBEDDING_ENGINE") - if engine: - params["engine"] = engine - else: - params["model"] = "text-embedding-ada-002" - - return np.array( - (await openai.Embedding.acreate(**params))["data"][0]["embedding"] - ) - - -if __name__ == "__main__": - from dotenv import load_dotenv - - load_dotenv() - - async def main(): - model = GoodbyeModel() - while True: - print(await model.is_goodbye(input("Text: "))) - - asyncio.run(main()) diff --git a/vocode/streaming/utils/mp3_helper.py b/vocode/streaming/utils/mp3_helper.py index b0a2af915..2e3cbea4a 100644 --- a/vocode/streaming/utils/mp3_helper.py +++ b/vocode/streaming/utils/mp3_helper.py @@ -1,5 +1,6 @@ import io import wave + import miniaudio diff --git a/vocode/streaming/utils/phone_numbers.py b/vocode/streaming/utils/phone_numbers.py new file mode 100644 index 000000000..0a9743227 --- /dev/null +++ b/vocode/streaming/utils/phone_numbers.py @@ -0,0 +1,42 @@ +import phonenumbers +from phonenumbers import PhoneNumberFormat + +NUMBER_PARSE_ERROR = "Input number cannot be interpreted as a phone number. If passing an international number, please include the country code (e.g. +49 for German numbers)" + + +def parse_number_e164(phone_number: str) -> phonenumbers.PhoneNumber: + if not phone_number.startswith("+"): + phone_number = "+" + phone_number + return phonenumbers.parse(phone_number, None) + + +def parse_number_usa_fallback_to_e164(phone_number: str) -> phonenumbers.PhoneNumber: + try: + phone_number_obj = phonenumbers.parse(phone_number, "US") + valid = phonenumbers.is_valid_number(phone_number_obj) + return phone_number_obj if valid else parse_number_e164(phone_number) + except phonenumbers.phonenumberutil.NumberParseException: + return parse_number_e164(phone_number) + + +def parse_phone_number(phone_number: str) -> phonenumbers.PhoneNumber: + if phone_number.startswith("+"): + # If we have a plus we know its e164 + return parse_number_e164(phone_number) + else: + # If we don't have a plus, we try as USA with e164 fallback + return parse_number_usa_fallback_to_e164(phone_number) + + +def sanitize_phone_number(phone_number: str) -> str: + phone_number_obj: phonenumbers.PhoneNumber + + try: + phone_number_obj = parse_phone_number(phone_number) + except Exception: + raise ValueError(NUMBER_PARSE_ERROR) + + if not phonenumbers.is_valid_number(phone_number_obj): + raise ValueError(NUMBER_PARSE_ERROR) + + return phonenumbers.format_number(phone_number_obj, PhoneNumberFormat.E164).replace("+", "") diff --git a/vocode/streaming/utils/redis.py b/vocode/streaming/utils/redis.py new file mode 100644 index 000000000..4d492c452 --- /dev/null +++ b/vocode/streaming/utils/redis.py @@ -0,0 +1,79 @@ +import os +from typing import Optional, TypeVar + +from loguru import logger +from redis.asyncio import Redis +from redis.backoff import ExponentialBackoff, NoBackoff +from redis.exceptions import ConnectionError, TimeoutError +from redis.retry import Retry + +from vocode.streaming.utils.singleton import Singleton + +WorkerInputType = TypeVar("WorkerInputType") +# Two separate factories for Redis clients so that the +# typing gets picked up properly + + +def initialize_redis(retries: int = 1): + backoff = ExponentialBackoff() if retries > 1 else NoBackoff() + retry = Retry(backoff, retries) + return Redis( # type: ignore + host=os.environ.get("REDISHOST", "localhost"), + port=int(os.environ.get("REDISPORT", 6379)), + username=os.environ.get("REDISUSER", None), + password=os.environ.get("REDISPASSWORD", None), + decode_responses=True, + retry=retry, + ssl=bool(os.environ.get("REDISSSL", False)), + ssl_cert_reqs="none", + retry_on_error=[ConnectionError, TimeoutError], + health_check_interval=30, + ) + + +def initialize_redis_bytes(): + return Redis( + host=os.environ.get("REDISHOST", "localhost"), + port=int(os.environ.get("REDISPORT", 6379)), + username=os.environ.get("REDISUSER", None), + password=os.environ.get("REDISPASSWORD", None), + db=0, + ssl=bool(os.environ.get("REDISSSL", False)), + ssl_cert_reqs="none", + ) + + +class RedisGenericMessageQueue(Singleton): + """Class representing a Redis Streams message queue.""" + + def __init__( + self, + prefix: Optional[str] = None, + suffix: Optional[str] = None, + ) -> None: + """ + Initialize a RedisGenericMessageQueue instance. + + This initializes a Redis client and sets the name of the stream. + """ + self.redis: Redis = initialize_redis() + queue_name_prefix = f"{prefix}_" if prefix else "" + queue_name_suffix = f"_{suffix}" if suffix else "" + self.queue_name = f"{queue_name_prefix}queue{queue_name_suffix}" + + async def publish(self, message: dict) -> None: + """ + Publishes a message to the Redis stream. + + Args: + message (dict): The message to be published. + + Returns: + None + """ + logger.info(f"[{self.queue_name}] Publishing message: {message}") + try: + await self.redis.xadd(self.queue_name, message) + except Exception as e: + logger.exception(f"[{self.queue_name}] Failed to publish message: {message}") + raise e diff --git a/vocode/streaming/utils/redis_conversation_message_queue.py b/vocode/streaming/utils/redis_conversation_message_queue.py new file mode 100644 index 000000000..4ec28edc8 --- /dev/null +++ b/vocode/streaming/utils/redis_conversation_message_queue.py @@ -0,0 +1,35 @@ +from typing import Annotated, AsyncGenerator, Literal, Union + +from loguru import logger +from pydantic.v1 import BaseModel, Field, parse_obj_as +from redis.asyncio import Redis + +from vocode.streaming.utils.redis import initialize_redis +from vocode.streaming.utils.singleton import Singleton + + +class RedisMessage(BaseModel): + type: str + + +class RedisConversationMessageQueue(Singleton): + def __init__(self): + self.redis: Redis = initialize_redis() + + async def publish(self, conversation_id: str, message: RedisMessage): + logger.info(f"Publishing message to {conversation_id}") + await self.redis.xadd(f"{conversation_id}:stream", message.dict()) # type: ignore + + async def wait_for_messages( + self, conversation_id: str, timeout_seconds: int = 20 + ) -> AsyncGenerator[RedisMessage, None]: + logger.info(f"Waiting for message from {conversation_id}") + streams = await self.redis.xread( + {f"{conversation_id}:stream": "$"}, block=timeout_seconds * 1000 + ) + for _, stream in streams: # stream_id, stream + for _, message in stream: # timestamp, message + yield parse_obj_as(RedisMessage, message) # type: ignore + + async def clear_stream(self, conversation_id: str): + await self.redis.delete(f"{conversation_id}:stream") diff --git a/vocode/streaming/utils/singleton.py b/vocode/streaming/utils/singleton.py new file mode 100644 index 000000000..eefcd9c12 --- /dev/null +++ b/vocode/streaming/utils/singleton.py @@ -0,0 +1,14 @@ +from typing import Any, Dict + + +class SingletonMeta(type): + _instances: Dict[Any, Any] = {} + + def __call__(cls, *args, **kwargs): + if cls not in cls._instances: + cls._instances[cls] = super().__call__(*args, **kwargs) + return cls._instances[cls] + + +class Singleton(metaclass=SingletonMeta): + pass diff --git a/vocode/streaming/utils/speed_manager.py b/vocode/streaming/utils/speed_manager.py new file mode 100644 index 000000000..421524f4d --- /dev/null +++ b/vocode/streaming/utils/speed_manager.py @@ -0,0 +1,44 @@ +from loguru import logger + +from vocode.streaming.models.transcriber import Transcription + +LEARNING_RATE = 0.1 +LENGTH_THRESHOLD = 5 +SMOOTHING_FACTOR = 3 +BASE_WPM = 150.0 + + +class SpeedManager: + """ + Uses the WPM of incoming transcriptions to update a speed coefficient to inform conversation orchestration. + + speed_coefficient is used in two places (currently): + - DeepgramTranscriber endpointing - when we receive fast utterances from the user, we decrease the endpointing threshold to match the speed of the user + - Interruption logic - if the user is speaking slowly, then when the agent is responding to an interrupt, we wait longer + + Initializes with a speed coefficient of 1.0, which corresponds to a WPM of 150.0 and uses a moving average to update the speed coefficient based on incoming transcriptions. + """ + + def __init__(self, speed_coefficient: float = 1.0): + self.wpm_0 = BASE_WPM * speed_coefficient + self.wpm = self.wpm_0 + self.speed_coefficient = speed_coefficient + + def update(self, transcription: Transcription): + transcription_wpm = transcription.wpm() + if transcription_wpm is not None: + length = len(transcription.message.strip().split()) + p_t = min( + 1, + LEARNING_RATE + * ((length + SMOOTHING_FACTOR) / (LENGTH_THRESHOLD + SMOOTHING_FACTOR)), + ) + self.wpm = self.wpm * (1 - p_t) + transcription_wpm * p_t + self.speed_coefficient = self.wpm / BASE_WPM + logger.info(f"Set speed coefficient to {self.speed_coefficient}") + + def get_speed_coefficient(self): + return self.speed_coefficient + + def get_wpm(self): + return self.wpm diff --git a/vocode/streaming/utils/state_manager.py b/vocode/streaming/utils/state_manager.py index b45f6704e..b67eb1bd2 100644 --- a/vocode/streaming/utils/state_manager.py +++ b/vocode/streaming/utils/state_manager.py @@ -1,23 +1,85 @@ -import asyncio from typing import TYPE_CHECKING, Optional -from vocode.streaming.models.message import BaseMessage + from vocode.streaming.models.transcriber import EndpointingConfig -from vocode.streaming.agent.base_agent import AgentResponseMessage +from vocode.streaming.synthesizer.input_streaming_synthesizer import InputStreamingSynthesizer +from vocode.streaming.telephony.client.twilio_client import TwilioClient +from vocode.streaming.telephony.client.vonage_client import VonageClient +from vocode.streaming.utils.redis_conversation_message_queue import RedisConversationMessageQueue if TYPE_CHECKING: from vocode.streaming.streaming_conversation import StreamingConversation - from vocode.streaming.telephony.conversation.vonage_call import VonageCall - from vocode.streaming.telephony.conversation.twilio_call import TwilioCall + from vocode.streaming.telephony.conversation.abstract_phone_conversation import ( + AbstractPhoneConversation, + ) + from vocode.streaming.telephony.conversation.twilio_phone_conversation import ( + TwilioPhoneConversation, + ) + from vocode.streaming.telephony.conversation.vonage_phone_conversation import ( + VonagePhoneConversation, + ) + + +# TODO: make this a proper ABC +class AbstractConversationStateManager: + @property + def logger(self): + raise NotImplementedError + + @property + def transcript(self): + raise NotImplementedError + + def get_transcriber_endpointing_config(self) -> Optional[EndpointingConfig]: + raise NotImplementedError + + def set_transcriber_endpointing_config(self, endpointing_config: EndpointingConfig): + raise NotImplementedError + + def disable_synthesis(self): + raise NotImplementedError + + def enable_synthesis(self): + raise NotImplementedError + + def mute_agent(self): + raise NotImplementedError + + def unmute_agent(self): + raise NotImplementedError + + def using_input_streaming_synthesizer(self): + raise NotImplementedError + + async def terminate_conversation(self): + raise NotImplementedError + + def get_conversation_id(self): + raise NotImplementedError -class ConversationStateManager: +class AbstractPhoneConversationStateManager(AbstractConversationStateManager): + def get_config_manager(self): + raise NotImplementedError + + def get_to_phone(self): + raise NotImplementedError + + def get_from_phone(self): + raise NotImplementedError + + +class ConversationStateManager(AbstractConversationStateManager): def __init__(self, conversation: "StreamingConversation"): self._conversation = conversation + if not hasattr(self, "redis_message_queue"): + self.redis_message_queue = RedisConversationMessageQueue() + + @property + def transcript(self): + return self._conversation.transcript def get_transcriber_endpointing_config(self) -> Optional[EndpointingConfig]: - return ( - self._conversation.transcriber.get_transcriber_config().endpointing_config - ) + return self._conversation.transcriber.get_transcriber_config().endpointing_config def set_transcriber_endpointing_config(self, endpointing_config: EndpointingConfig): assert self.get_transcriber_endpointing_config() is not None @@ -37,30 +99,66 @@ def mute_agent(self): def unmute_agent(self): self._conversation.agent.is_muted = False + def using_input_streaming_synthesizer(self): + return isinstance( + self._conversation.synthesizer, + InputStreamingSynthesizer, + ) + async def terminate_conversation(self): - await self._conversation.terminate() - - def send_bot_message(self, message: BaseMessage) -> asyncio.Event: - # returns an asyncio.Event that will be set when the agent has finished uttering the message - agent_response_tracker = asyncio.Event() - self._conversation.agent.produce_interruptible_agent_response_event_nonblocking( - item=AgentResponseMessage( - message=message, - is_interruptible=False, - ), - is_interruptible=False, - agent_response_tracker=agent_response_tracker, + self._conversation.mark_terminated() + + def set_call_check_for_idle_paused(self, value: bool): + if not self._conversation: + return + self._conversation.set_check_for_idle_paused(value) + + def get_conversation_id(self): + return self._conversation.id + + +class PhoneConversationStateManager( + AbstractPhoneConversationStateManager, ConversationStateManager +): + def __init__(self, conversation: "AbstractPhoneConversation"): + ConversationStateManager.__init__(self, conversation) + self._phone_conversation = conversation + + def get_config_manager(self): + return self._phone_conversation.config_manager + + def get_to_phone(self): + return self._phone_conversation.to_phone + + def get_from_phone(self): + return self._phone_conversation.from_phone + + def get_direction(self): + return self._phone_conversation.direction + + +class VonagePhoneConversationStateManager(PhoneConversationStateManager): + def __init__(self, conversation: "VonagePhoneConversation"): + super().__init__(conversation=conversation) + self._vonage_phone_conversation = conversation + + def create_vonage_client(self): + return VonageClient( + base_url=self._vonage_phone_conversation.base_url, + maybe_vonage_config=self._vonage_phone_conversation.vonage_config, ) - return agent_response_tracker -class VonageCallStateManager(ConversationStateManager): - def __init__(self, call: "VonageCall"): - super().__init__(call) - self._call = call +class TwilioPhoneConversationStateManager(PhoneConversationStateManager): + def __init__(self, conversation: "TwilioPhoneConversation"): + super().__init__(conversation=conversation) + self._twilio_phone_conversation = conversation + def get_twilio_config(self): + return self._twilio_phone_conversation.twilio_config -class TwilioCallStateManager(ConversationStateManager): - def __init__(self, call: "TwilioCall"): - super().__init__(call) - self._call = call + def create_twilio_client(self): + return TwilioClient( + base_url=self._twilio_phone_conversation.base_url, + maybe_twilio_config=self.get_twilio_config(), + ) diff --git a/vocode/streaming/utils/worker.py b/vocode/streaming/utils/worker.py index d01599407..80021b580 100644 --- a/vocode/streaming/utils/worker.py +++ b/vocode/streaming/utils/worker.py @@ -2,13 +2,12 @@ import asyncio import threading -import janus -from typing import Any, Optional -from typing import TypeVar, Generic -import logging +from typing import Any, Generic, Optional, TypeVar +import janus +from loguru import logger -logger = logging.getLogger(__name__) +from vocode.streaming.utils.create_task import asyncio_create_task_with_done_error_log WorkerInputType = TypeVar("WorkerInputType") @@ -24,7 +23,11 @@ def __init__( self.output_queue = output_queue def start(self) -> asyncio.Task: - self.worker_task = asyncio.create_task(self._run_loop()) + self.worker_task = asyncio_create_task_with_done_error_log( + self._run_loop(), + ) + if not self.worker_task: + raise Exception("Worker task not created") return self.worker_task def consume_nonblocking(self, item: WorkerInputType): @@ -57,7 +60,11 @@ def __init__( def start(self) -> asyncio.Task: self.worker_thread = threading.Thread(target=self._run_loop) self.worker_thread.start() - self.worker_task = asyncio.create_task(self.run_thread_forwarding()) + self.worker_task = asyncio_create_task_with_done_error_log( + self.run_thread_forwarding(), + ) + if not self.worker_task: + raise Exception("Worker task not created") return self.worker_task async def run_thread_forwarding(self): @@ -94,7 +101,7 @@ async def _run_loop(self): await self.process(item) except asyncio.CancelledError: return - except Exception as e: + except Exception: logger.exception("AsyncQueueWorker", exc_info=True) async def process(self, item): @@ -143,6 +150,10 @@ def __init__( super().__init__(payload, is_interruptible, interruption_event) self.agent_response_tracker = agent_response_tracker + def interrupt(self) -> bool: + self.agent_response_tracker.set() + return super().interrupt() + class InterruptibleEventFactory: def create_interruptible_event( @@ -181,13 +192,9 @@ def __init__( self.current_task = None self.interruptible_event = None - def produce_interruptible_event_nonblocking( - self, item: Any, is_interruptible: bool = True - ): - interruptible_event = ( - self.interruptible_event_factory.create_interruptible_event( - item, is_interruptible=is_interruptible - ) + def produce_interruptible_event_nonblocking(self, item: Any, is_interruptible: bool = True): + interruptible_event = self.interruptible_event_factory.create_interruptible_event( + item, is_interruptible=is_interruptible ) return super().produce_nonblocking(interruptible_event) @@ -209,16 +216,24 @@ def produce_interruptible_agent_response_event_nonblocking( async def _run_loop(self): # TODO Implement concurrency with max_nb_of_thread while True: - item = await self.input_queue.get() + try: + item = await self.input_queue.get() + except asyncio.CancelledError: + return + if item.is_interrupted(): continue self.interruptible_event = item - self.current_task = asyncio.create_task(self.process(item)) + self.current_task = asyncio_create_task_with_done_error_log( + self.process(item), + reraise_cancelled=True, + ) + try: await self.current_task except asyncio.CancelledError: return - except Exception as e: + except Exception: logger.exception("InterruptibleWorker", exc_info=True) self.interruptible_event.is_interruptible = False self.current_task = None @@ -246,7 +261,5 @@ def cancel_current_task(self): return False -class InterruptibleAgentResponseWorker( - InterruptibleWorker[InterruptibleAgentResponseEvent] -): +class InterruptibleAgentResponseWorker(InterruptibleWorker[InterruptibleAgentResponseEvent]): pass diff --git a/vocode/streaming/vector_db/base_vector_db.py b/vocode/streaming/vector_db/base_vector_db.py index 7127a2b22..032b29c05 100644 --- a/vocode/streaming/vector_db/base_vector_db.py +++ b/vocode/streaming/vector_db/base_vector_db.py @@ -1,13 +1,18 @@ import os -from typing import Iterable, List, Optional, Tuple +from typing import Iterable, List, Optional, Tuple, Union + import aiohttp -import openai from langchain.docstore.document import Document +from openai import AsyncAzureOpenAI, AsyncOpenAI + +from vocode.streaming.models.agent import AZURE_OPENAI_DEFAULT_API_VERSION DEFAULT_OPENAI_EMBEDDING_MODEL = "text-embedding-ada-002" class VectorDB: + openai_client: Union[AsyncOpenAI, AsyncAzureOpenAI] + def __init__( self, aiohttp_session: Optional[aiohttp.ClientSession] = None, @@ -20,6 +25,20 @@ def __init__( self.aiohttp_session = aiohttp.ClientSession() self.should_close_session_on_tear_down = True + self.engine = os.getenv("AZURE_OPENAI_TEXT_EMBEDDING_ENGINE") + if self.engine: + azure_base = os.getenv("AZURE_OPENAI_API_BASE_EAST_US") + azure_base = azure_base if azure_base is not None else "" + self.openai_client = AsyncAzureOpenAI( + azure_endpoint=azure_base, + api_key=os.getenv("AZURE_OPENAI_API_KEY_EAST_US"), + api_version=AZURE_OPENAI_DEFAULT_API_VERSION, + ) + else: + self.openai_client = AsyncOpenAI( + api_key=os.getenv("OPENAI_API_KEY"), + ) + async def create_openai_embedding( self, text, model=DEFAULT_OPENAI_EMBEDDING_MODEL ) -> List[float]: @@ -27,13 +46,9 @@ async def create_openai_embedding( "input": text, } - engine = os.getenv("AZURE_OPENAI_TEXT_EMBEDDING_ENGINE") - if engine: - params["engine"] = engine - else: - params["model"] = model + params["model"] = self.engine if self.engine else model - return list((await openai.Embedding.acreate(**params))["data"][0]["embedding"]) + return (await self.openai_client.embeddings.create(**params)).data[0].embedding async def add_texts( self, diff --git a/vocode/streaming/vector_db/factory.py b/vocode/streaming/vector_db/factory.py index 1889081b7..3aa8eecd5 100644 --- a/vocode/streaming/vector_db/factory.py +++ b/vocode/streaming/vector_db/factory.py @@ -1,6 +1,7 @@ -import logging from typing import Optional + import aiohttp + from vocode.streaming.models.vector_db import PineconeConfig, VectorDBConfig from vocode.streaming.vector_db.base_vector_db import VectorDB from vocode.streaming.vector_db.pinecone import PineconeDB diff --git a/vocode/streaming/vector_db/pinecone.py b/vocode/streaming/vector_db/pinecone.py index 646590860..26cd048f3 100644 --- a/vocode/streaming/vector_db/pinecone.py +++ b/vocode/streaming/vector_db/pinecone.py @@ -1,13 +1,13 @@ -import logging -from typing import Iterable, List, Optional, Tuple import uuid +from typing import Iterable, List, Optional, Tuple + from langchain.docstore.document import Document +from loguru import logger + from vocode import getenv from vocode.streaming.models.vector_db import PineconeConfig from vocode.streaming.vector_db.base_vector_db import VectorDB -logger = logging.getLogger(__name__) - class PineconeDB(VectorDB): def __init__(self, config: PineconeConfig, *args, **kwargs) -> None: @@ -16,12 +16,8 @@ def __init__(self, config: PineconeConfig, *args, **kwargs) -> None: self.index_name = self.config.index self.pinecone_api_key = getenv("PINECONE_API_KEY") or self.config.api_key - self.pinecone_environment = ( - getenv("PINECONE_ENVIRONMENT") or self.config.api_environment - ) - self.pinecone_url = ( - f"https://{self.index_name}.svc.{self.pinecone_environment}.pinecone.io" - ) + self.pinecone_environment = getenv("PINECONE_ENVIRONMENT") or self.config.api_environment + self.pinecone_url = f"https://{self.index_name}.svc.{self.pinecone_environment}.pinecone.io" self._text_key = "text" async def add_texts( @@ -109,7 +105,5 @@ async def similarity_search_with_score( score = res["score"] docs.append((Document(page_content=text, metadata=metadata), score)) else: - logger.warning( - f"Found document with no `{self._text_key}` key. Skipping." - ) + logger.warning(f"Found document with no `{self._text_key}` key. Skipping.") return docs diff --git a/vocode/turn_based/agent/chat_gpt_agent.py b/vocode/turn_based/agent/chat_gpt_agent.py index 37e6e5b0e..a6d8ac41c 100644 --- a/vocode/turn_based/agent/chat_gpt_agent.py +++ b/vocode/turn_based/agent/chat_gpt_agent.py @@ -1,16 +1,8 @@ -from typing import Optional +from typing import Any, List, Optional + import openai -from langchain.prompts import ( - ChatPromptTemplate, - MessagesPlaceholder, - SystemMessagePromptTemplate, - HumanMessagePromptTemplate, -) -from langchain.chains import ConversationChain -from langchain_community.chat_models import ChatOpenAI -from langchain.memory import ConversationBufferMemory -from vocode import getenv +from vocode import getenv from vocode.turn_based.agent.base_agent import BaseAgent @@ -23,32 +15,41 @@ def __init__( model_name: str = "gpt-3.5-turbo", temperature: float = 0.7, max_tokens: int = 100, - memory: Optional[ConversationBufferMemory] = None, ): super().__init__(initial_message=initial_message) openai.api_key = getenv("OPENAI_API_KEY", api_key) if not openai.api_key: raise ValueError("OpenAI API key not provided") - self.prompt = ChatPromptTemplate.from_messages( - [ - SystemMessagePromptTemplate.from_template(system_prompt), - MessagesPlaceholder(variable_name="history"), - HumanMessagePromptTemplate.from_template("{input}"), - ] - ) - self.memory = ( - memory if memory else ConversationBufferMemory(return_messages=True) + self.client = openai.OpenAI() + self.prompt = system_prompt + self.model_name = model_name + self.messages: List[Any] = [ + { + "role": "system", + "content": system_prompt, + }, + { + "role": "assistant", + "content": initial_message, + }, + ] + + def respond(self, human_input: str): + self.messages.append( + { + "role": "user", + "content": human_input, + } ) - if initial_message: - self.memory.chat_memory.add_ai_message(initial_message) - self.llm = ChatOpenAI( # type: ignore - model_name=model_name, - temperature=temperature, - max_tokens=max_tokens, + response = self.client.chat.completions.create( + model=self.model_name, + messages=self.messages, ) - self.conversation = ConversationChain( - memory=self.memory, prompt=self.prompt, llm=self.llm + content = response.choices[0].message.content + self.messages.append( + { + "role": "system", + "content": content, + } ) - - def respond(self, human_input: str): - return self.conversation.predict(input=human_input) + return content diff --git a/vocode/turn_based/agent/gpt4all_agent.py b/vocode/turn_based/agent/gpt4all_agent.py index 71495b139..f5e5e3dd5 100644 --- a/vocode/turn_based/agent/gpt4all_agent.py +++ b/vocode/turn_based/agent/gpt4all_agent.py @@ -1,10 +1,14 @@ import asyncio -from concurrent.futures import ThreadPoolExecutor, wait -import logging import sys +from concurrent.futures import ThreadPoolExecutor, wait from typing import Optional + +from loguru import logger + from vocode.turn_based.agent.base_agent import BaseAgent +raise DeprecationWarning("This Agent is deprecated and will be removed in the future.") + class StopThreadException(Exception): pass @@ -20,13 +24,11 @@ def __init__( model_path: str, system_prompt: str, initial_message: Optional[str] = None, - logger: Optional[logging.Logger] = None, ): from pygpt4all.models.gpt4all_j import GPT4All_J super().__init__(initial_message) self.prompt_template = f"{system_prompt}\n\n{self.DEFAULT_PROMPT_TEMPLATE}" - self.logger = logger or logging.getLogger(__name__) self.memory = [f"AI: {initial_message}"] if initial_message else [] self.llm = GPT4All_J(model_path) self.thread_pool_executor = ThreadPoolExecutor(max_workers=1) @@ -42,16 +44,14 @@ def respond( self, human_input, ) -> str: - self.logger.debug("LLM responding to human input") + logger.debug("LLM responding to human input") prompt = self.create_prompt(human_input) response_buffer = "" def new_text_callback(text): nonlocal response_buffer response_buffer += text - if len(response_buffer) > len(prompt) and response_buffer.endswith( - "Human:" - ): + if len(response_buffer) > len(prompt) and response_buffer.endswith("Human:"): response_buffer = response_buffer[: -len("Human:")] sys.exit() @@ -63,7 +63,7 @@ def new_text_callback(text): wait([future], timeout=10) response = response_buffer[(len(prompt) + 1) :] self.memory.append(self.get_memory_entry(human_input, response)) - self.logger.debug(f"LLM response: {response}") + logger.debug(f"LLM response: {response}") return response async def respond_async(self, human_input) -> str: @@ -73,9 +73,7 @@ async def respond_async(self, human_input) -> str: def new_text_callback(text): nonlocal response_buffer response_buffer += text - if len(response_buffer) > len(prompt) and response_buffer.endswith( - "Human:" - ): + if len(response_buffer) > len(prompt) and response_buffer.endswith("Human:"): response_buffer = response_buffer[: -len("Human:")] raise StopThreadException("Stopping the thread") diff --git a/vocode/turn_based/input_device/microphone_input.py b/vocode/turn_based/input_device/microphone_input.py index 4ee35b449..9a032bfa0 100644 --- a/vocode/turn_based/input_device/microphone_input.py +++ b/vocode/turn_based/input_device/microphone_input.py @@ -1,9 +1,10 @@ +import io +import wave from typing import Optional -import sounddevice as sd + import numpy as np +import sounddevice as sd from pydub import AudioSegment -import io -import wave from vocode.turn_based.input_device.base_input_device import BaseInputDevice diff --git a/vocode/turn_based/output_device/speaker_output.py b/vocode/turn_based/output_device/speaker_output.py index 24a475b98..a0b35dc4d 100644 --- a/vocode/turn_based/output_device/speaker_output.py +++ b/vocode/turn_based/output_device/speaker_output.py @@ -1,6 +1,7 @@ from typing import Optional -import sounddevice as sd + import numpy as np +import sounddevice as sd from pydub import AudioSegment from vocode.turn_based.output_device.base_output_device import BaseOutputDevice diff --git a/vocode/turn_based/synthesizer/__init__.py b/vocode/turn_based/synthesizer/__init__.py deleted file mode 100644 index 3353d6dd0..000000000 --- a/vocode/turn_based/synthesizer/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -from vocode.turn_based.synthesizer.azure_synthesizer import AzureSynthesizer -from vocode.turn_based.synthesizer.bark_synthesizer import BarkSynthesizer -from vocode.turn_based.synthesizer.base_synthesizer import BaseSynthesizer -from vocode.turn_based.synthesizer.coqui_synthesizer import CoquiSynthesizer -from vocode.turn_based.synthesizer.coqui_tts_synthesizer import CoquiTTSSynthesizer -from vocode.turn_based.synthesizer.eleven_labs_synthesizer import ElevenLabsSynthesizer -from vocode.turn_based.synthesizer.google_synthesizer import GoogleSynthesizer -from vocode.turn_based.synthesizer.gtts_synthesizer import GTTSSynthesizer -from vocode.turn_based.synthesizer.play_ht_synthesizer import PlayHtSynthesizer -from vocode.turn_based.synthesizer.rime_synthesizer import RimeSynthesizer -from vocode.turn_based.synthesizer.polly_synthesizer import PollySynthesizer -from vocode.turn_based.synthesizer.stream_elements_synthesizer import ( - StreamElementsSynthesizer, -) diff --git a/vocode/turn_based/synthesizer/azure_synthesizer.py b/vocode/turn_based/synthesizer/azure_synthesizer.py index 19f3c5937..b5221edda 100644 --- a/vocode/turn_based/synthesizer/azure_synthesizer.py +++ b/vocode/turn_based/synthesizer/azure_synthesizer.py @@ -1,9 +1,10 @@ from typing import Optional from xml.etree import ElementTree + from pydub import AudioSegment from regex import D -from vocode import getenv +from vocode import getenv from vocode.turn_based.synthesizer.base_synthesizer import BaseSynthesizer DEFAULT_SAMPLING_RATE = 22050 diff --git a/vocode/turn_based/synthesizer/bark_synthesizer.py b/vocode/turn_based/synthesizer/bark_synthesizer.py index ffedabf84..80f43f1e1 100644 --- a/vocode/turn_based/synthesizer/bark_synthesizer.py +++ b/vocode/turn_based/synthesizer/bark_synthesizer.py @@ -1,27 +1,27 @@ import io -from typing import Optional -import numpy as np import logging + +import numpy as np +from loguru import logger from pydub import AudioSegment from scipy.io.wavfile import write as write_wav + from vocode.turn_based.synthesizer.base_synthesizer import BaseSynthesizer class BarkSynthesizer(BaseSynthesizer): - def __init__( - self, logger: Optional[logging.Logger] = None, silent: bool = False, **kwargs - ) -> None: + def __init__(self, silent: bool = False, **kwargs) -> None: from bark import SAMPLE_RATE, generate_audio, preload_models self.SAMPLE_RATE = SAMPLE_RATE self.generate_audio = generate_audio - self.logger = logger or logging.getLogger(__name__) - self.logger.info("Loading Bark models") + logger = logger or logging.getLogger(__name__) + logger.info("Loading Bark models") self.silent = silent preload_models(**kwargs) def synthesize(self, text: str, **kwargs) -> AudioSegment: - self.logger.debug("Bark synthesizing audio") + logger.debug("Bark synthesizing audio") audio_array = self.generate_audio(text, silent=self.silent, **kwargs) int_audio_arr = (audio_array * np.iinfo(np.int16).max).astype(np.int16) diff --git a/vocode/turn_based/synthesizer/coqui_synthesizer.py b/vocode/turn_based/synthesizer/coqui_synthesizer.py index bc53f8389..d39570dcc 100644 --- a/vocode/turn_based/synthesizer/coqui_synthesizer.py +++ b/vocode/turn_based/synthesizer/coqui_synthesizer.py @@ -1,13 +1,17 @@ +import asyncio import io import re import typing -from typing import Optional, List -from pydub import AudioSegment +from typing import List, Optional + +import aiohttp import requests +from pydub import AudioSegment + from vocode import getenv from vocode.turn_based.synthesizer.base_synthesizer import BaseSynthesizer -import aiohttp -import asyncio + +raise DeprecationWarning("This Synthesizer is deprecated and will be removed in the future.") COQUI_BASE_URL = "https://app.coqui.ai/api/v2/samples" DEFAULT_SPEAKER_ID = "d2bd7ccb-1b65-4005-9578-32c4e02d8ddf" @@ -98,10 +102,7 @@ async def async_synthesize(self, text: str) -> AudioSegment: text_chunks = self.split_text(text) # Create a list of tasks for each chunk using asyncio.create_task() - tasks = [ - asyncio.create_task(self.async_synthesize_chunk(chunk)) - for chunk in text_chunks - ] + tasks = [asyncio.create_task(self.async_synthesize_chunk(chunk)) for chunk in text_chunks] # Wait for all tasks to complete using asyncio.gather() audio_chunks = await asyncio.gather(*tasks) diff --git a/vocode/turn_based/synthesizer/coqui_tts_synthesizer.py b/vocode/turn_based/synthesizer/coqui_tts_synthesizer.py index c1f2ca6f9..579d8512c 100644 --- a/vocode/turn_based/synthesizer/coqui_tts_synthesizer.py +++ b/vocode/turn_based/synthesizer/coqui_tts_synthesizer.py @@ -1,9 +1,10 @@ import io from typing import Optional -from pydub import AudioSegment -from vocode import getenv + import numpy +from pydub import AudioSegment +from vocode import getenv from vocode.turn_based.synthesizer.base_synthesizer import BaseSynthesizer diff --git a/vocode/turn_based/synthesizer/eleven_labs_synthesizer.py b/vocode/turn_based/synthesizer/eleven_labs_synthesizer.py index 9c5b2ffda..742bea578 100644 --- a/vocode/turn_based/synthesizer/eleven_labs_synthesizer.py +++ b/vocode/turn_based/synthesizer/eleven_labs_synthesizer.py @@ -1,6 +1,10 @@ import io from typing import Optional + +from elevenlabs import Voice, VoiceSettings +from elevenlabs.client import AsyncElevenLabs from pydub import AudioSegment + from vocode import getenv from vocode.turn_based.synthesizer.base_synthesizer import BaseSynthesizer @@ -13,12 +17,13 @@ def __init__( similarity_boost: Optional[float] = None, api_key: Optional[str] = None, ): - import elevenlabs - - self.elevenlabs = elevenlabs self.voice_id = voice_id self.api_key = getenv("ELEVEN_LABS_API_KEY", api_key) + + self.elevenlabs_client = AsyncElevenLabs( + api_key=self.api_key, + ) self.validate_stability_and_similarity_boost(stability, similarity_boost) self.stability = stability self.similarity_boost = similarity_boost @@ -27,18 +32,15 @@ def validate_stability_and_similarity_boost( self, stability: Optional[float], similarity_boost: Optional[float] ) -> None: if (stability is None) != (similarity_boost is None): - raise ValueError( - "Both stability and similarity_boost must be set or not set." - ) + raise ValueError("Both stability and similarity_boost must be set or not set.") def synthesize(self, text: str) -> AudioSegment: - self.elevenlabs.set_api_key(self.api_key) - voice = self.elevenlabs.Voice(voice_id=self.voice_id) + voice = Voice(voice_id=self.voice_id) if self.stability is not None and self.similarity_boost is not None: - voice.settings = self.elevenlabs.VoiceSettings( + voice.settings = VoiceSettings( stability=self.stability, similarity_boost=self.similarity_boost ) - audio = self.elevenlabs.generate(text, voice=voice) + audio = self.elevenlabs_client.generate(text=text, voice=voice) return AudioSegment.from_mp3(io.BytesIO(audio)) # type: ignore diff --git a/vocode/turn_based/synthesizer/google_synthesizer.py b/vocode/turn_based/synthesizer/google_synthesizer.py index 6c55a6461..ace1fe958 100644 --- a/vocode/turn_based/synthesizer/google_synthesizer.py +++ b/vocode/turn_based/synthesizer/google_synthesizer.py @@ -1,9 +1,11 @@ import io from typing import Optional + +from google.cloud import texttospeech_v1beta1 as tts # type: ignore from pydub import AudioSegment + from vocode import getenv from vocode.turn_based.synthesizer.base_synthesizer import BaseSynthesizer -from google.cloud import texttospeech_v1beta1 as tts DEFAULT_LANGUAGE_CODE = "en-US" DEFAULT_VOICE_NAME = "en-US-Neural2-I" @@ -11,9 +13,7 @@ DEFAULT_SPEAKING_RATE = 1.2 DEFAULT_SAMPLE_RATE = 24000 DEFAULT_AUDIO_ENCODING = tts.AudioEncoding.LINEAR16 -DEFAULT_TIME_POINTING = [ - tts.SynthesizeSpeechRequest.TimepointType.TIMEPOINT_TYPE_UNSPECIFIED -] +DEFAULT_TIME_POINTING = [tts.SynthesizeSpeechRequest.TimepointType.TIMEPOINT_TYPE_UNSPECIFIED] class GoogleSynthesizer(BaseSynthesizer): diff --git a/vocode/turn_based/synthesizer/gtts_synthesizer.py b/vocode/turn_based/synthesizer/gtts_synthesizer.py index 650241511..12be8dde3 100644 --- a/vocode/turn_based/synthesizer/gtts_synthesizer.py +++ b/vocode/turn_based/synthesizer/gtts_synthesizer.py @@ -1,7 +1,9 @@ +from io import BytesIO from os import PathLike from typing import Any + from pydub import AudioSegment -from io import BytesIO + from vocode.turn_based.synthesizer.base_synthesizer import BaseSynthesizer diff --git a/vocode/turn_based/synthesizer/play_ht_synthesizer.py b/vocode/turn_based/synthesizer/play_ht_synthesizer.py index 2481c17eb..00d5e84be 100644 --- a/vocode/turn_based/synthesizer/play_ht_synthesizer.py +++ b/vocode/turn_based/synthesizer/play_ht_synthesizer.py @@ -1,13 +1,14 @@ import io from typing import Optional -from pydub import AudioSegment + import requests -from vocode import getenv -from vocode.streaming.telephony.constants import DEFAULT_SAMPLING_RATE +from pydub import AudioSegment +from vocode import getenv +from vocode.streaming.models.audio import SamplingRate from vocode.turn_based.synthesizer.base_synthesizer import BaseSynthesizer -DEFAULT_SAMPLING_RATE = 24000 +DEFAULT_SAMPLING_RATE = SamplingRate.RATE_24000 TTS_ENDPOINT = "https://play.ht/api/v2/tts/stream" @@ -50,8 +51,6 @@ def synthesize( response = requests.post(TTS_ENDPOINT, headers=headers, json=body, timeout=5) if not response.ok: - raise Exception( - f"Play.ht API error: {response.status_code}, {response.text}" - ) + raise Exception(f"Play.ht API error: {response.status_code}, {response.text}") return AudioSegment.from_mp3(io.BytesIO(response.content)) # type: ignore diff --git a/vocode/turn_based/synthesizer/polly_synthesizer.py b/vocode/turn_based/synthesizer/polly_synthesizer.py index e8ad71de5..58fec724a 100644 --- a/vocode/turn_based/synthesizer/polly_synthesizer.py +++ b/vocode/turn_based/synthesizer/polly_synthesizer.py @@ -1,8 +1,9 @@ import io -from pydub import AudioSegment -from vocode.turn_based.synthesizer.base_synthesizer import BaseSynthesizer import boto3 +from pydub import AudioSegment + +from vocode.turn_based.synthesizer.base_synthesizer import BaseSynthesizer DEFAULT_SAMPLING_RATE = 16000 DEFAULT_LANGUAGE_CODE = "en-US" diff --git a/vocode/turn_based/synthesizer/rime_synthesizer.py b/vocode/turn_based/synthesizer/rime_synthesizer.py index 5e1da5273..99fdc406d 100644 --- a/vocode/turn_based/synthesizer/rime_synthesizer.py +++ b/vocode/turn_based/synthesizer/rime_synthesizer.py @@ -1,10 +1,11 @@ import base64 import io from typing import Optional -from pydub import AudioSegment + import requests -from vocode import getenv +from pydub import AudioSegment +from vocode import getenv from vocode.turn_based.synthesizer.base_synthesizer import BaseSynthesizer RIME_BASE_URL = "https://rjmopratfrdjgmfmaios.functions.supabase.co/rime-tts" diff --git a/vocode/turn_based/synthesizer/stream_elements_synthesizer.py b/vocode/turn_based/synthesizer/stream_elements_synthesizer.py index ff91c6489..1bb1ddc22 100644 --- a/vocode/turn_based/synthesizer/stream_elements_synthesizer.py +++ b/vocode/turn_based/synthesizer/stream_elements_synthesizer.py @@ -1,10 +1,10 @@ import io -import requests -from vocode.turn_based.synthesizer.base_synthesizer import BaseSynthesizer - +import requests from pydub import AudioSegment +from vocode.turn_based.synthesizer.base_synthesizer import BaseSynthesizer + class StreamElementsSynthesizer(BaseSynthesizer): def __init__(self, voice: str = "Brian"): diff --git a/vocode/turn_based/transcriber/sr_transcriber.py b/vocode/turn_based/transcriber/sr_transcriber.py index 16e33e058..dc20a4ab2 100644 --- a/vocode/turn_based/transcriber/sr_transcriber.py +++ b/vocode/turn_based/transcriber/sr_transcriber.py @@ -1,8 +1,10 @@ -from pydub import AudioSegment +from enum import Enum + import speech_recognition as sr +from pydub import AudioSegment + from vocode import getenv from vocode.turn_based.transcriber.base_transcriber import BaseTranscriber -from enum import Enum class SpeechRecognitionAPI(Enum): @@ -46,9 +48,7 @@ def transcribe(self, audio_segment: AudioSegment) -> str: credentials_json = getenv("GOOGLE_CLOUD_SPEECH_CREDENTIALS") if not credentials_json: raise ValueError("Google Cloud Speech credentials not provided") - text = r.recognize_google_cloud( - audio, credentials_json=credentials_json - ) + text = r.recognize_google_cloud(audio, credentials_json=credentials_json) elif self.api == SpeechRecognitionAPI.WIT: api_key = getenv("WIT_AI_API_KEY") @@ -76,17 +76,13 @@ def transcribe(self, audio_segment: AudioSegment) -> str: client_key = getenv("HOUNDIFY_CLIENT_KEY") if not client_id or not client_key: raise ValueError("Houndify client ID or key not provided") - text = r.recognize_houndify( - audio, client_id=client_id, client_key=client_key - ) + text = r.recognize_houndify(audio, client_id=client_id, client_key=client_key) elif self.api == SpeechRecognitionAPI.IBM: username = getenv("IBM_USERNAME") password = getenv("IBM_PASSWORD") if not username or not password: - raise ValueError( - "IBM Speech to Text username or password not provided" - ) + raise ValueError("IBM Speech to Text username or password not provided") text = r.recognize_ibm(audio, username=username, password=password) else: @@ -94,8 +90,6 @@ def transcribe(self, audio_segment: AudioSegment) -> str: except sr.UnknownValueError: raise sr.UnknownValueError("Speech Recognition could not understand audio") except sr.RequestError as e: - raise sr.RequestError( - f"Could not request results from Speech Recognition service." - ) + raise sr.RequestError(f"Could not request results from Speech Recognition service.") return text diff --git a/vocode/turn_based/transcriber/whisper_cpp_transcriber.py b/vocode/turn_based/transcriber/whisper_cpp_transcriber.py index ca9d2337b..57c0f7914 100644 --- a/vocode/turn_based/transcriber/whisper_cpp_transcriber.py +++ b/vocode/turn_based/transcriber/whisper_cpp_transcriber.py @@ -1,5 +1,6 @@ import ctypes import pathlib + import numpy as np from pydub import AudioSegment diff --git a/vocode/turn_based/transcriber/whisper_transcriber.py b/vocode/turn_based/transcriber/whisper_transcriber.py index 95e0d9736..1b6c582b1 100644 --- a/vocode/turn_based/transcriber/whisper_transcriber.py +++ b/vocode/turn_based/transcriber/whisper_transcriber.py @@ -1,9 +1,10 @@ -from typing import Optional -from pydub import AudioSegment import io +from typing import Optional + import openai -from vocode import getenv +from pydub import AudioSegment +from vocode import getenv from vocode.turn_based.transcriber.base_transcriber import BaseTranscriber @@ -12,11 +13,12 @@ def __init__(self, api_key: Optional[str] = None): openai.api_key = getenv("OPENAI_API_KEY", api_key) if not openai.api_key: raise ValueError("OpenAI API key not provided") + self.client = openai.OpenAI() def transcribe(self, audio_segment: AudioSegment) -> str: in_memory_wav = io.BytesIO() audio_segment.export(in_memory_wav, format="wav") # type: ignore in_memory_wav.seek(0) in_memory_wav.name = "whisper.wav" - transcript = openai.Audio.transcribe("whisper-1", in_memory_wav) + transcript = self.client.audio.transcriptions.create(model="whisper-1", file=in_memory_wav) return transcript.text diff --git a/vocode/turn_based/turn_based_conversation.py b/vocode/turn_based/turn_based_conversation.py index 3b30f9417..faddb613b 100644 --- a/vocode/turn_based/turn_based_conversation.py +++ b/vocode/turn_based/turn_based_conversation.py @@ -1,9 +1,7 @@ -import logging -from typing import Optional +from loguru import logger + from vocode.turn_based.agent.base_agent import BaseAgent -from vocode.turn_based.input_device.base_input_device import ( - BaseInputDevice, -) +from vocode.turn_based.input_device.base_input_device import BaseInputDevice from vocode.turn_based.output_device.base_output_device import BaseOutputDevice from vocode.turn_based.synthesizer.base_synthesizer import BaseSynthesizer from vocode.turn_based.transcriber.base_transcriber import BaseTranscriber @@ -17,7 +15,6 @@ def __init__( agent: BaseAgent, synthesizer: BaseSynthesizer, output_device: BaseOutputDevice, - logger: Optional[logging.Logger] = None, ): self.input_device = input_device self.transcriber = transcriber @@ -25,20 +22,17 @@ def __init__( self.synthesizer = synthesizer self.output_device = output_device self.maybe_play_initial_message() - self.logger = logger or logging.getLogger(__name__) def maybe_play_initial_message(self): if self.agent.initial_message: - self.output_device.send_audio( - self.synthesizer.synthesize(self.agent.initial_message) - ) + self.output_device.send_audio(self.synthesizer.synthesize(self.agent.initial_message)) def start_speech(self): self.input_device.start_listening() def end_speech_and_respond(self): human_input = self.transcriber.transcribe(self.input_device.end_listening()) - self.logger.info(f"Transcription: {human_input}") + logger.info(f"Transcription: {human_input}") agent_response = self.agent.respond(human_input) - self.logger.info(f"Agent response: {agent_response}") + logger.info(f"Agent response: {agent_response}") self.output_device.send_audio(self.synthesizer.synthesize(agent_response)) diff --git a/vocode/utils/sentry_utils.py b/vocode/utils/sentry_utils.py new file mode 100644 index 000000000..f27829fd0 --- /dev/null +++ b/vocode/utils/sentry_utils.py @@ -0,0 +1,243 @@ +import functools +from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Tuple + +from loguru import logger + +from vocode import get_serialized_ctx_wrappers + +try: + import sentry_sdk + from sentry_sdk.tracing import Span, Transaction, _SpanRecorder + + SENTRY_SDK_AVAILABLE = True +except ImportError: + logger.debug("Sentry SDK not detected -- disabling metrics!") + SENTRY_SDK_AVAILABLE = False + +if TYPE_CHECKING: + from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer + +_SYNTHESIZER_NAMES = { + "AzureSynthesizer": "azure", + "ElevenLabsSynthesizer": "eleven_labs", + "ElevenLabsWSSynthesizer": "eleven_labs_ws", + "PlayHtSynthesizer": "play_ht", + "PlayHtSynthesizerV2": "play_ht_v2", + "RimeSynthesizer": "rime", +} + +_FILTERED_SPANS = {"middleware.starlette.receive", "middleware.starlette.send", "Queue.get"} + + +class CustomSentrySpans: + CONNECTED_TO_FIRST_SEND = "connected_to_first_send" + ENDPOINTING_LATENCY = "endpointing_latency" + FIRST_SEND_TO_FIRST_RECEIVE = "first_send_to_first_receive" + LANGUAGE_MODEL_TIME_TO_FIRST_TOKEN = "language_model_time_to_first_token" + LATENCY_OF_CONVERSATION = "latency_of_conversation" + LATENCY_OF_TRANSCRIPTION_START = "latency_of_transcription_start" + LLM_FIRST_SENTENCE_TOTAL = "llm_first_sentence_total" + START_TO_CONNECTION = "start_to_connection" + SYNTHESIS_GENERATE_FIRST_CHUNK = "synthesis_generate_first_chunk" + SYNTHESIS_TIME_TO_FIRST_TOKEN = "synthesis_time_to_first_token" + TIME_TO_FIRST_TOKEN = "time_to_first_token" + + SYNTHESIZER_SYNTHESIS_TOTAL = ".synthesis_total" + SYNTHESIZER_TIME_TO_FIRST_TOKEN = ".time_to_first_token" + SYNTHESIZER_CREATE_SPEECH = ".create_speech" + + @classmethod + def is_present(cls, value): + for attr in dir(cls): + if not attr.startswith("__"): + attr_value = getattr(cls, attr) + if isinstance(attr_value, str) and ( + attr_value == value or value.endswith(attr_value) + ): + return True + return False + + +class SentryConfiguredContextManager: + """ + A context manager that only executes a function if Sentry is configured. + + Attributes: + func (Callable): The function to be executed. + args (Tuple): The positional arguments to pass to the function. + kwargs (Dict): The keyword arguments to pass to the function. + result (Any): The result of the function execution. + """ + + def __init__(self, func: Callable, *args: Tuple, **kwargs: Dict) -> None: + """ + Constructs all the necessary attributes for the SentryConfiguredContextManager object. + + Args: + func (Callable): The function to be executed. + *args (Tuple): The positional arguments to pass to the function. + **kwargs (Dict): The keyword arguments to pass to the function. + """ + self.func = func + self.args = args + self.kwargs = kwargs + self.result: Optional[Any] = None + + @property + def is_configured(self) -> bool: + """ + Checks if Sentry is available and configured. + + Returns: + bool: True if Sentry is configured, False otherwise. + """ + if not SENTRY_SDK_AVAILABLE: + return False + + client = sentry_sdk.Hub.current.client + if client is not None and client.options is not None and "dsn" in client.options: + return True + return False + + def __enter__(self) -> Optional[Any]: + """ + Executes the function if Sentry is configured. + + Returns: + Any: The result of the function execution, or None if Sentry is not configured. + """ + if self.is_configured: + self.result = self.func(*self.args, **self.kwargs) + return self.result + else: + return None + + def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None: + """ + Defines the behavior when exiting the context. + + Args: + exc_type (Any): The type of the exception. + exc_val (Any): The value of the exception. + exc_tb (Any): The traceback of the exception. + """ + pass + + def __call__(self) -> Optional[Any]: + """ + Executes the function if Sentry is configured, and prints a message if it's not. + + Returns: + Any: The result of the function execution, or None if Sentry is not configured. + """ + if self.is_configured: + return self.func(*self.args, **self.kwargs) + else: + logger.debug("Sentry is not configured, skipping function execution.") + return None + + def execute(self) -> Optional[Any]: + """Executes the wrapped function immediately and returns its result.""" + return self() + + +def sentry_configured(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + context_manager = SentryConfiguredContextManager(func, *args, **kwargs) + if "with" not in func.__code__.co_names: + return context_manager.execute() + return context_manager + + return wrapper + + +def synthesizer_base_name_if_should_report_to_sentry( + synthesizer: "BaseSynthesizer", +) -> Optional[str]: + """Returns a synthesizer name if we should report metrics to Sentry for this + kind of synthesizer; else returns None. + """ + return f"synthesizer.{_SYNTHESIZER_NAMES.get(synthesizer.__class__.__qualname__)}" + + +@sentry_configured +def set_tags(span: Span) -> Span: + serialized_ctx_wrappers = get_serialized_ctx_wrappers() + for name, value in serialized_ctx_wrappers.items(): + span.set_tag(name, value) + if not span.description: + span.description = serialized_ctx_wrappers.get("conversation_id") or span.op + return span + + +@sentry_configured +def get_span_by_op(op_value): + transaction: Transaction = sentry_sdk.Hub.current.scope.transaction + if transaction is not None: + # Probably not great accessing an internal variable but transaction spans aren't + # exposed publicly so it is what it is. + span_matches = [ + span + for span in transaction._span_recorder.spans + if span.op == op_value and span.timestamp is None + ] + if span_matches: + most_recent_span = max( + span_matches, key=lambda span: span.start_timestamp, default=None + ) + if most_recent_span is not None: + return set_tags(most_recent_span) + else: + # If no span with the matching op was found + logger.error(f"No span found with op '{op_value}'.") + return None + else: + logger.debug("No active transaction found.") + return None + + +@sentry_configured +def complete_span_by_op(op_value): + span = get_span_by_op(op_value) + if span is None: + logger.error(f"No span found with op '{op_value}'.") + return None + span.finish() + + +@sentry_configured +def sentry_create_span(*args, sentry_callable: Callable, **kwargs) -> Span: + span = sentry_callable(*args, **kwargs) + + return set_tags(span) + + +class SpanRecorder(_SpanRecorder): + + def __init__(self, maxlen): + self.maxlen = 900 + self._auto_spans = [] + self._custom_spans = [] + self._low_prio_spans = [] + + def add(self, span: Span): + if span.op in _FILTERED_SPANS and span.description in _FILTERED_SPANS: + self._low_prio_spans.append(span) + else: + if CustomSentrySpans.is_present(span.op): + self._custom_spans.append(span) + else: + self._auto_spans.append(span) + + @property + def spans(self): + return (self._custom_spans + self._auto_spans + self._low_prio_spans)[: self.maxlen] + + +def init_span_recorder(self, maxlen: int): + if self._span_recorder is None: + self._span_recorder = SpanRecorder(maxlen) + + +Span.init_span_recorder = init_span_recorder # type: ignore diff --git a/vocode/utils/whisper_cpp/helpers.py b/vocode/utils/whisper_cpp/helpers.py index e99004448..d3076f811 100644 --- a/vocode/utils/whisper_cpp/helpers.py +++ b/vocode/utils/whisper_cpp/helpers.py @@ -1,6 +1,7 @@ import ctypes import re from typing import Tuple + import numpy as np from pydub import AudioSegment @@ -9,9 +10,9 @@ def transcribe(whisper, params, ctx, audio_segment: AudioSegment) -> Tuple[str, if len(audio_segment) <= 100: return "", 0.0 normalized = ( - np.frombuffer( - audio_segment.set_frame_rate(16000).raw_data, dtype=np.int16 - ).astype("float32") + np.frombuffer(audio_segment.set_frame_rate(16000).raw_data, dtype=np.int16).astype( + "float32" + ) / 32768.0 ) @@ -24,9 +25,7 @@ def transcribe(whisper, params, ctx, audio_segment: AudioSegment) -> Tuple[str, if result != 0: print("Error: {}".format(result)) exit(1) - text: str = whisper.whisper_full_get_segment_text(ctypes.c_void_p(ctx), 0).decode( - "utf-8" - ) + text: str = whisper.whisper_full_get_segment_text(ctypes.c_void_p(ctx), 0).decode("utf-8") # heuristic to filter out non-speech if not re.search(r"^\w.*", text.strip()): return "", 0.0 diff --git a/vocode/utils/whisper_cpp/whisper_params.py b/vocode/utils/whisper_cpp/whisper_params.py index 0777dbb58..1b5e7e76c 100644 --- a/vocode/utils/whisper_cpp/whisper_params.py +++ b/vocode/utils/whisper_cpp/whisper_params.py @@ -5,14 +5,13 @@ class WhisperFullParams(ctypes.Structure): _fields_ = [ ("strategy", ctypes.c_int), # - ("n_threads", ctypes.c_int), ("n_max_text_ctx", ctypes.c_int), + ("n_threads", ctypes.c_int), ("offset_ms", ctypes.c_int), ("duration_ms", ctypes.c_int), # ("translate", ctypes.c_bool), ("no_context", ctypes.c_bool), - ("no_timestamps", ctypes.c_bool), ("single_segment", ctypes.c_bool), ("print_special", ctypes.c_bool), ("print_progress", ctypes.c_bool), @@ -27,17 +26,13 @@ class WhisperFullParams(ctypes.Structure): ("max_tokens", ctypes.c_int), # ("speed_up", ctypes.c_bool), - ("debug_mode", ctypes.c_bool), ("audio_ctx", ctypes.c_int), # - ("tdrz_enable", ctypes.c_bool), - # ("initial_prompt", ctypes.c_char_p), ("prompt_tokens", ctypes.c_void_p), ("prompt_n_tokens", ctypes.c_int), # ("language", ctypes.c_char_p), - ("detect_language", ctypes.c_bool), # ("suppress_blank", ctypes.c_bool), ("suppress_non_speech_tokens", ctypes.c_bool), @@ -52,7 +47,7 @@ class WhisperFullParams(ctypes.Structure): ("no_speech_thold", ctypes.c_float), # ("greedy", ctypes.c_int * 1), - ("beam_search", ctypes.c_int * 2), + ("beam_search", ctypes.c_int * 3), # ("new_segment_callback", ctypes.c_void_p), ("new_segment_callback_user_data", ctypes.c_void_p), @@ -65,9 +60,4 @@ class WhisperFullParams(ctypes.Structure): # ("logits_filter_callback", ctypes.c_void_p), ("logits_filter_callback_user_data", ctypes.c_void_p), - # - ("grammar_rules", ctypes.POINTER(ctypes.c_void_p)), - ("n_grammar_rules", ctypes.c_size_t), - ("i_start_rule", ctypes.c_size_t), - ("grammar_penalty", ctypes.c_float), ] From 3d7f0d39953dfc4d9da02a2ff2be25c1c9a87b97 Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Thu, 30 May 2024 23:20:33 -0700 Subject: [PATCH 03/25] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d02598156..1862811f8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 🤫 Vocode 0.0.112 Early Preview +# 🚀 Vocode 0.0.112 Early Preview 👋 Hey there, Vocode Explorer! From 78cda9e06e61eafc311e727e0518044250da2b16 Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Sun, 2 Jun 2024 15:17:08 -0700 Subject: [PATCH 04/25] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1862811f8..25e7ccba5 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ 👋 Hey there, Vocode Explorer! -Congratulations! You've stumbled upon the Vocode 0.0.112 Early Preview Repo! Whether we (the Vocode team) sent you this link or you found it through your own detective work, we want to celebrate your awesomeness in the Vocode community with this exclusive sneak peek of our latest work! +Congratulations! You've stumbled upon the Vocode 0.0.112 Early Preview Repo! Whether we (the Vocode team) sent you this link or you found it through your own detective work, we want to celebrate your awesomeness in the Vocode community with this sneak peek of our latest work! ## 🎉 What's Next? From eaaf4d18d70d0eab635515ad48f022cad4324417 Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Tue, 4 Jun 2024 14:22:21 -0700 Subject: [PATCH 05/25] fix turn based quickstart (#3) --- vocode/turn_based/agent/__init__.py | 4 ---- vocode/turn_based/transcriber/__init__.py | 4 ---- 2 files changed, 8 deletions(-) delete mode 100644 vocode/turn_based/agent/__init__.py delete mode 100644 vocode/turn_based/transcriber/__init__.py diff --git a/vocode/turn_based/agent/__init__.py b/vocode/turn_based/agent/__init__.py deleted file mode 100644 index c0291ecb7..000000000 --- a/vocode/turn_based/agent/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from vocode.turn_based.agent.base_agent import BaseAgent -from vocode.turn_based.agent.chat_gpt_agent import ChatGPTAgent -from vocode.turn_based.agent.echo_agent import EchoAgent -from vocode.turn_based.agent.gpt4all_agent import GPT4AllAgent diff --git a/vocode/turn_based/transcriber/__init__.py b/vocode/turn_based/transcriber/__init__.py deleted file mode 100644 index 50631f547..000000000 --- a/vocode/turn_based/transcriber/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from vocode.turn_based.transcriber.base_transcriber import BaseTranscriber -from vocode.turn_based.transcriber.sr_transcriber import SpeechRecognitionTranscriber -from vocode.turn_based.transcriber.whisper_cpp_transcriber import WhisperCPPTranscriber -from vocode.turn_based.transcriber.whisper_transcriber import WhisperTranscriber From 838091154ba215b1002b73946ac52fc5e9a1c65e Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Tue, 4 Jun 2024 14:29:40 -0700 Subject: [PATCH 06/25] [hotfix] remove unused import (#4) --- vocode/streaming/models/actions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/vocode/streaming/models/actions.py b/vocode/streaming/models/actions.py index 52afeeaec..47b7e454c 100644 --- a/vocode/streaming/models/actions.py +++ b/vocode/streaming/models/actions.py @@ -1,5 +1,4 @@ import asyncio -from distutils.sysconfig import EXEC_PREFIX from enum import Enum from typing import Annotated, Generic, List, Literal, Optional, TypeVar, Union From 8c53bfeebc504f54a449b5473c317f8f406cd1a8 Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Thu, 6 Jun 2024 09:53:29 -0700 Subject: [PATCH 07/25] Update README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 25e7ccba5..5cc83afc6 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ We’re super excited to share this with you, but we’d appreciate it if you co - Synthesizers - Telephony Providers -### 👥 Conversation Mechanics +### 👥 Conversation Mechanics (guide to follow!) - Better endpointing (agnostic of transcribers) - Better interruption handling @@ -40,10 +40,10 @@ We’re super excited to share this with you, but we’d appreciate it if you co ### 💪 Actions -- ✨NEW✨ External Actions +- ✨NEW✨ External Actions (guide to follow!) - Improved Call Transfer - ✨NEW✨ Wait Actions (IVR Navigation) -- ✨NEW✨ Phrase triggers for actions (instead of function calls) +- ✨NEW✨ Phrase triggers for actions (instead of function calls) (guide to follow!) ### 🗣️ Synthesizers @@ -62,12 +62,12 @@ We’re super excited to share this with you, but we’d appreciate it if you co - Twilio - Stronger interruption handling by [clearing audio queues](https://www.twilio.com/docs/voice/media-streams/websocket-messages#send-a-clear-message) - Vonage - - Koala Noise Suppression + - Koala Noise Suppression (guide to follow!) ### 🎉 Miscellaneous - ✨NEW✨  Loguru for improved logging formatting - - Some new utilities to make setting up loguru in your projects fast and easy 😉 -- Sentry for Metric / Error Collection + - Some new utilities to make setting up loguru in your projects fast and easy 😉 (guide to follow!) +- Sentry for Metric / Error Collection (guide to follow!) - Clean handling of content filters in ChatGPT agents - Redis Message Queue for tracking mid-call events across different instances From 69df5bc252422174db68bae58c004ae9f7ef3d50 Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Thu, 6 Jun 2024 10:03:46 -0700 Subject: [PATCH 08/25] Update README.md --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 5cc83afc6..882b3621b 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,15 @@ If you can see this but don't have access to the new channels, just reach out to We’re super excited to share this with you, but we’d appreciate it if you could keep this on the down-low for now. While we know you might share this with close friends, please avoid posting it in public places. We're still polishing things up for the big public launch! +## 📜 Viewing Preview Docs + +We'll be updating our existing documentation and adding guides for new functionality (see below) in this fork itself. To view them, use the [Mintlify CLI](https://mintlify.com/docs/development): + +``` +/path/to/vocode-python > cd docs +/path/to/vocode-python/docs > mintlify dev +``` + ## 📝 Brief Changelog ### 🧱Vocode Core Abstractions Revamp From e1f6fbd1f542e9002ea2390822fa6cb1e60c2561 Mon Sep 17 00:00:00 2001 From: Adnaan Sachidanandan Date: Thu, 6 Jun 2024 10:43:19 -0700 Subject: [PATCH 09/25] Remove create_speech() from rime synthesizer (#6) --- .../streaming/synthesizer/rime_synthesizer.py | 35 ------------------- 1 file changed, 35 deletions(-) diff --git a/vocode/streaming/synthesizer/rime_synthesizer.py b/vocode/streaming/synthesizer/rime_synthesizer.py index acb77480c..f776da4a8 100644 --- a/vocode/streaming/synthesizer/rime_synthesizer.py +++ b/vocode/streaming/synthesizer/rime_synthesizer.py @@ -142,38 +142,3 @@ def get_request_body(self, text): body["modelId"] = self.model_id return body - - async def create_speech( - self, - message: BaseMessage, - chunk_size: int, - is_first_text_chunk: bool = False, - is_sole_text_chunk: bool = False, - ) -> SynthesisResult: - headers = { - "Authorization": self.api_key, - "Content-Type": "application/json", - } - - body = self.get_request_body(message.text) - - async with self.async_requestor.get_session().post( - self.base_url, - headers=headers, - json=body, - timeout=aiohttp.ClientTimeout(total=15), - ) as response: - if not response.ok: - raise Exception(f"Rime API error: {response.status}, {await response.text()}") - data = await response.json() - - audio_file = io.BytesIO(base64.b64decode(data.get("audioContent"))) - - result = self.create_synthesis_result_from_wav( - synthesizer_config=self.synthesizer_config, - file=audio_file, - message=message, - chunk_size=chunk_size, - ) - - return result From 239addb791a229383bd9bdbcddc5fe734f10dcf5 Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Fri, 7 Jun 2024 09:45:02 -0700 Subject: [PATCH 10/25] Fix default factory for elevenlabs WS (#12) * dispatch into elvenlabsws if experimental_websocket is on * fix mypy --- vocode/streaming/synthesizer/default_factory.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/vocode/streaming/synthesizer/default_factory.py b/vocode/streaming/synthesizer/default_factory.py index b5f8b654a..7539cf1dd 100644 --- a/vocode/streaming/synthesizer/default_factory.py +++ b/vocode/streaming/synthesizer/default_factory.py @@ -1,3 +1,4 @@ +from typing import Type from vocode.streaming.models.synthesizer import ( AzureSynthesizerConfig, ElevenLabsSynthesizerConfig, @@ -8,7 +9,9 @@ ) from vocode.streaming.synthesizer.abstract_factory import AbstractSynthesizerFactory from vocode.streaming.synthesizer.azure_synthesizer import AzureSynthesizer +from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer from vocode.streaming.synthesizer.eleven_labs_synthesizer import ElevenLabsSynthesizer +from vocode.streaming.synthesizer.eleven_labs_websocket_synthesizer import ElevenLabsWSSynthesizer from vocode.streaming.synthesizer.play_ht_synthesizer import PlayHtSynthesizer from vocode.streaming.synthesizer.play_ht_synthesizer_v2 import PlayHtSynthesizerV2 from vocode.streaming.synthesizer.rime_synthesizer import RimeSynthesizer @@ -23,7 +26,10 @@ def create_synthesizer( if isinstance(synthesizer_config, AzureSynthesizerConfig): return AzureSynthesizer(synthesizer_config) elif isinstance(synthesizer_config, ElevenLabsSynthesizerConfig): - return ElevenLabsSynthesizer(synthesizer_config) + eleven_labs_synthesizer_class_type: Type[BaseSynthesizer] = ElevenLabsSynthesizer + if synthesizer_config.experimental_websocket: + eleven_labs_synthesizer_class_type = ElevenLabsWSSynthesizer + return eleven_labs_synthesizer_class_type(synthesizer_config) elif isinstance(synthesizer_config, PlayHtSynthesizerConfig): if synthesizer_config.version == "2": return PlayHtSynthesizerV2(synthesizer_config) From cfd6226e7b5534f1fbac807f965bd78d7b06d33d Mon Sep 17 00:00:00 2001 From: Mac Wilkinson Date: Fri, 7 Jun 2024 09:45:58 -0700 Subject: [PATCH 11/25] Merge In Recent Fixes (#14) --- poetry.lock | 610 +++++++++--------- pyproject.toml | 36 +- quickstarts/streaming_conversation.py | 42 +- quickstarts/turn_based_conversation.py | 34 +- vocode/__init__.py | 4 + vocode/meta.py | 15 + vocode/streaming/agent/chat_gpt_agent.py | 81 ++- vocode/streaming/agent/default_factory.py | 1 - vocode/streaming/agent/llamacpp_agent.py | 257 ++++---- vocode/streaming/models/agent.py | 13 +- vocode/streaming/models/transcriber.py | 1 + vocode/streaming/streaming_conversation.py | 24 +- .../streaming/synthesizer/base_synthesizer.py | 17 + .../synthesizer/eleven_labs_synthesizer.py | 22 +- .../eleven_labs_websocket_synthesizer.py | 18 +- .../telephony/client/vonage_client.py | 9 +- .../conversation/twilio_phone_conversation.py | 1 + .../transcriber/azure_transcriber.py | 1 - .../transcriber/deepgram_transcriber.py | 8 +- .../utils/redis_conversation_message_queue.py | 4 +- vocode/streaming/vector_db/base_vector_db.py | 8 +- vocode/streaming/vector_db/factory.py | 20 +- .../synthesizer/eleven_labs_synthesizer.py | 14 +- vocode/utils/sentry_utils.py | 16 +- 24 files changed, 713 insertions(+), 543 deletions(-) create mode 100644 vocode/meta.py diff --git a/poetry.lock b/poetry.lock index c349910d4..e9786cffe 100644 --- a/poetry.lock +++ b/poetry.lock @@ -317,13 +317,13 @@ files = [ [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.6.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"}, + {file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"}, ] [[package]] @@ -583,43 +583,43 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "42.0.7" +version = "42.0.8" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"}, - {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"}, - {file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"}, - {file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"}, - {file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"}, - {file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"}, - {file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"}, - {file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"}, + {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"}, + {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"}, + {file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"}, + {file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"}, + {file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"}, + {file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"}, + {file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"}, + {file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"}, ] [package.dependencies] @@ -942,13 +942,13 @@ files = [ [[package]] name = "fsspec" -version = "2024.5.0" +version = "2024.6.0" description = "File-system specification" optional = true python-versions = ">=3.8" files = [ - {file = "fsspec-2024.5.0-py3-none-any.whl", hash = "sha256:e0fdbc446d67e182f49a70b82cf7889028a63588fde6b222521f10937b2b670c"}, - {file = "fsspec-2024.5.0.tar.gz", hash = "sha256:1d021b0b0f933e3b3029ed808eb400c08ba101ca2de4b3483fbc9ca23fcee94a"}, + {file = "fsspec-2024.6.0-py3-none-any.whl", hash = "sha256:58d7122eb8a1a46f7f13453187bfea4972d66bf01618d37366521b1998034cee"}, + {file = "fsspec-2024.6.0.tar.gz", hash = "sha256:f579960a56e6d8038a9efc8f9c77279ec12e6299aa86b0769a7e9c46b94527c2"}, ] [package.extras] @@ -957,6 +957,7 @@ adl = ["adlfs"] arrow = ["pyarrow (>=1)"] dask = ["dask", "distributed"] dev = ["pre-commit", "ruff"] +doc = ["numpydoc", "sphinx", "sphinx-design", "sphinx-rtd-theme", "yarl"] dropbox = ["dropbox", "dropboxdrivefs", "requests"] full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] fuse = ["fusepy"] @@ -1068,17 +1069,17 @@ protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4 [[package]] name = "googleapis-common-protos" -version = "1.63.0" +version = "1.63.1" description = "Common protobufs used in Google APIs" optional = true python-versions = ">=3.7" files = [ - {file = "googleapis-common-protos-1.63.0.tar.gz", hash = "sha256:17ad01b11d5f1d0171c06d3ba5c04c54474e883b66b949722b4938ee2694ef4e"}, - {file = "googleapis_common_protos-1.63.0-py2.py3-none-any.whl", hash = "sha256:ae45f75702f7c08b541f750854a678bd8f534a1a6bace6afe975f1d0a82d6632"}, + {file = "googleapis-common-protos-1.63.1.tar.gz", hash = "sha256:c6442f7a0a6b2a80369457d79e6672bb7dcbaab88e0848302497e3ec80780a6a"}, + {file = "googleapis_common_protos-1.63.1-py2.py3-none-any.whl", hash = "sha256:0e1c2cdfcbc354b76e4a211a35ea35d6926a835cba1377073c4861db904a1877"}, ] [package.dependencies] -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" [package.extras] grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] @@ -1156,61 +1157,61 @@ test = ["objgraph", "psutil"] [[package]] name = "grpcio" -version = "1.64.0" +version = "1.64.1" description = "HTTP/2-based RPC framework" optional = true python-versions = ">=3.8" files = [ - {file = "grpcio-1.64.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:3b09c3d9de95461214a11d82cc0e6a46a6f4e1f91834b50782f932895215e5db"}, - {file = "grpcio-1.64.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:7e013428ab472892830287dd082b7d129f4d8afef49227a28223a77337555eaa"}, - {file = "grpcio-1.64.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:02cc9cc3f816d30f7993d0d408043b4a7d6a02346d251694d8ab1f78cc723e7e"}, - {file = "grpcio-1.64.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f5de082d936e0208ce8db9095821361dfa97af8767a6607ae71425ac8ace15c"}, - {file = "grpcio-1.64.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7b7bf346391dffa182fba42506adf3a84f4a718a05e445b37824136047686a1"}, - {file = "grpcio-1.64.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b2cbdfba18408389a1371f8c2af1659119e1831e5ed24c240cae9e27b4abc38d"}, - {file = "grpcio-1.64.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:aca4f15427d2df592e0c8f3d38847e25135e4092d7f70f02452c0e90d6a02d6d"}, - {file = "grpcio-1.64.0-cp310-cp310-win32.whl", hash = "sha256:7c1f5b2298244472bcda49b599be04579f26425af0fd80d3f2eb5fd8bc84d106"}, - {file = "grpcio-1.64.0-cp310-cp310-win_amd64.whl", hash = "sha256:73f84f9e5985a532e47880b3924867de16fa1aa513fff9b26106220c253c70c5"}, - {file = "grpcio-1.64.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:2a18090371d138a57714ee9bffd6c9c9cb2e02ce42c681aac093ae1e7189ed21"}, - {file = "grpcio-1.64.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:59c68df3a934a586c3473d15956d23a618b8f05b5e7a3a904d40300e9c69cbf0"}, - {file = "grpcio-1.64.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:b52e1ec7185512103dd47d41cf34ea78e7a7361ba460187ddd2416b480e0938c"}, - {file = "grpcio-1.64.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d598b5d5e2c9115d7fb7e2cb5508d14286af506a75950762aa1372d60e41851"}, - {file = "grpcio-1.64.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01615bbcae6875eee8091e6b9414072f4e4b00d8b7e141f89635bdae7cf784e5"}, - {file = "grpcio-1.64.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0b2dfe6dcace264807d9123d483d4c43274e3f8c39f90ff51de538245d7a4145"}, - {file = "grpcio-1.64.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7f17572dc9acd5e6dfd3014d10c0b533e9f79cd9517fc10b0225746f4c24b58e"}, - {file = "grpcio-1.64.0-cp311-cp311-win32.whl", hash = "sha256:6ec5ed15b4ffe56e2c6bc76af45e6b591c9be0224b3fb090adfb205c9012367d"}, - {file = "grpcio-1.64.0-cp311-cp311-win_amd64.whl", hash = "sha256:597191370951b477b7a1441e1aaa5cacebeb46a3b0bd240ec3bb2f28298c7553"}, - {file = "grpcio-1.64.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:1ce4cd5a61d4532651079e7aae0fedf9a80e613eed895d5b9743e66b52d15812"}, - {file = "grpcio-1.64.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:650a8150a9b288f40d5b7c1d5400cc11724eae50bd1f501a66e1ea949173649b"}, - {file = "grpcio-1.64.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:8de0399b983f8676a7ccfdd45e5b2caec74a7e3cc576c6b1eecf3b3680deda5e"}, - {file = "grpcio-1.64.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:46b8b43ba6a2a8f3103f103f97996cad507bcfd72359af6516363c48793d5a7b"}, - {file = "grpcio-1.64.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a54362f03d4dcfae63be455d0a7d4c1403673498b92c6bfe22157d935b57c7a9"}, - {file = "grpcio-1.64.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1f8ea18b928e539046bb5f9c124d717fbf00cc4b2d960ae0b8468562846f5aa1"}, - {file = "grpcio-1.64.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c56c91bd2923ddb6e7ed28ebb66d15633b03e0df22206f22dfcdde08047e0a48"}, - {file = "grpcio-1.64.0-cp312-cp312-win32.whl", hash = "sha256:874c741c8a66f0834f653a69e7e64b4e67fcd4a8d40296919b93bab2ccc780ba"}, - {file = "grpcio-1.64.0-cp312-cp312-win_amd64.whl", hash = "sha256:0da1d921f8e4bcee307aeef6c7095eb26e617c471f8cb1c454fd389c5c296d1e"}, - {file = "grpcio-1.64.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:c46fb6bfca17bfc49f011eb53416e61472fa96caa0979b4329176bdd38cbbf2a"}, - {file = "grpcio-1.64.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3d2004e85cf5213995d09408501f82c8534700d2babeb81dfdba2a3bff0bb396"}, - {file = "grpcio-1.64.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:6d5541eb460d73a07418524fb64dcfe0adfbcd32e2dac0f8f90ce5b9dd6c046c"}, - {file = "grpcio-1.64.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f279ad72dd7d64412e10f2443f9f34872a938c67387863c4cd2fb837f53e7d2"}, - {file = "grpcio-1.64.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85fda90b81da25993aa47fae66cae747b921f8f6777550895fb62375b776a231"}, - {file = "grpcio-1.64.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a053584079b793a54bece4a7d1d1b5c0645bdbee729215cd433703dc2532f72b"}, - {file = "grpcio-1.64.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:579dd9fb11bc73f0de061cab5f8b2def21480fd99eb3743ed041ad6a1913ee2f"}, - {file = "grpcio-1.64.0-cp38-cp38-win32.whl", hash = "sha256:23b6887bb21d77649d022fa1859e05853fdc2e60682fd86c3db652a555a282e0"}, - {file = "grpcio-1.64.0-cp38-cp38-win_amd64.whl", hash = "sha256:753cb58683ba0c545306f4e17dabf468d29cb6f6b11832e1e432160bb3f8403c"}, - {file = "grpcio-1.64.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:2186d76a7e383e1466e0ea2b0febc343ffeae13928c63c6ec6826533c2d69590"}, - {file = "grpcio-1.64.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0f30596cdcbed3c98024fb4f1d91745146385b3f9fd10c9f2270cbfe2ed7ed91"}, - {file = "grpcio-1.64.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:d9171f025a196f5bcfec7e8e7ffb7c3535f7d60aecd3503f9e250296c7cfc150"}, - {file = "grpcio-1.64.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf4c8daed18ae2be2f1fc7d613a76ee2a2e28fdf2412d5c128be23144d28283d"}, - {file = "grpcio-1.64.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3550493ac1d23198d46dc9c9b24b411cef613798dc31160c7138568ec26bc9b4"}, - {file = "grpcio-1.64.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3161a8f8bb38077a6470508c1a7301cd54301c53b8a34bb83e3c9764874ecabd"}, - {file = "grpcio-1.64.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2e8fabe2cc57a369638ab1ad8e6043721014fdf9a13baa7c0e35995d3a4a7618"}, - {file = "grpcio-1.64.0-cp39-cp39-win32.whl", hash = "sha256:31890b24d47b62cc27da49a462efe3d02f3c120edb0e6c46dcc0025506acf004"}, - {file = "grpcio-1.64.0-cp39-cp39-win_amd64.whl", hash = "sha256:5a56797dea8c02e7d3a85dfea879f286175cf4d14fbd9ab3ef2477277b927baa"}, - {file = "grpcio-1.64.0.tar.gz", hash = "sha256:257baf07f53a571c215eebe9679c3058a313fd1d1f7c4eede5a8660108c52d9c"}, + {file = "grpcio-1.64.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:55697ecec192bc3f2f3cc13a295ab670f51de29884ca9ae6cd6247df55df2502"}, + {file = "grpcio-1.64.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:3b64ae304c175671efdaa7ec9ae2cc36996b681eb63ca39c464958396697daff"}, + {file = "grpcio-1.64.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:bac71b4b28bc9af61efcdc7630b166440bbfbaa80940c9a697271b5e1dabbc61"}, + {file = "grpcio-1.64.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c024ffc22d6dc59000faf8ad781696d81e8e38f4078cb0f2630b4a3cf231a90"}, + {file = "grpcio-1.64.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7cd5c1325f6808b8ae31657d281aadb2a51ac11ab081ae335f4f7fc44c1721d"}, + {file = "grpcio-1.64.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0a2813093ddb27418a4c99f9b1c223fab0b053157176a64cc9db0f4557b69bd9"}, + {file = "grpcio-1.64.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2981c7365a9353f9b5c864595c510c983251b1ab403e05b1ccc70a3d9541a73b"}, + {file = "grpcio-1.64.1-cp310-cp310-win32.whl", hash = "sha256:1262402af5a511c245c3ae918167eca57342c72320dffae5d9b51840c4b2f86d"}, + {file = "grpcio-1.64.1-cp310-cp310-win_amd64.whl", hash = "sha256:19264fc964576ddb065368cae953f8d0514ecc6cb3da8903766d9fb9d4554c33"}, + {file = "grpcio-1.64.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:58b1041e7c870bb30ee41d3090cbd6f0851f30ae4eb68228955d973d3efa2e61"}, + {file = "grpcio-1.64.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bbc5b1d78a7822b0a84c6f8917faa986c1a744e65d762ef6d8be9d75677af2ca"}, + {file = "grpcio-1.64.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:5841dd1f284bd1b3d8a6eca3a7f062b06f1eec09b184397e1d1d43447e89a7ae"}, + {file = "grpcio-1.64.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8caee47e970b92b3dd948371230fcceb80d3f2277b3bf7fbd7c0564e7d39068e"}, + {file = "grpcio-1.64.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73819689c169417a4f978e562d24f2def2be75739c4bed1992435d007819da1b"}, + {file = "grpcio-1.64.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6503b64c8b2dfad299749cad1b595c650c91e5b2c8a1b775380fcf8d2cbba1e9"}, + {file = "grpcio-1.64.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1de403fc1305fd96cfa75e83be3dee8538f2413a6b1685b8452301c7ba33c294"}, + {file = "grpcio-1.64.1-cp311-cp311-win32.whl", hash = "sha256:d4d29cc612e1332237877dfa7fe687157973aab1d63bd0f84cf06692f04c0367"}, + {file = "grpcio-1.64.1-cp311-cp311-win_amd64.whl", hash = "sha256:5e56462b05a6f860b72f0fa50dca06d5b26543a4e88d0396259a07dc30f4e5aa"}, + {file = "grpcio-1.64.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:4657d24c8063e6095f850b68f2d1ba3b39f2b287a38242dcabc166453e950c59"}, + {file = "grpcio-1.64.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:62b4e6eb7bf901719fce0ca83e3ed474ae5022bb3827b0a501e056458c51c0a1"}, + {file = "grpcio-1.64.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:ee73a2f5ca4ba44fa33b4d7d2c71e2c8a9e9f78d53f6507ad68e7d2ad5f64a22"}, + {file = "grpcio-1.64.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:198908f9b22e2672a998870355e226a725aeab327ac4e6ff3a1399792ece4762"}, + {file = "grpcio-1.64.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39b9d0acaa8d835a6566c640f48b50054f422d03e77e49716d4c4e8e279665a1"}, + {file = "grpcio-1.64.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:5e42634a989c3aa6049f132266faf6b949ec2a6f7d302dbb5c15395b77d757eb"}, + {file = "grpcio-1.64.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b1a82e0b9b3022799c336e1fc0f6210adc019ae84efb7321d668129d28ee1efb"}, + {file = "grpcio-1.64.1-cp312-cp312-win32.whl", hash = "sha256:55260032b95c49bee69a423c2f5365baa9369d2f7d233e933564d8a47b893027"}, + {file = "grpcio-1.64.1-cp312-cp312-win_amd64.whl", hash = "sha256:c1a786ac592b47573a5bb7e35665c08064a5d77ab88a076eec11f8ae86b3e3f6"}, + {file = "grpcio-1.64.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:a011ac6c03cfe162ff2b727bcb530567826cec85eb8d4ad2bfb4bd023287a52d"}, + {file = "grpcio-1.64.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:4d6dab6124225496010bd22690f2d9bd35c7cbb267b3f14e7a3eb05c911325d4"}, + {file = "grpcio-1.64.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:a5e771d0252e871ce194d0fdcafd13971f1aae0ddacc5f25615030d5df55c3a2"}, + {file = "grpcio-1.64.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c3c1b90ab93fed424e454e93c0ed0b9d552bdf1b0929712b094f5ecfe7a23ad"}, + {file = "grpcio-1.64.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20405cb8b13fd779135df23fabadc53b86522d0f1cba8cca0e87968587f50650"}, + {file = "grpcio-1.64.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0cc79c982ccb2feec8aad0e8fb0d168bcbca85bc77b080d0d3c5f2f15c24ea8f"}, + {file = "grpcio-1.64.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a3a035c37ce7565b8f4f35ff683a4db34d24e53dc487e47438e434eb3f701b2a"}, + {file = "grpcio-1.64.1-cp38-cp38-win32.whl", hash = "sha256:1257b76748612aca0f89beec7fa0615727fd6f2a1ad580a9638816a4b2eb18fd"}, + {file = "grpcio-1.64.1-cp38-cp38-win_amd64.whl", hash = "sha256:0a12ddb1678ebc6a84ec6b0487feac020ee2b1659cbe69b80f06dbffdb249122"}, + {file = "grpcio-1.64.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:75dbbf415026d2862192fe1b28d71f209e2fd87079d98470db90bebe57b33179"}, + {file = "grpcio-1.64.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e3d9f8d1221baa0ced7ec7322a981e28deb23749c76eeeb3d33e18b72935ab62"}, + {file = "grpcio-1.64.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:5f8b75f64d5d324c565b263c67dbe4f0af595635bbdd93bb1a88189fc62ed2e5"}, + {file = "grpcio-1.64.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c84ad903d0d94311a2b7eea608da163dace97c5fe9412ea311e72c3684925602"}, + {file = "grpcio-1.64.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:940e3ec884520155f68a3b712d045e077d61c520a195d1a5932c531f11883489"}, + {file = "grpcio-1.64.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f10193c69fc9d3d726e83bbf0f3d316f1847c3071c8c93d8090cf5f326b14309"}, + {file = "grpcio-1.64.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ac15b6c2c80a4d1338b04d42a02d376a53395ddf0ec9ab157cbaf44191f3ffdd"}, + {file = "grpcio-1.64.1-cp39-cp39-win32.whl", hash = "sha256:03b43d0ccf99c557ec671c7dede64f023c7da9bb632ac65dbc57f166e4970040"}, + {file = "grpcio-1.64.1-cp39-cp39-win_amd64.whl", hash = "sha256:ed6091fa0adcc7e4ff944090cf203a52da35c37a130efa564ded02b7aff63bcd"}, + {file = "grpcio-1.64.1.tar.gz", hash = "sha256:8d51dd1c59d5fa0f34266b80a3805ec29a1f26425c2a54736133f6d87fc4968a"}, ] [package.extras] -protobuf = ["grpcio-tools (>=1.64.0)"] +protobuf = ["grpcio-tools (>=1.64.1)"] [[package]] name = "grpcio-status" @@ -1334,13 +1335,13 @@ socks = ["socksio (==1.*)"] [[package]] name = "huggingface-hub" -version = "0.23.2" +version = "0.23.3" description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" optional = true python-versions = ">=3.8.0" files = [ - {file = "huggingface_hub-0.23.2-py3-none-any.whl", hash = "sha256:48727a16e704d409c4bb5913613308499664f22a99743435dc3a13b23c485827"}, - {file = "huggingface_hub-0.23.2.tar.gz", hash = "sha256:f6829b62d5fdecb452a76fdbec620cba4c1573655a8d710c1df71735fd9edbd2"}, + {file = "huggingface_hub-0.23.3-py3-none-any.whl", hash = "sha256:22222c41223f1b7c209ae5511d2d82907325a0e3cdbce5f66949d43c598ff3bc"}, + {file = "huggingface_hub-0.23.3.tar.gz", hash = "sha256:1a1118a0b3dea3bab6c325d71be16f5ffe441d32f3ac7c348d6875911b694b5b"}, ] [package.dependencies] @@ -1409,13 +1410,13 @@ files = [ [[package]] name = "ipython" -version = "8.24.0" +version = "8.25.0" description = "IPython: Productive Interactive Computing" optional = true python-versions = ">=3.10" files = [ - {file = "ipython-8.24.0-py3-none-any.whl", hash = "sha256:d7bf2f6c4314984e3e02393213bab8703cf163ede39672ce5918c51fe253a2a3"}, - {file = "ipython-8.24.0.tar.gz", hash = "sha256:010db3f8a728a578bb641fdd06c063b9fb8e96a9464c63aec6310fbcb5e80501"}, + {file = "ipython-8.25.0-py3-none-any.whl", hash = "sha256:53eee7ad44df903a06655871cbab66d156a051fd86f3ec6750470ac9604ac1ab"}, + {file = "ipython-8.25.0.tar.gz", hash = "sha256:c6ed726a140b6e725b911528f80439c534fac915246af3efc39440a6b0f9d716"}, ] [package.dependencies] @@ -1434,7 +1435,7 @@ typing-extensions = {version = ">=4.6", markers = "python_version < \"3.12\""} [package.extras] all = ["ipython[black,doc,kernel,matplotlib,nbconvert,nbformat,notebook,parallel,qtconsole]", "ipython[test,test-extra]"] black = ["black"] -doc = ["docrepr", "exceptiongroup", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "stack-data", "typing-extensions"] +doc = ["docrepr", "exceptiongroup", "intersphinx-registry", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "tomli", "typing-extensions"] kernel = ["ipykernel"] matplotlib = ["matplotlib"] nbconvert = ["nbconvert"] @@ -1511,72 +1512,72 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "jiter" -version = "0.4.0" +version = "0.4.1" description = "Fast iterable JSON parser." optional = true python-versions = ">=3.8" files = [ - {file = "jiter-0.4.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:4aa6226d82a4a4505078c0bd5947bad65399635fc5cd4b226512e41753624edf"}, - {file = "jiter-0.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:947111ac906740a948e7b63799481acd3d5ef666ccb178d146e25718640b7408"}, - {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69572ffb4e84ae289a7422b9af4ea123cae2ce0772228859b37d4b26b4bc92ea"}, - {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ba6046cbb5d1baa5a781b846f7e5438596a332f249a857d63f86ef5d1d9563b0"}, - {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4f346e54602782e66d07df0d1c7389384fd93680052ed6170da2c6dc758409e"}, - {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:49110ce693f07e97d61089d894cea05a0b9894d5ccc6ac6fc583028726c8c8af"}, - {file = "jiter-0.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e358df6fd129f3a4e087539f086355ad0107e5da16dbc8bc857d94222eaeed5"}, - {file = "jiter-0.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7eb852ca39a48f3c049def56f0d1771b32e948e4f429a782d14ef4cc64cfd26e"}, - {file = "jiter-0.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:44dc045decb2545bffe2da04ea4c36d9438d3f3d49fc47ed423ea75c352b712e"}, - {file = "jiter-0.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:413adb15372ac63db04373240f40925788e4282c997eeafc2040530049a0a599"}, - {file = "jiter-0.4.0-cp310-none-win32.whl", hash = "sha256:0b48ea71673a97b897e4b94bbc871e62495a5a85f836c9f90712a4c70aa3ef7e"}, - {file = "jiter-0.4.0-cp310-none-win_amd64.whl", hash = "sha256:6a1c84b44afafaf0ba6223679cf17af664b889da14da31d8af3595fd977d96fa"}, - {file = "jiter-0.4.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b2cc498345fa37ca23fbc20271a553aa46e6eb00924600f49b7dc4b2aa8952ee"}, - {file = "jiter-0.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:69f7221ac09ab421abf04f89942026868297c568133998fb181bcf435760cbf3"}, - {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef7d01c52f3e5a56ae73af36bd13797dd1a56711eb522748e5e84d15425b3f10"}, - {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:39be97d5ce0c4d0dae28c23c03a0af0501a725589427e99763f99c42e18aa402"}, - {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eac2ed1ec1e577b92b7ea2d4e6de8aec0c1164defd8af8affdc8ec0f0ec2904a"}, - {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6258837d184c92c9cb91c983c310ad7269d41afb49d34f00ca9246e073943a03"}, - {file = "jiter-0.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:123c2a77b066bf17a4d021e238e8351058cfa56b90ac04f2522d120dc64ea055"}, - {file = "jiter-0.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2df939f792c7a40e55f36700417db551b9f6b84d348990fa0f2c608adeb1f11b"}, - {file = "jiter-0.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cb1b09b16d40cf9ba1d11ba11e5b96ad29286a6a1c4ad5e6a2aef5e352a89f5d"}, - {file = "jiter-0.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0efb4208889ebdbf933bf08dbcbc16e64ffd34c8e2b28044ee142789a9dc3a67"}, - {file = "jiter-0.4.0-cp311-none-win32.whl", hash = "sha256:20545ac1b68e7e5b066a1e8347840c9cebdd02ace65faae2e655fc02ec5c915c"}, - {file = "jiter-0.4.0-cp311-none-win_amd64.whl", hash = "sha256:6b300f9887c8e4431cd03a974ea3e4f9958885636003c3864220a9b2d2f8462b"}, - {file = "jiter-0.4.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:923432a0563bbae404ff25bb010e348514a69bfab979f2f8119b23b625dbf6d9"}, - {file = "jiter-0.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab8bb0ec8b97cec4422dc8b37b525442d969244488c805b834609ab0ccd788e2"}, - {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b857adb127b9c533907226791eafa79c5038c3eb5a477984994bf7c4715ba518"}, - {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2609cc0d1d8d470e921ff9a604afeb4c701bbe13e00bd9834d5aa6e7ea732a9b"}, - {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d39e99f8b7df46a119b6f84321f6ba01f16fa46abfa765d44c05c486d8e66829"}, - {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:56de8b518ebfe76a70f856741f6de248ce396c50a87acef827b6e8388e3a502d"}, - {file = "jiter-0.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:488b7e777be47f67ce1a1f8f8eb907f9bbd81af5c03784a9bab09d025c250233"}, - {file = "jiter-0.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7ea35e0ecbb5dadd457855eb980dcc548c14cf5341bcd22a43814cb56f2bcc79"}, - {file = "jiter-0.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e1a9e9ee69c80b63951c93226b68d0e955953f64fe758bad2afe7ef7f9016af9"}, - {file = "jiter-0.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:78e2f3cc2a32a21d43ccc5afcf66f5d17e827ccc4e6d21c0b353bdad2c7dcc9c"}, - {file = "jiter-0.4.0-cp312-none-win32.whl", hash = "sha256:eeaa7a2b47a99f4ebbb4142bb58b95617e09f24c87570f6a57d2770687c9ddbe"}, - {file = "jiter-0.4.0-cp312-none-win_amd64.whl", hash = "sha256:8d4a78b385b93ff59a67215d26000fcb4789a388fca3730d1b60fab17fc81e3c"}, - {file = "jiter-0.4.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:ebf20a3fac1089ce26963bf04140da0f803d55332ec69d59c5a87cf1a87d29c4"}, - {file = "jiter-0.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d62244ffc6a168187452277adeefb7b2c30170689c6bf543a51e98e8c17ddab7"}, - {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40b2cde77446a41cec595739fd168be87edff2428eaf7c3438231224dd0ab7a5"}, - {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e51fc0a22021ec8905b9b00a2f7d25756f2ff7a653e35a790a2067ae126b51f6"}, - {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a56e6f980b89d7cfe5c43811dcf52d6f37b319428a4540511235dafda9ea7808"}, - {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0fec16adab8d3d3d6d74e3711a1f380836ebeab2a20e3f88cfe2ec5094d8b84"}, - {file = "jiter-0.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19e3de515801c954e8f1dc1f575282a4a86df9e782d4993ea1ed2be9a8dedaa0"}, - {file = "jiter-0.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17e0ad8abf0bb04d81810eaeaab35d2c99b5da11fcd1058e0a389607ff6503b0"}, - {file = "jiter-0.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8dc0132b728f3b3e90ff0d1874504cd49c78f3553bf3745168a7fc0b4cf674e1"}, - {file = "jiter-0.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:81a883104aa96e494d3d28eaf7070780d03ecee8ccfdfaf7e4899710340c47f1"}, - {file = "jiter-0.4.0-cp38-none-win32.whl", hash = "sha256:a044c53ab1aaa4af624ac9574181b5bad8e260aea7e03104738156511433deba"}, - {file = "jiter-0.4.0-cp38-none-win_amd64.whl", hash = "sha256:d920035c869053e3d9a0b3ff94384d16a8ef5fde3dea55f97bd29916f6e27554"}, - {file = "jiter-0.4.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:091e978f4e586a2f1c69bf940d45f4e6a23455877172a0ab7d6de04a3b119299"}, - {file = "jiter-0.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:79134b2d601309bcbe3304a262d7d228ad61d53c80883231c637773000a6d683"}, - {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c471473e0b05058b5d729ff04271b6d45a575ac8bd9948563268c734b380ac7e"}, - {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb84b8930da8b32b0b1fdff9817e2c4b47e8981b5647ad11c4975403416e4112"}, - {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f2805e28941751ebfe0948596a64cde4cfb9b84bea5282affd020063e659c96"}, - {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:42ef59f9e513bf081a8b5c5578933ea9c3a63e559e6e3501a3e72edcd456ff5e"}, - {file = "jiter-0.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ae12e3906f9e565120ab569de261b738e3a1ec50c40e30c67499e4f893e9a8c"}, - {file = "jiter-0.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:264dc1324f45a793bc89af4f653225229eb17bca9ec7107dce6c8fb4fe68d20f"}, - {file = "jiter-0.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9a1c172ec47d846e25881dfbd52438ddb690da4ea04d185e477abd3db6c32f8a"}, - {file = "jiter-0.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ccde31d0bc114aedad0dbd71b7f63ba0f0eecd7ec9ae1926a0ca01c1eb2854e7"}, - {file = "jiter-0.4.0-cp39-none-win32.whl", hash = "sha256:13139b05792fbc13a0f9a5b4c89823ea0874141decae1b8f693f12bb1d28e061"}, - {file = "jiter-0.4.0-cp39-none-win_amd64.whl", hash = "sha256:3a729b2631c6d5551a41069697415fee9659c3eadc9ab87369376ba51930cd00"}, - {file = "jiter-0.4.0.tar.gz", hash = "sha256:68203e02e0419bc3eca717c580c2d8f615aeee1150e2a1fb68d6600a7e52a37c"}, + {file = "jiter-0.4.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3c2370cd8826b484f3fc6ed729cb58510ba24b4bc277c92323a57d35cf4df223"}, + {file = "jiter-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3587af23140a2eb282bba980010dae60f3b8b1579a034c5e869e9b94220a5972"}, + {file = "jiter-0.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df8788d34545d47de864032a78bae49a14b66b67196c73cd95f1c1e3081d9c73"}, + {file = "jiter-0.4.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91bf2d31e906a3ca26fc8ee0cb979e0e51b12aa7e83999c6afea047538f95e5c"}, + {file = "jiter-0.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8586e68702666b6acd919c65f718a09603adcfd8b4c7026bade2441d9e7bd34e"}, + {file = "jiter-0.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:639b766bde088546b5205fd31608502b5b42abee3294b43cc95c6ea8f9a257c3"}, + {file = "jiter-0.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5cb32457296351c98da289d21a092a6c53c75beb80e7127c8e16224ee342c7c7"}, + {file = "jiter-0.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:583263bd81bce5426806cf27ba85e4b97746797fae13c71e50a8689e06e57f81"}, + {file = "jiter-0.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c0e413999a819ccef9b5fd22ef4b9b8c48a98e49da4d09b43ebce286d0d80e26"}, + {file = "jiter-0.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5e50468d5acfef335ba8bc3892bb304354c38ba18acb3f7ae428451e47136e49"}, + {file = "jiter-0.4.1-cp310-none-win32.whl", hash = "sha256:b2ac90b94dd717644c61c8ed0c2ec6e9505bd7314b91a1549680d7f1cb8f1da4"}, + {file = "jiter-0.4.1-cp310-none-win_amd64.whl", hash = "sha256:2509868b8dacf4f65d04b4d951d390f30f403a87a997a14e2db2d232c7a468a7"}, + {file = "jiter-0.4.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b56e4f2fa5767976f2332e9e067010ddfe1379b6456b5458123ba50657c33e02"}, + {file = "jiter-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f813b49db21c946aa010accc54b8e5c9d0007be252bda4738159fa6c65d6d396"}, + {file = "jiter-0.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2933c04ebd77b3e9cf34f80ba45c093739c687c9c5a4fd0a8c701a3bfd90940"}, + {file = "jiter-0.4.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b02ddd65513705ec38211ea48ffc0fde41aa46166d9f7706972daf97b57c8599"}, + {file = "jiter-0.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:88d06af883524e5429d75395bb4ee6ddeda4c30818b2f3e3b8f4afa2dd8f28c0"}, + {file = "jiter-0.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd333eca1090cf21e6359721eecbb2a7fe031cc4db3dd595081430b4a59371c5"}, + {file = "jiter-0.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdc90017cd22dca6b40f2f8518b38363e78aee3cb32f84e1cb08900a598ca91b"}, + {file = "jiter-0.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aedce5b11ca58853d46461e1880079836bfab4e132be2b7d2093ec193081bbc8"}, + {file = "jiter-0.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e55b2f4d2d5066979b0e0e58d85e3fffd0f6e6a0523aab7e0ce75950259387da"}, + {file = "jiter-0.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b3c85c586f1cd71c2a1e78756f6857119947b532379bd9be4338bf3dacf1e87f"}, + {file = "jiter-0.4.1-cp311-none-win32.whl", hash = "sha256:37875f56222f2bb61410e15196d9b91510ccca322c391f3d20c91d667130d15e"}, + {file = "jiter-0.4.1-cp311-none-win_amd64.whl", hash = "sha256:b71758befea8dbdc10e0fb40a776e085eed0e74afef42468ebb58562289e9190"}, + {file = "jiter-0.4.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:93a8869c18a3721e41d7adb289c5c71aea8887eb368a3411219a0afb62955cbe"}, + {file = "jiter-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0ffbc61349f2f27676d40d68e8ef83fc2a9dd2c1464962b1d1b1d8504bccbf85"}, + {file = "jiter-0.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5f1f33e9fd4de4369a8d00fdf2571a8246a942095fb2a9d4cd25135ee675c85"}, + {file = "jiter-0.4.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d8f91a19eba23b4a1bb1e5b64c19cfdbf46604180e5dee40548b53ca13afd2d9"}, + {file = "jiter-0.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a60f8e495448d8e02d291fa9a8522cfe775a10210ba428994f383965e6f6e65"}, + {file = "jiter-0.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7387998c6585ce0f02ae4f5338fabf72b99494860c347f27bc34720290eafb15"}, + {file = "jiter-0.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7cbf41da6506b42db21a1a0befa48e16384591e84e80db002a826ccf07668f1"}, + {file = "jiter-0.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:793ae2499722b9fc31e300abd07418902512109bca17f617598a31a9e17bddce"}, + {file = "jiter-0.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:19f7953b8ada7ee109764ad91d4afb1a9f69b77cde0b890844744c513612dbf8"}, + {file = "jiter-0.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:dcd3d6a142d7b267a8c5f1e28d02759e2e29343b095f6d8aaf463333a842e1f8"}, + {file = "jiter-0.4.1-cp312-none-win32.whl", hash = "sha256:fffdf137c3ab7f0c5facb7c478b57ad3e1eb9b149daff48687844de77b78ab70"}, + {file = "jiter-0.4.1-cp312-none-win_amd64.whl", hash = "sha256:fde004e47a801512c4167f188a6372960374fbd59e635753b3ee536e81953eb3"}, + {file = "jiter-0.4.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b429ba25e05ca28d5e7efa4249032746ac28ec6ad68017ed3ea009989c597911"}, + {file = "jiter-0.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:27df9925d0282c80bdd41613ace7cd799bd6355acdfe25cc48ec16843541999e"}, + {file = "jiter-0.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb68736a0e2b00eda83937c1937f999e8d7dab68820c04343ac2e2eb2c5c2193"}, + {file = "jiter-0.4.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c218458ac32ce0b495f013293867649b40c067a4d7533fa0d70a46f7194febae"}, + {file = "jiter-0.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ebead86e80e352753f6e6f78ca96c12d764a8dbbc7c4b25938ce657ab0e4e879"}, + {file = "jiter-0.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf58f878d43294bea400a9df86ef7796dd2e67969109bce22d337ca77372c69"}, + {file = "jiter-0.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba671e60570cd99b8ed83ce0d82703040dc34c793229ac607f09683ba1981163"}, + {file = "jiter-0.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef0bd8b68ad14f045544989b6ad3758bee6dc01f6924bce5b4fd7060b0a09b1b"}, + {file = "jiter-0.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7888f165a0fe285e015ee18cfcb8b5432c4fa389235b4c24c339ca0cc51ba979"}, + {file = "jiter-0.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7d9c443b2a71a8c3ab6578f5faf7725ad5f63dbb92d87f820eec56de9da0560f"}, + {file = "jiter-0.4.1-cp38-none-win32.whl", hash = "sha256:6f618d1b04493bc9196e466ef59e0a6388eb85e936d1a61833449677643bbdd9"}, + {file = "jiter-0.4.1-cp38-none-win_amd64.whl", hash = "sha256:46b6364a0b2a81cc259768bda131e8528aa3af4312f23f7e10aa04d24f54bbb1"}, + {file = "jiter-0.4.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:6680785a9273a87e463c86a962042d620c00c7bb8100dde1a4c78b2184cdd613"}, + {file = "jiter-0.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:36b10d945b9ccd2e9f2720e37395daf9e63cfa47e5e0e2887c4931888f0800cd"}, + {file = "jiter-0.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78820599693bda34be17119abf9fad1f02e501b4816e47addbee9c5c768fb361"}, + {file = "jiter-0.4.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68697317170d8f851dfe978ba278b886e54e837ecd2a80c4a33ae780a0f19526"}, + {file = "jiter-0.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d126ffc3876cfc1fba6ae2be37f2532b5db593a96cf4b845724b50b44339c4fd"}, + {file = "jiter-0.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b082223f2e7e6f506d837df935f58f25cabf0a2b35902b4ec73fb561fbf2694a"}, + {file = "jiter-0.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13314287782782be8439dfafca50f13fcab18046227068a3a8e8d8ac888f092b"}, + {file = "jiter-0.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3da1346375605926f1ca4604d154ff41f5e3b933c6e01005e534bca2197d919f"}, + {file = "jiter-0.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9b67a97fbce3ec35ee97439c8b786393f71ecbe7458d5e9279d4c172772eac36"}, + {file = "jiter-0.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7b0f34544923bff0f3393aa3d60087686d86089c9361f6530bb5d19ebfb3db47"}, + {file = "jiter-0.4.1-cp39-none-win32.whl", hash = "sha256:b0c93ef95b896a4ce5edff23071e4dcad77c9e9262fcb6ca2b050f781e8335a9"}, + {file = "jiter-0.4.1-cp39-none-win_amd64.whl", hash = "sha256:3db5c83c8655ce031943b6f08434dac1a91e1477b0df452de0c44f3390a9b22c"}, + {file = "jiter-0.4.1.tar.gz", hash = "sha256:741851cf5f37cf3583f2a56829d734c9fd17334770c9a326e6d25291603d4278"}, ] [[package]] @@ -1652,13 +1653,13 @@ referencing = ">=0.31.0" [[package]] name = "langchain" -version = "0.2.1" +version = "0.2.2" description = "Building applications with LLMs through composability" optional = true python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain-0.2.1-py3-none-any.whl", hash = "sha256:3e13bf97c5717bce2c281f5117e8778823e8ccf62d949e73d3869448962b1c97"}, - {file = "langchain-0.2.1.tar.gz", hash = "sha256:5758a315e1ac92eb26dafec5ad0fafa03cafa686aba197d5bb0b1dd28cc03ebe"}, + {file = "langchain-0.2.2-py3-none-any.whl", hash = "sha256:58ca0c47bcdd156da66f50a0a4fcedc49bf6950827f4a6b06c8c4842d55805f3"}, + {file = "langchain-0.2.2.tar.gz", hash = "sha256:9d61e50e9cdc2bea659bc5e6c03650ba048fda63a307490ae368e539f61a0d3a"}, ] [package.dependencies] @@ -1690,13 +1691,13 @@ text-helpers = ["chardet (>=5.1.0,<6.0.0)"] [[package]] name = "langchain-community" -version = "0.2.1" +version = "0.2.2" description = "Community contributed LangChain integrations." optional = true python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_community-0.2.1-py3-none-any.whl", hash = "sha256:b834e2c5ded6903b839fcaf566eee90a0ffae53405a0f7748202725e701d39cd"}, - {file = "langchain_community-0.2.1.tar.gz", hash = "sha256:079942e8f15da975769ccaae19042b7bba5481c42020bbbd7d8cad73a9393261"}, + {file = "langchain_community-0.2.2-py3-none-any.whl", hash = "sha256:470ee16e05f1acacb91a656b6d3c2cbf6fb6a8dcb00a13901cd1353cd29c2bb3"}, + {file = "langchain_community-0.2.2.tar.gz", hash = "sha256:fb09faf4640726a929932056dc55ff120e490aaf2e424fae8ddbb15605195447"}, ] [package.dependencies] @@ -1713,22 +1714,22 @@ tenacity = ">=8.1.0,<9.0.0" [package.extras] cli = ["typer (>=0.9.0,<0.10.0)"] -extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "azure-identity (>=1.15.0,<2.0.0)", "azure-search-documents (==11.4.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.6,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cloudpathlib (>=0.18,<0.19)", "cloudpickle (>=2.0.0)", "cohere (>=4,<5)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "friendli-client (>=1.2.4,<2.0.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "httpx (>=0.24.1,<0.25.0)", "httpx-sse (>=0.4.0,<0.5.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "nvidia-riva-client (>=2.14.0,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "oracledb (>=2.2.0,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "premai (>=0.3.25,<0.4.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pyjwt (>=2.8.0,<3.0.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "tidb-vector (>=0.0.3,<1.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "tree-sitter (>=0.20.2,<0.21.0)", "tree-sitter-languages (>=1.8.0,<2.0.0)", "upstash-redis (>=0.15.0,<0.16.0)", "vdms (>=0.0.20,<0.0.21)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] +extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "azure-identity (>=1.15.0,<2.0.0)", "azure-search-documents (==11.4.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.6,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cloudpathlib (>=0.18,<0.19)", "cloudpickle (>=2.0.0)", "cohere (>=4,<5)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "friendli-client (>=1.2.4,<2.0.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "httpx (>=0.24.1,<0.25.0)", "httpx-sse (>=0.4.0,<0.5.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "nvidia-riva-client (>=2.14.0,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "oracledb (>=2.2.0,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "premai (>=0.3.25,<0.4.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pyjwt (>=2.8.0,<3.0.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "simsimd (>=4.3.1,<5.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "tidb-vector (>=0.0.3,<1.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "tree-sitter (>=0.20.2,<0.21.0)", "tree-sitter-languages (>=1.8.0,<2.0.0)", "upstash-redis (>=0.15.0,<0.16.0)", "vdms (>=0.0.20,<0.0.21)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] [[package]] name = "langchain-core" -version = "0.2.3" +version = "0.2.4" description = "Building applications with LLMs through composability" optional = true python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_core-0.2.3-py3-none-any.whl", hash = "sha256:22189b5a3a30bfd65eb995f95e627f7c2c3acb322feb89f5f5f2fb7df21833a7"}, - {file = "langchain_core-0.2.3.tar.gz", hash = "sha256:fbc75a64b9c0b7655d96ca57a707df1e6c09efc1539c36adbd73260612549810"}, + {file = "langchain_core-0.2.4-py3-none-any.whl", hash = "sha256:5212f7ec78a525e88a178ed3aefe2fd7134b03fb92573dfbab9914f1d92d6ec5"}, + {file = "langchain_core-0.2.4.tar.gz", hash = "sha256:82bdcc546eb0341cefcf1f4ecb3e49836fff003903afddda2d1312bb8491ef81"}, ] [package.dependencies] jsonpatch = ">=1.33,<2.0" -langsmith = ">=0.1.65,<0.2.0" +langsmith = ">=0.1.66,<0.2.0" packaging = ">=23.2,<24.0" pydantic = ">=1,<3" PyYAML = ">=5.3" @@ -1739,13 +1740,13 @@ extended-testing = ["jinja2 (>=3,<4)"] [[package]] name = "langchain-text-splitters" -version = "0.2.0" +version = "0.2.1" description = "LangChain text splitting utilities" optional = true python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_text_splitters-0.2.0-py3-none-any.whl", hash = "sha256:7b4c6a45f8471630a882b321e138329b6897102a5bc62f4c12be1c0b05bb9199"}, - {file = "langchain_text_splitters-0.2.0.tar.gz", hash = "sha256:b32ab4f7397f7d42c1fa3283fefc2547ba356bd63a68ee9092865e5ad83c82f9"}, + {file = "langchain_text_splitters-0.2.1-py3-none-any.whl", hash = "sha256:c2774a85f17189eaca50339629d2316d13130d4a8d9f1a1a96f3a03670c4a138"}, + {file = "langchain_text_splitters-0.2.1.tar.gz", hash = "sha256:06853d17d7241ecf5c97c7b6ef01f600f9b0fb953dd997838142a527a4f32ea4"}, ] [package.dependencies] @@ -1756,13 +1757,13 @@ extended-testing = ["beautifulsoup4 (>=4.12.3,<5.0.0)", "lxml (>=4.9.3,<6.0)"] [[package]] name = "langsmith" -version = "0.1.65" +version = "0.1.72" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = true python-versions = "<4.0,>=3.8.1" files = [ - {file = "langsmith-0.1.65-py3-none-any.whl", hash = "sha256:ab4487029240e69cca30da1065f1e9138e5a7ca2bbe8c697f0bd7d5839f71cf7"}, - {file = "langsmith-0.1.65.tar.gz", hash = "sha256:d3c2eb2391478bd79989f02652cf66e29a7959d677614b6993a47cef43f7f43b"}, + {file = "langsmith-0.1.72-py3-none-any.whl", hash = "sha256:a4456707669521bd75b7431b9205a6b99579fb9ff01bd338f52d29df11a7662d"}, + {file = "langsmith-0.1.72.tar.gz", hash = "sha256:262ae9e8aceaba50f3a0f5b6eb559d6110886f0afc6b0ed5270e7d3d3f1fd8d6"}, ] [package.dependencies] @@ -2175,7 +2176,7 @@ twitter = ["twython"] name = "numpy" version = "1.26.4" description = "Fundamental package for array computing in Python" -optional = true +optional = false python-versions = ">=3.9" files = [ {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, @@ -2218,13 +2219,13 @@ files = [ [[package]] name = "openai" -version = "1.30.5" +version = "1.31.0" description = "The official Python library for the openai API" optional = true python-versions = ">=3.7.1" files = [ - {file = "openai-1.30.5-py3-none-any.whl", hash = "sha256:2ad95e926de0d2e09cde632a9204b0a6dca4a03c2cdcc84329b01f355784355a"}, - {file = "openai-1.30.5.tar.gz", hash = "sha256:5366562eb2c5917e6116ae0391b7ae6e3acd62b0ae3f565ada32b35d8fcfa106"}, + {file = "openai-1.31.0-py3-none-any.whl", hash = "sha256:82044ee3122113f2a468a1f308a8882324d09556ba5348687c535d3655ee331c"}, + {file = "openai-1.31.0.tar.gz", hash = "sha256:54ae0625b005d6a3b895db2b8438dae1059cffff0cd262a26e9015c13a29ab06"}, ] [package.dependencies] @@ -2392,13 +2393,13 @@ ptyprocess = ">=0.5" [[package]] name = "phonenumbers" -version = "8.13.37" +version = "8.13.38" description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers." optional = false python-versions = "*" files = [ - {file = "phonenumbers-8.13.37-py2.py3-none-any.whl", hash = "sha256:4ea00ef5012422c08c7955c21131e7ae5baa9a3ef52cf2d561e963f023006b80"}, - {file = "phonenumbers-8.13.37.tar.gz", hash = "sha256:bd315fed159aea0516f7c367231810fe8344d5bec26156b88fa18374c11d1cf2"}, + {file = "phonenumbers-8.13.38-py2.py3-none-any.whl", hash = "sha256:d22aa747fb591ef2a18afec13cab5a0e294ab20fce5a1560e4949e459e70eeef"}, + {file = "phonenumbers-8.13.38.tar.gz", hash = "sha256:2822c74ee9334e9d8ad792fc352cc8d21004307349b6b1bb61da12937fa2eaba"}, ] [[package]] @@ -2434,13 +2435,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "prompt-toolkit" -version = "3.0.45" +version = "3.0.46" description = "Library for building powerful interactive command lines in Python" optional = true python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.45-py3-none-any.whl", hash = "sha256:a29b89160e494e3ea8622b09fa5897610b437884dcdcd054fdc1308883326c2a"}, - {file = "prompt_toolkit-3.0.45.tar.gz", hash = "sha256:07c60ee4ab7b7e90824b61afa840c8f5aad2d46b3e2e10acc33d8ecc94a49089"}, + {file = "prompt_toolkit-3.0.46-py3-none-any.whl", hash = "sha256:45abe60a8300f3c618b23c16c4bb98c6fc80af8ce8b17c7ae92db48db3ee63c1"}, + {file = "prompt_toolkit-3.0.46.tar.gz", hash = "sha256:869c50d682152336e23c4db7f74667639b5047494202ffe7670817053fd57795"}, ] [package.dependencies] @@ -2557,18 +2558,18 @@ files = [ [[package]] name = "pydantic" -version = "2.7.2" +version = "2.7.3" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.7.2-py3-none-any.whl", hash = "sha256:834ab954175f94e6e68258537dc49402c4a5e9d0409b9f1b86b7e934a8372de7"}, - {file = "pydantic-2.7.2.tar.gz", hash = "sha256:71b2945998f9c9b7919a45bde9a50397b289937d215ae141c1d0903ba7149fd7"}, + {file = "pydantic-2.7.3-py3-none-any.whl", hash = "sha256:ea91b002777bf643bb20dd717c028ec43216b24a6001a280f83877fd2655d0b4"}, + {file = "pydantic-2.7.3.tar.gz", hash = "sha256:c46c76a40bb1296728d7a8b99aa73dd70a48c3510111ff290034f860c99c419e"}, ] [package.dependencies] annotated-types = ">=0.4.0" -pydantic-core = "2.18.3" +pydantic-core = "2.18.4" typing-extensions = ">=4.6.1" [package.extras] @@ -2576,95 +2577,114 @@ email = ["email-validator (>=2.0.0)"] [[package]] name = "pydantic-core" -version = "2.18.3" +version = "2.18.4" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.18.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:744697428fcdec6be5670460b578161d1ffe34743a5c15656be7ea82b008197c"}, - {file = "pydantic_core-2.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b40c05ced1ba4218b14986fe6f283d22e1ae2ff4c8e28881a70fb81fbfcda7"}, - {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a9a75622357076efb6b311983ff190fbfb3c12fc3a853122b34d3d358126c"}, - {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e2e253af04ceaebde8eb201eb3f3e3e7e390f2d275a88300d6a1959d710539e2"}, - {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:855ec66589c68aa367d989da5c4755bb74ee92ccad4fdb6af942c3612c067e34"}, - {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d3e42bb54e7e9d72c13ce112e02eb1b3b55681ee948d748842171201a03a98a"}, - {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6ac9ffccc9d2e69d9fba841441d4259cb668ac180e51b30d3632cd7abca2b9b"}, - {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c56eca1686539fa0c9bda992e7bd6a37583f20083c37590413381acfc5f192d6"}, - {file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:17954d784bf8abfc0ec2a633108207ebc4fa2df1a0e4c0c3ccbaa9bb01d2c426"}, - {file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:98ed737567d8f2ecd54f7c8d4f8572ca7c7921ede93a2e52939416170d357812"}, - {file = "pydantic_core-2.18.3-cp310-none-win32.whl", hash = "sha256:9f9e04afebd3ed8c15d67a564ed0a34b54e52136c6d40d14c5547b238390e779"}, - {file = "pydantic_core-2.18.3-cp310-none-win_amd64.whl", hash = "sha256:45e4ffbae34f7ae30d0047697e724e534a7ec0a82ef9994b7913a412c21462a0"}, - {file = "pydantic_core-2.18.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b9ebe8231726c49518b16b237b9fe0d7d361dd221302af511a83d4ada01183ab"}, - {file = "pydantic_core-2.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b8e20e15d18bf7dbb453be78a2d858f946f5cdf06c5072453dace00ab652e2b2"}, - {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0d9ff283cd3459fa0bf9b0256a2b6f01ac1ff9ffb034e24457b9035f75587cb"}, - {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f7ef5f0ebb77ba24c9970da18b771711edc5feaf00c10b18461e0f5f5949231"}, - {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73038d66614d2e5cde30435b5afdced2b473b4c77d4ca3a8624dd3e41a9c19be"}, - {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6afd5c867a74c4d314c557b5ea9520183fadfbd1df4c2d6e09fd0d990ce412cd"}, - {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd7df92f28d351bb9f12470f4c533cf03d1b52ec5a6e5c58c65b183055a60106"}, - {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:80aea0ffeb1049336043d07799eace1c9602519fb3192916ff525b0287b2b1e4"}, - {file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaee40f25bba38132e655ffa3d1998a6d576ba7cf81deff8bfa189fb43fd2bbe"}, - {file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9128089da8f4fe73f7a91973895ebf2502539d627891a14034e45fb9e707e26d"}, - {file = "pydantic_core-2.18.3-cp311-none-win32.whl", hash = "sha256:fec02527e1e03257aa25b1a4dcbe697b40a22f1229f5d026503e8b7ff6d2eda7"}, - {file = "pydantic_core-2.18.3-cp311-none-win_amd64.whl", hash = "sha256:58ff8631dbab6c7c982e6425da8347108449321f61fe427c52ddfadd66642af7"}, - {file = "pydantic_core-2.18.3-cp311-none-win_arm64.whl", hash = "sha256:3fc1c7f67f34c6c2ef9c213e0f2a351797cda98249d9ca56a70ce4ebcaba45f4"}, - {file = "pydantic_core-2.18.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f0928cde2ae416a2d1ebe6dee324709c6f73e93494d8c7aea92df99aab1fc40f"}, - {file = "pydantic_core-2.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0bee9bb305a562f8b9271855afb6ce00223f545de3d68560b3c1649c7c5295e9"}, - {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e862823be114387257dacbfa7d78547165a85d7add33b446ca4f4fae92c7ff5c"}, - {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a36f78674cbddc165abab0df961b5f96b14461d05feec5e1f78da58808b97e7"}, - {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba905d184f62e7ddbb7a5a751d8a5c805463511c7b08d1aca4a3e8c11f2e5048"}, - {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fdd362f6a586e681ff86550b2379e532fee63c52def1c666887956748eaa326"}, - {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24b214b7ee3bd3b865e963dbed0f8bc5375f49449d70e8d407b567af3222aae4"}, - {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:691018785779766127f531674fa82bb368df5b36b461622b12e176c18e119022"}, - {file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:60e4c625e6f7155d7d0dcac151edf5858102bc61bf959d04469ca6ee4e8381bd"}, - {file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4e651e47d981c1b701dcc74ab8fec5a60a5b004650416b4abbef13db23bc7be"}, - {file = "pydantic_core-2.18.3-cp312-none-win32.whl", hash = "sha256:ffecbb5edb7f5ffae13599aec33b735e9e4c7676ca1633c60f2c606beb17efc5"}, - {file = "pydantic_core-2.18.3-cp312-none-win_amd64.whl", hash = "sha256:2c8333f6e934733483c7eddffdb094c143b9463d2af7e6bd85ebcb2d4a1b82c6"}, - {file = "pydantic_core-2.18.3-cp312-none-win_arm64.whl", hash = "sha256:7a20dded653e516a4655f4c98e97ccafb13753987434fe7cf044aa25f5b7d417"}, - {file = "pydantic_core-2.18.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:eecf63195be644b0396f972c82598cd15693550f0ff236dcf7ab92e2eb6d3522"}, - {file = "pydantic_core-2.18.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c44efdd3b6125419c28821590d7ec891c9cb0dff33a7a78d9d5c8b6f66b9702"}, - {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e59fca51ffbdd1638b3856779342ed69bcecb8484c1d4b8bdb237d0eb5a45e2"}, - {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70cf099197d6b98953468461d753563b28e73cf1eade2ffe069675d2657ed1d5"}, - {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63081a49dddc6124754b32a3774331467bfc3d2bd5ff8f10df36a95602560361"}, - {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:370059b7883485c9edb9655355ff46d912f4b03b009d929220d9294c7fd9fd60"}, - {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a64faeedfd8254f05f5cf6fc755023a7e1606af3959cfc1a9285744cc711044"}, - {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19d2e725de0f90d8671f89e420d36c3dd97639b98145e42fcc0e1f6d492a46dc"}, - {file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:67bc078025d70ec5aefe6200ef094576c9d86bd36982df1301c758a9fff7d7f4"}, - {file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:adf952c3f4100e203cbaf8e0c907c835d3e28f9041474e52b651761dc248a3c0"}, - {file = "pydantic_core-2.18.3-cp38-none-win32.whl", hash = "sha256:9a46795b1f3beb167eaee91736d5d17ac3a994bf2215a996aed825a45f897558"}, - {file = "pydantic_core-2.18.3-cp38-none-win_amd64.whl", hash = "sha256:200ad4e3133cb99ed82342a101a5abf3d924722e71cd581cc113fe828f727fbc"}, - {file = "pydantic_core-2.18.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:304378b7bf92206036c8ddd83a2ba7b7d1a5b425acafff637172a3aa72ad7083"}, - {file = "pydantic_core-2.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c826870b277143e701c9ccf34ebc33ddb4d072612683a044e7cce2d52f6c3fef"}, - {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e201935d282707394f3668380e41ccf25b5794d1b131cdd96b07f615a33ca4b1"}, - {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5560dda746c44b48bf82b3d191d74fe8efc5686a9ef18e69bdabccbbb9ad9442"}, - {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b32c2a1f8032570842257e4c19288eba9a2bba4712af542327de9a1204faff8"}, - {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:929c24e9dea3990bc8bcd27c5f2d3916c0c86f5511d2caa69e0d5290115344a9"}, - {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a8376fef60790152564b0eab376b3e23dd6e54f29d84aad46f7b264ecca943"}, - {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dccf3ef1400390ddd1fb55bf0632209d39140552d068ee5ac45553b556780e06"}, - {file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:41dbdcb0c7252b58fa931fec47937edb422c9cb22528f41cb8963665c372caf6"}, - {file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:666e45cf071669fde468886654742fa10b0e74cd0fa0430a46ba6056b24fb0af"}, - {file = "pydantic_core-2.18.3-cp39-none-win32.whl", hash = "sha256:f9c08cabff68704a1b4667d33f534d544b8a07b8e5d039c37067fceb18789e78"}, - {file = "pydantic_core-2.18.3-cp39-none-win_amd64.whl", hash = "sha256:4afa5f5973e8572b5c0dcb4e2d4fda7890e7cd63329bd5cc3263a25c92ef0026"}, - {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:77319771a026f7c7d29c6ebc623de889e9563b7087911b46fd06c044a12aa5e9"}, - {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:df11fa992e9f576473038510d66dd305bcd51d7dd508c163a8c8fe148454e059"}, - {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d531076bdfb65af593326ffd567e6ab3da145020dafb9187a1d131064a55f97c"}, - {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d33ce258e4e6e6038f2b9e8b8a631d17d017567db43483314993b3ca345dcbbb"}, - {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1f9cd7f5635b719939019be9bda47ecb56e165e51dd26c9a217a433e3d0d59a9"}, - {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cd4a032bb65cc132cae1fe3e52877daecc2097965cd3914e44fbd12b00dae7c5"}, - {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f2718430098bcdf60402136c845e4126a189959d103900ebabb6774a5d9fdb"}, - {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c0037a92cf0c580ed14e10953cdd26528e8796307bb8bb312dc65f71547df04d"}, - {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b95a0972fac2b1ff3c94629fc9081b16371dad870959f1408cc33b2f78ad347a"}, - {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a62e437d687cc148381bdd5f51e3e81f5b20a735c55f690c5be94e05da2b0d5c"}, - {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b367a73a414bbb08507da102dc2cde0fa7afe57d09b3240ce82a16d608a7679c"}, - {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ecce4b2360aa3f008da3327d652e74a0e743908eac306198b47e1c58b03dd2b"}, - {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd4435b8d83f0c9561a2a9585b1de78f1abb17cb0cef5f39bf6a4b47d19bafe3"}, - {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:616221a6d473c5b9aa83fa8982745441f6a4a62a66436be9445c65f241b86c94"}, - {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7e6382ce89a92bc1d0c0c5edd51e931432202b9080dc921d8d003e616402efd1"}, - {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ff58f379345603d940e461eae474b6bbb6dab66ed9a851ecd3cb3709bf4dcf6a"}, - {file = "pydantic_core-2.18.3.tar.gz", hash = "sha256:432e999088d85c8f36b9a3f769a8e2b57aabd817bbb729a90d1fe7f18f6f1f39"}, + {file = "pydantic_core-2.18.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f76d0ad001edd426b92233d45c746fd08f467d56100fd8f30e9ace4b005266e4"}, + {file = "pydantic_core-2.18.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:59ff3e89f4eaf14050c8022011862df275b552caef8082e37b542b066ce1ff26"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a55b5b16c839df1070bc113c1f7f94a0af4433fcfa1b41799ce7606e5c79ce0a"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4d0dcc59664fcb8974b356fe0a18a672d6d7cf9f54746c05f43275fc48636851"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8951eee36c57cd128f779e641e21eb40bc5073eb28b2d23f33eb0ef14ffb3f5d"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4701b19f7e3a06ea655513f7938de6f108123bf7c86bbebb1196eb9bd35cf724"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e00a3f196329e08e43d99b79b286d60ce46bed10f2280d25a1718399457e06be"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:97736815b9cc893b2b7f663628e63f436018b75f44854c8027040e05230eeddb"}, + {file = "pydantic_core-2.18.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6891a2ae0e8692679c07728819b6e2b822fb30ca7445f67bbf6509b25a96332c"}, + {file = "pydantic_core-2.18.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bc4ff9805858bd54d1a20efff925ccd89c9d2e7cf4986144b30802bf78091c3e"}, + {file = "pydantic_core-2.18.4-cp310-none-win32.whl", hash = "sha256:1b4de2e51bbcb61fdebd0ab86ef28062704f62c82bbf4addc4e37fa4b00b7cbc"}, + {file = "pydantic_core-2.18.4-cp310-none-win_amd64.whl", hash = "sha256:6a750aec7bf431517a9fd78cb93c97b9b0c496090fee84a47a0d23668976b4b0"}, + {file = "pydantic_core-2.18.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:942ba11e7dfb66dc70f9ae66b33452f51ac7bb90676da39a7345e99ffb55402d"}, + {file = "pydantic_core-2.18.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b2ebef0e0b4454320274f5e83a41844c63438fdc874ea40a8b5b4ecb7693f1c4"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a642295cd0c8df1b86fc3dced1d067874c353a188dc8e0f744626d49e9aa51c4"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f09baa656c904807e832cf9cce799c6460c450c4ad80803517032da0cd062e2"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98906207f29bc2c459ff64fa007afd10a8c8ac080f7e4d5beff4c97086a3dabd"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19894b95aacfa98e7cb093cd7881a0c76f55731efad31073db4521e2b6ff5b7d"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fbbdc827fe5e42e4d196c746b890b3d72876bdbf160b0eafe9f0334525119c8"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f85d05aa0918283cf29a30b547b4df2fbb56b45b135f9e35b6807cb28bc47951"}, + {file = "pydantic_core-2.18.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e85637bc8fe81ddb73fda9e56bab24560bdddfa98aa64f87aaa4e4b6730c23d2"}, + {file = "pydantic_core-2.18.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2f5966897e5461f818e136b8451d0551a2e77259eb0f73a837027b47dc95dab9"}, + {file = "pydantic_core-2.18.4-cp311-none-win32.whl", hash = "sha256:44c7486a4228413c317952e9d89598bcdfb06399735e49e0f8df643e1ccd0558"}, + {file = "pydantic_core-2.18.4-cp311-none-win_amd64.whl", hash = "sha256:8a7164fe2005d03c64fd3b85649891cd4953a8de53107940bf272500ba8a788b"}, + {file = "pydantic_core-2.18.4-cp311-none-win_arm64.whl", hash = "sha256:4e99bc050fe65c450344421017f98298a97cefc18c53bb2f7b3531eb39bc7805"}, + {file = "pydantic_core-2.18.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6f5c4d41b2771c730ea1c34e458e781b18cc668d194958e0112455fff4e402b2"}, + {file = "pydantic_core-2.18.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2fdf2156aa3d017fddf8aea5adfba9f777db1d6022d392b682d2a8329e087cef"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4748321b5078216070b151d5271ef3e7cc905ab170bbfd27d5c83ee3ec436695"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847a35c4d58721c5dc3dba599878ebbdfd96784f3fb8bb2c356e123bdcd73f34"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c40d4eaad41f78e3bbda31b89edc46a3f3dc6e171bf0ecf097ff7a0ffff7cb1"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:21a5e440dbe315ab9825fcd459b8814bb92b27c974cbc23c3e8baa2b76890077"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01dd777215e2aa86dfd664daed5957704b769e726626393438f9c87690ce78c3"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4b06beb3b3f1479d32befd1f3079cc47b34fa2da62457cdf6c963393340b56e9"}, + {file = "pydantic_core-2.18.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:564d7922e4b13a16b98772441879fcdcbe82ff50daa622d681dd682175ea918c"}, + {file = "pydantic_core-2.18.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0eb2a4f660fcd8e2b1c90ad566db2b98d7f3f4717c64fe0a83e0adb39766d5b8"}, + {file = "pydantic_core-2.18.4-cp312-none-win32.whl", hash = "sha256:8b8bab4c97248095ae0c4455b5a1cd1cdd96e4e4769306ab19dda135ea4cdb07"}, + {file = "pydantic_core-2.18.4-cp312-none-win_amd64.whl", hash = "sha256:14601cdb733d741b8958224030e2bfe21a4a881fb3dd6fbb21f071cabd48fa0a"}, + {file = "pydantic_core-2.18.4-cp312-none-win_arm64.whl", hash = "sha256:c1322d7dd74713dcc157a2b7898a564ab091ca6c58302d5c7b4c07296e3fd00f"}, + {file = "pydantic_core-2.18.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:823be1deb01793da05ecb0484d6c9e20baebb39bd42b5d72636ae9cf8350dbd2"}, + {file = "pydantic_core-2.18.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ebef0dd9bf9b812bf75bda96743f2a6c5734a02092ae7f721c048d156d5fabae"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae1d6df168efb88d7d522664693607b80b4080be6750c913eefb77e34c12c71a"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f9899c94762343f2cc2fc64c13e7cae4c3cc65cdfc87dd810a31654c9b7358cc"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99457f184ad90235cfe8461c4d70ab7dd2680e28821c29eca00252ba90308c78"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18f469a3d2a2fdafe99296a87e8a4c37748b5080a26b806a707f25a902c040a8"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7cdf28938ac6b8b49ae5e92f2735056a7ba99c9b110a474473fd71185c1af5d"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:938cb21650855054dc54dfd9120a851c974f95450f00683399006aa6e8abb057"}, + {file = "pydantic_core-2.18.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:44cd83ab6a51da80fb5adbd9560e26018e2ac7826f9626bc06ca3dc074cd198b"}, + {file = "pydantic_core-2.18.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:972658f4a72d02b8abfa2581d92d59f59897d2e9f7e708fdabe922f9087773af"}, + {file = "pydantic_core-2.18.4-cp38-none-win32.whl", hash = "sha256:1d886dc848e60cb7666f771e406acae54ab279b9f1e4143babc9c2258213daa2"}, + {file = "pydantic_core-2.18.4-cp38-none-win_amd64.whl", hash = "sha256:bb4462bd43c2460774914b8525f79b00f8f407c945d50881568f294c1d9b4443"}, + {file = "pydantic_core-2.18.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:44a688331d4a4e2129140a8118479443bd6f1905231138971372fcde37e43528"}, + {file = "pydantic_core-2.18.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a2fdd81edd64342c85ac7cf2753ccae0b79bf2dfa063785503cb85a7d3593223"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86110d7e1907ab36691f80b33eb2da87d780f4739ae773e5fc83fb272f88825f"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:46387e38bd641b3ee5ce247563b60c5ca098da9c56c75c157a05eaa0933ed154"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:123c3cec203e3f5ac7b000bd82235f1a3eced8665b63d18be751f115588fea30"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc1803ac5c32ec324c5261c7209e8f8ce88e83254c4e1aebdc8b0a39f9ddb443"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53db086f9f6ab2b4061958d9c276d1dbe3690e8dd727d6abf2321d6cce37fa94"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:abc267fa9837245cc28ea6929f19fa335f3dc330a35d2e45509b6566dc18be23"}, + {file = "pydantic_core-2.18.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a0d829524aaefdebccb869eed855e2d04c21d2d7479b6cada7ace5448416597b"}, + {file = "pydantic_core-2.18.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:509daade3b8649f80d4e5ff21aa5673e4ebe58590b25fe42fac5f0f52c6f034a"}, + {file = "pydantic_core-2.18.4-cp39-none-win32.whl", hash = "sha256:ca26a1e73c48cfc54c4a76ff78df3727b9d9f4ccc8dbee4ae3f73306a591676d"}, + {file = "pydantic_core-2.18.4-cp39-none-win_amd64.whl", hash = "sha256:c67598100338d5d985db1b3d21f3619ef392e185e71b8d52bceacc4a7771ea7e"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:574d92eac874f7f4db0ca653514d823a0d22e2354359d0759e3f6a406db5d55d"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1f4d26ceb5eb9eed4af91bebeae4b06c3fb28966ca3a8fb765208cf6b51102ab"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77450e6d20016ec41f43ca4a6c63e9fdde03f0ae3fe90e7c27bdbeaece8b1ed4"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d323a01da91851a4f17bf592faf46149c9169d68430b3146dcba2bb5e5719abc"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43d447dd2ae072a0065389092a231283f62d960030ecd27565672bd40746c507"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:578e24f761f3b425834f297b9935e1ce2e30f51400964ce4801002435a1b41ef"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:81b5efb2f126454586d0f40c4d834010979cb80785173d1586df845a632e4e6d"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ab86ce7c8f9bea87b9d12c7f0af71102acbf5ecbc66c17796cff45dae54ef9a5"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:90afc12421df2b1b4dcc975f814e21bc1754640d502a2fbcc6d41e77af5ec312"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:51991a89639a912c17bef4b45c87bd83593aee0437d8102556af4885811d59f5"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:293afe532740370aba8c060882f7d26cfd00c94cae32fd2e212a3a6e3b7bc15e"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b48ece5bde2e768197a2d0f6e925f9d7e3e826f0ad2271120f8144a9db18d5c8"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:eae237477a873ab46e8dd748e515c72c0c804fb380fbe6c85533c7de51f23a8f"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:834b5230b5dfc0c1ec37b2fda433b271cbbc0e507560b5d1588e2cc1148cf1ce"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e858ac0a25074ba4bce653f9b5d0a85b7456eaddadc0ce82d3878c22489fa4ee"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2fd41f6eff4c20778d717af1cc50eca52f5afe7805ee530a4fbd0bae284f16e9"}, + {file = "pydantic_core-2.18.4.tar.gz", hash = "sha256:ec3beeada09ff865c344ff3bc2f427f5e6c26401cc6113d77e372c3fdac73864"}, ] [package.dependencies] typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" +[[package]] +name = "pydantic-settings" +version = "2.3.0" +description = "Settings management using Pydantic" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_settings-2.3.0-py3-none-any.whl", hash = "sha256:26eeed27370a9c5e3f64e4a7d6602573cbedf05ed940f1d5b11c3f178427af7a"}, + {file = "pydantic_settings-2.3.0.tar.gz", hash = "sha256:78db28855a71503cfe47f39500a1dece523c640afd5280edb5c5c9c9cfa534c9"}, +] + +[package.dependencies] +pydantic = ">=2.7.0" +python-dotenv = ">=0.21.0" + +[package.extras] +toml = ["tomli (>=2.0.1)"] +yaml = ["pyyaml (>=6.0.1)"] + [[package]] name = "pydub" version = "0.25.1" @@ -2743,13 +2763,13 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] [[package]] name = "pytest" -version = "8.2.1" +version = "8.2.2" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.2.1-py3-none-any.whl", hash = "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1"}, - {file = "pytest-8.2.1.tar.gz", hash = "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd"}, + {file = "pytest-8.2.2-py3-none-any.whl", hash = "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343"}, + {file = "pytest-8.2.2.tar.gz", hash = "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"}, ] [package.dependencies] @@ -3235,13 +3255,13 @@ pyasn1 = ">=0.1.3" [[package]] name = "sentry-sdk" -version = "2.3.1" +version = "2.4.0" description = "Python client for Sentry (https://sentry.io)" optional = true python-versions = ">=3.6" files = [ - {file = "sentry_sdk-2.3.1-py2.py3-none-any.whl", hash = "sha256:c5aeb095ba226391d337dd42a6f9470d86c9fc236ecc71cfc7cd1942b45010c6"}, - {file = "sentry_sdk-2.3.1.tar.gz", hash = "sha256:139a71a19f5e9eb5d3623942491ce03cf8ebc14ea2e39ba3e6fe79560d8a5b1f"}, + {file = "sentry_sdk-2.4.0-py2.py3-none-any.whl", hash = "sha256:a42b70981cd4ed7da3c85d0360502d2ac932a15a4a420b360e1ebded2fc19a92"}, + {file = "sentry_sdk-2.4.0.tar.gz", hash = "sha256:62b9bb0489e731ecbce008f9647899b51d220067a75c3adfd46f8187660c0029"}, ] [package.dependencies] @@ -3792,13 +3812,13 @@ files = [ [[package]] name = "types-requests" -version = "2.32.0.20240523" +version = "2.32.0.20240602" description = "Typing stubs for requests" optional = false python-versions = ">=3.8" files = [ - {file = "types-requests-2.32.0.20240523.tar.gz", hash = "sha256:26b8a6de32d9f561192b9942b41c0ab2d8010df5677ca8aa146289d11d505f57"}, - {file = "types_requests-2.32.0.20240523-py3-none-any.whl", hash = "sha256:f19ed0e2daa74302069bbbbf9e82902854ffa780bc790742a810a9aaa52f65ec"}, + {file = "types-requests-2.32.0.20240602.tar.gz", hash = "sha256:3f98d7bbd0dd94ebd10ff43a7fbe20c3b8528acace6d8efafef0b6a184793f06"}, + {file = "types_requests-2.32.0.20240602-py3-none-any.whl", hash = "sha256:ed3946063ea9fbc6b5fc0c44fa279188bae42d582cb63760be6cb4b9d06c3de8"}, ] [package.dependencies] @@ -3817,13 +3837,13 @@ files = [ [[package]] name = "typing-extensions" -version = "4.12.0" +version = "4.12.1" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"}, - {file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"}, + {file = "typing_extensions-4.12.1-py3-none-any.whl", hash = "sha256:6024b58b69089e5a89c347397254e35f1bf02a907728ec7fee9bf0fe837d203a"}, + {file = "typing_extensions-4.12.1.tar.gz", hash = "sha256:915f5e35ff76f56588223f15fdd5938f9a1cf9195c0de25130c627e4d597f6d1"}, ] [[package]] @@ -3947,13 +3967,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "uvicorn" -version = "0.30.0" +version = "0.30.1" description = "The lightning-fast ASGI server." optional = false python-versions = ">=3.8" files = [ - {file = "uvicorn-0.30.0-py3-none-any.whl", hash = "sha256:78fa0b5f56abb8562024a59041caeb555c86e48d0efdd23c3fe7de7a4075bdab"}, - {file = "uvicorn-0.30.0.tar.gz", hash = "sha256:f678dec4fa3a39706bbf49b9ec5fc40049d42418716cea52b53f07828a60aa37"}, + {file = "uvicorn-0.30.1-py3-none-any.whl", hash = "sha256:cd17daa7f3b9d7a24de3617820e634d0933b69eed8e33a516071174427238c81"}, + {file = "uvicorn-0.30.1.tar.gz", hash = "sha256:d46cd8e0fd80240baffbcd9ec1012a712938754afcf81bce56c024c1656aece8"}, ] [package.dependencies] @@ -4017,13 +4037,13 @@ test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)" [[package]] name = "vonage" -version = "3.14.0" +version = "3.15.0" description = "Vonage Server SDK for Python" optional = true python-versions = ">=3.8" files = [ - {file = "vonage-3.14.0-py2.py3-none-any.whl", hash = "sha256:f8d28b8fcd157c0610d84b880779aadd3ab3768abfb18ef863e08669de163ccf"}, - {file = "vonage-3.14.0.tar.gz", hash = "sha256:ea001e9616abb19670c4250a1ac46288207030ebc9d9ecbcf5fcffef61fa5850"}, + {file = "vonage-3.15.0-py2.py3-none-any.whl", hash = "sha256:2843345a744444ab5a7ba24ffed8ea2b5493edbc2e47292b1a3e924b2df55cac"}, + {file = "vonage-3.15.0.tar.gz", hash = "sha256:4ce60ad0d52c43fb05e860050598576b97a4397aa426f19c3326c76978b4ffc8"}, ] [package.dependencies] @@ -4440,18 +4460,18 @@ multidict = ">=4.0" [[package]] name = "zipp" -version = "3.19.0" +version = "3.19.2" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.19.0-py3-none-any.whl", hash = "sha256:96dc6ad62f1441bcaccef23b274ec471518daf4fbbc580341204936a5a3dddec"}, - {file = "zipp-3.19.0.tar.gz", hash = "sha256:952df858fb3164426c976d9338d3961e8e8b3758e2e059e0f754b8c4262625ee"}, + {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"}, + {file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [extras] agents = ["anthropic", "openai", "tiktoken"] @@ -4464,4 +4484,4 @@ transcribers = ["google-cloud-speech"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<4.0" -content-hash = "ee0e29c5a613ac943287786c64a591f516801fcada5aa7411d9f2d26ff2a7405" +content-hash = "0b362b102f8d84dd63633857a97c7ae7922358bfbb1e66b070e40c10643b7667" diff --git a/pyproject.toml b/pyproject.toml index 3df2cf670..fe9c29741 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,46 +11,46 @@ homepage = "https://github.com/vocodedev/vocode-python" [tool.poetry.dependencies] python = ">=3.10,<4.0" aiohttp = "^3.9.5" +anthropic = "^0.28.0" +azure-cognitiveservices-speech = "^1.37.0" +elevenlabs = "^1.2.2" fastapi = "^0.111.0" janus = "^1.0.0" jinja2 = "^3.1.4" jsonschema = "^4.22.0" loguru = "^0.7.2" +numpy = "^1.26.4" +openai = "^1.30.5" opentelemetry-sdk = "^1.24.0" phonenumbers = "^8.13.37" pydantic = "^2.7.2" +pydantic-settings = "^2.3.0" +pyht = "^0.0.28" +redis = "^5.0.4" requests = "^2.32.3" +sentry-sdk = { extras = ["fastapi"], version = "^2.3.1" } sounddevice = "^0.4.7" +tiktoken = "^0.7.0" uvicorn = "^0.30.0" websockets = "^12.0" -# Agents -anthropic = { version = "^0.28.0", optional = true } -openai = { version = "^1.30.5", optional = true } -tiktoken = { version = "0.7.0", optional = true } - # Synthesizers -azure-cognitiveservices-speech = { version = "^1.37.0", optional = true } -elevenlabs = { version = "^1.2.2", optional = true } google-cloud-texttospeech = { version = "^2.16.3", optional = true } miniaudio = { version = "^1.59", optional = true } nltk = { version = "^3.8.1", optional = true } pvkoala = { version = "^2.0.1", optional = true } pydub = { version = "^0.25.1", optional = true } -pyht = { version = "^0.0.28", optional = true } # Transcribers google-cloud-speech = { version = "^2.26.0", optional = true } # Telephony -redis = { version = "^5.0.4", optional = true } twilio = { version = "^9.1.0", optional = true } vonage = { version = "^3.14.0", optional = true } # Misc langchain = { version = "^0.2.1", optional = true } langchain-community = { version = "^0.2.1", optional = true } -sentry-sdk = { extras = ["fastapi"], version = "^2.3.1", optional = true } [tool.poetry.group.lint.dependencies] @@ -76,39 +76,27 @@ pytest-httpx = "^0.30.0" pytest-mock = "^3.14.0" [tool.poetry.extras] -agents = ["anthropic", "openai", "tiktoken"] synthesizers = [ - "azure-cognitiveservices-speech", - "elevenlabs", "google-cloud-texttospeech", "miniaudio", "nltk", "pvkoala", "pydub", - "pyht", ] transcribers = ["google-cloud-speech"] -telephony = ["twilio", "redis", "vonage"] -misc = ["langchain", "langchain-community", "sentry-sdk"] +telephony = ["twilio", "vonage"] +misc = ["langchain", "langchain-community"] all = [ - "anthropic", - "openai", - "tiktoken", - "azure-cognitiveservices-speech", - "elevenlabs", "google-cloud-texttospeech", "miniaudio", "nltk", "pvkoala", "pydub", - "pyht", "google-cloud-speech", "twilio", - "redis", "vonage", "langchain", "langchain-community", - "sentry-sdk", ] [tool.mypy] diff --git a/quickstarts/streaming_conversation.py b/quickstarts/streaming_conversation.py index 4d22ec046..9a482299f 100644 --- a/quickstarts/streaming_conversation.py +++ b/quickstarts/streaming_conversation.py @@ -1,26 +1,46 @@ import asyncio import signal -from dotenv import load_dotenv +from pydantic_settings import BaseSettings, SettingsConfigDict +from vocode.helpers import create_streaming_microphone_input_and_speaker_output from vocode.logging import configure_pretty_logging from vocode.streaming.agent.chat_gpt_agent import ChatGPTAgent from vocode.streaming.models.agent import ChatGPTAgentConfig +from vocode.streaming.models.message import BaseMessage from vocode.streaming.models.synthesizer import AzureSynthesizerConfig from vocode.streaming.models.transcriber import ( DeepgramTranscriberConfig, PunctuationEndpointingConfig, ) +from vocode.streaming.streaming_conversation import StreamingConversation from vocode.streaming.synthesizer.azure_synthesizer import AzureSynthesizer from vocode.streaming.transcriber.deepgram_transcriber import DeepgramTranscriber -load_dotenv() +configure_pretty_logging() -from vocode.helpers import create_streaming_microphone_input_and_speaker_output -from vocode.streaming.models.message import BaseMessage -from vocode.streaming.streaming_conversation import StreamingConversation -configure_pretty_logging() +class Settings(BaseSettings): + """ + Settings for the streaming conversation quickstart. + These parameters can be configured with environment variables. + """ + + openai_api_key: str = "ENTER_YOUR_OPENAI_API_KEY_HERE" + azure_speech_key: str = "ENTER_YOUR_AZURE_KEY_HERE" + deepgram_api_key: str = "ENTER_YOUR_DEEPGRAM_API_KEY_HERE" + + azure_speech_region: str = "eastus" + + # This means a .env file can be used to overload these settings + # ex: "OPENAI_API_KEY=my_key" will set openai_api_key over the default above + model_config = SettingsConfigDict( + env_file=".env", + env_file_encoding="utf-8", + ) + + +settings = Settings() async def main(): @@ -38,15 +58,21 @@ async def main(): DeepgramTranscriberConfig.from_input_device( microphone_input, endpointing_config=PunctuationEndpointingConfig(), - ) + api_key=settings.deepgram_api_key, + ), ), agent=ChatGPTAgent( ChatGPTAgentConfig( + openai_api_key=settings.openai_api_key, initial_message=BaseMessage(text="What up"), prompt_preamble="""The AI is having a pleasant conversation about life""", ) ), - synthesizer=AzureSynthesizer(AzureSynthesizerConfig.from_output_device(speaker_output)), + synthesizer=AzureSynthesizer( + AzureSynthesizerConfig.from_output_device(speaker_output), + azure_speech_key=settings.azure_speech_key, + azure_speech_region=settings.azure_speech_region, + ), ) await conversation.start() print("Conversation started, press Ctrl+C to end") diff --git a/quickstarts/turn_based_conversation.py b/quickstarts/turn_based_conversation.py index 35eef61fe..73cfb0f0c 100644 --- a/quickstarts/turn_based_conversation.py +++ b/quickstarts/turn_based_conversation.py @@ -1,16 +1,32 @@ -from dotenv import load_dotenv +from pydantic_settings import BaseSettings, SettingsConfigDict -from vocode import getenv from vocode.helpers import create_turn_based_microphone_input_and_speaker_output from vocode.turn_based.agent.chat_gpt_agent import ChatGPTAgent from vocode.turn_based.synthesizer.azure_synthesizer import AzureSynthesizer from vocode.turn_based.transcriber.whisper_transcriber import WhisperTranscriber from vocode.turn_based.turn_based_conversation import TurnBasedConversation -load_dotenv() -# See https://api.elevenlabs.io/v1/voices -ADAM_VOICE_ID = "pNInz6obpgDQGcFmaJgB" +class Settings(BaseSettings): + """ + Settings for the turn-based conversation quickstart. + These parameters can be configured with environment variables. + """ + + openai_api_key: str = "ENTER_YOUR_OPENAI_API_KEY_HERE" + azure_speech_key: str = "ENTER_YOUR_AZURE_KEY_HERE" + + azure_speech_region: str = "eastus" + + # This means a .env file can be used to overload these settings + # ex: "OPENAI_API_KEY=my_key" will set openai_api_key over the default above + model_config = SettingsConfigDict( + env_file=".env", + env_file_encoding="utf-8", + ) + + +settings = Settings() if __name__ == "__main__": ( @@ -23,15 +39,15 @@ conversation = TurnBasedConversation( input_device=microphone_input, output_device=speaker_output, - transcriber=WhisperTranscriber(api_key=getenv("OPENAI_API_KEY")), + transcriber=WhisperTranscriber(api_key=settings.openai_api_key), agent=ChatGPTAgent( system_prompt="The AI is having a pleasant conversation about life", initial_message="Hello!", - api_key=getenv("OPENAI_API_KEY"), + api_key=settings.openai_api_key, ), synthesizer=AzureSynthesizer( - api_key=getenv("AZURE_SPEECH_KEY"), - region=getenv("AZURE_SPEECH_REGION"), + api_key=settings.azure_speech_key, + region=settings.azure_speech_region, voice_name="en-US-SteffanNeural", ), ) diff --git a/vocode/__init__.py b/vocode/__init__.py index eca391cb8..c895c2e45 100644 --- a/vocode/__init__.py +++ b/vocode/__init__.py @@ -6,9 +6,13 @@ import sentry_sdk from loguru import logger +from vocode.meta import ensure_punkt_installed + environment = {} logger.disable("vocode") +ensure_punkt_installed() + class ContextWrapper: """Context Variable Wrapper.""" diff --git a/vocode/meta.py b/vocode/meta.py new file mode 100644 index 000000000..f3f455b54 --- /dev/null +++ b/vocode/meta.py @@ -0,0 +1,15 @@ +from loguru import logger + + +def ensure_punkt_installed(): + try: + from nltk.data import find + + find("tokenizers/punkt") + except LookupError: + from nltk import download + + # If not installed, download 'punkt' + logger.info("Downloading 'punkt' tokenizer...") + download("punkt") + logger.info("'punkt' tokenizer downloaded successfully.") diff --git a/vocode/streaming/agent/chat_gpt_agent.py b/vocode/streaming/agent/chat_gpt_agent.py index 889c5f459..047aa6c90 100644 --- a/vocode/streaming/agent/chat_gpt_agent.py +++ b/vocode/streaming/agent/chat_gpt_agent.py @@ -4,7 +4,8 @@ import sentry_sdk from loguru import logger -from openai import AsyncAzureOpenAI, AsyncOpenAI +from openai import DEFAULT_MAX_RETRIES as OPENAI_DEFAULT_MAX_RETRIES +from openai import AsyncAzureOpenAI, AsyncOpenAI, NotFoundError, RateLimitError from vocode import sentry_span_tags from vocode.streaming.action.abstract_factory import AbstractActionFactory @@ -27,6 +28,24 @@ ChatGPTAgentConfigType = TypeVar("ChatGPTAgentConfigType", bound=ChatGPTAgentConfig) +def instantiate_openai_client(agent_config: ChatGPTAgentConfig, model_fallback: bool = False): + if agent_config.azure_params: + return AsyncAzureOpenAI( + azure_endpoint=agent_config.azure_params.base_url, + api_key=agent_config.azure_params.api_key, + api_version=agent_config.azure_params.api_version, + max_retries=0 if model_fallback else OPENAI_DEFAULT_MAX_RETRIES, + ) + else: + if agent_config.openai_api_key is not None: + logger.info("Using OpenAI API key override") + return AsyncOpenAI( + api_key=agent_config.openai_api_key or os.environ["OPENAI_API_KEY"], + base_url="https://api.openai.com/v1", + max_retries=0 if model_fallback else OPENAI_DEFAULT_MAX_RETRIES, + ) + + class ChatGPTAgent(RespondAgent[ChatGPTAgentConfigType]): openai_client: Union[AsyncOpenAI, AsyncAzureOpenAI] @@ -42,19 +61,9 @@ def __init__( action_factory=action_factory, **kwargs, ) - if agent_config.azure_params: - self.openai_client = AsyncAzureOpenAI( - azure_endpoint=agent_config.azure_params.base_url, - api_key=agent_config.azure_params.api_key, - api_version=agent_config.azure_params.api_version, - ) - else: - if agent_config.openai_api_key is not None: - logger.info("Using OpenAI API key override") - self.openai_client = AsyncOpenAI( - api_key=agent_config.openai_api_key or os.environ["OPENAI_API_KEY"], - base_url="https://api.openai.com/v1", - ) + self.openai_client = instantiate_openai_client( + agent_config, model_fallback=agent_config.llm_fallback is not None + ) if not self.openai_client.api_key: raise ValueError("OPENAI_API_KEY must be set in environment or passed in") @@ -109,9 +118,37 @@ def get_model_name_for_tokenizer(self): else: return self.agent_config.azure_params.openai_model_name - async def _create_openai_stream(self, chat_parameters: Dict[str, Any]) -> AsyncGenerator: + def apply_model_fallback(self, chat_parameters: Dict[str, Any]): + if self.agent_config.llm_fallback is None: + return + if self.agent_config.llm_fallback.provider == "openai": + self.agent_config.model_name = self.agent_config.llm_fallback.model_name + if isinstance(self.openai_client, AsyncAzureOpenAI): + self.agent_config.azure_params = None + else: + if self.agent_config.azure_params: + self.agent_config.azure_params.deployment_name = ( + self.agent_config.llm_fallback.model_name + ) + if isinstance(self.openai_client, AsyncOpenAI): + # TODO: handle OpenAI fallback to Azure + pass + + self.openai_client = instantiate_openai_client(self.agent_config, model_fallback=False) + chat_parameters["model"] = self.agent_config.llm_fallback.model_name + + async def _create_openai_stream_with_fallback( + self, chat_parameters: Dict[str, Any] + ) -> AsyncGenerator: try: stream = await self.openai_client.chat.completions.create(**chat_parameters) + except (NotFoundError, RateLimitError) as e: + logger.error( + f"{'Model not found' if isinstance(e, NotFoundError) else 'Rate limit error'} for model_name: {chat_parameters.get('model')}. Applying fallback.", + exc_info=True, + ) + self.apply_model_fallback(chat_parameters) + stream = await self.openai_client.chat.completions.create(**chat_parameters) except Exception as e: logger.error( f"Error while hitting OpenAI with chat_parameters: {chat_parameters}", @@ -120,6 +157,20 @@ async def _create_openai_stream(self, chat_parameters: Dict[str, Any]) -> AsyncG raise e return stream + async def _create_openai_stream(self, chat_parameters: Dict[str, Any]) -> AsyncGenerator: + if self.agent_config.llm_fallback is not None and self.openai_client.max_retries == 0: + stream = await self._create_openai_stream_with_fallback(chat_parameters) + else: + try: + stream = await self.openai_client.chat.completions.create(**chat_parameters) + except Exception as e: + logger.error( + f"Error while hitting OpenAI with chat_parameters: {chat_parameters}", + exc_info=True, + ) + raise e + return stream + def should_backchannel(self, human_input: str) -> bool: return ( not self.is_first_response() diff --git a/vocode/streaming/agent/default_factory.py b/vocode/streaming/agent/default_factory.py index c862a5cc5..7a05c842a 100644 --- a/vocode/streaming/agent/default_factory.py +++ b/vocode/streaming/agent/default_factory.py @@ -9,7 +9,6 @@ AnthropicAgentConfig, ChatGPTAgentConfig, EchoAgentConfig, - LlamacppAgentConfig, RESTfulUserImplementedAgentConfig, ) diff --git a/vocode/streaming/agent/llamacpp_agent.py b/vocode/streaming/agent/llamacpp_agent.py index 8b04756b6..efd565f9d 100644 --- a/vocode/streaming/agent/llamacpp_agent.py +++ b/vocode/streaming/agent/llamacpp_agent.py @@ -1,140 +1,121 @@ -import asyncio -import typing -from concurrent.futures import ThreadPoolExecutor -from typing import Any, AsyncGenerator, Optional, Tuple, Union - -from langchain import ConversationChain -from langchain.callbacks.base import BaseCallbackHandler -from langchain.callbacks.manager import CallbackManager -from langchain.llms import LlamaCpp -from langchain.memory import ConversationBufferMemory -from langchain.prompts import ( - ChatPromptTemplate, - HumanMessagePromptTemplate, - MessagesPlaceholder, - PromptTemplate, -) -from langchain.schema import LLMResult, SystemMessage, get_buffer_string -from langchain_core.prompts.string import DEFAULT_FORMATTER_MAPPING -from loguru import logger -from pydantic.v1 import BaseModel - -from vocode.streaming.agent.base_agent import RespondAgent -from vocode.streaming.agent.streaming_utils import collate_response_async -from vocode.streaming.models.agent import LlamacppAgentConfig - raise DeprecationWarning("This Agent is deprecated and will be removed in the future.") -ALPACA_TEMPLATE_WITH_HISTORY = """### Instruction: -Your previous conversation history: -{history} - -Current instruction/message to respond to: {input} -### Response:""" - - -class CallbackOutput(BaseModel): - finish: bool = False - response: Optional[LLMResult] = None - token: str = "" - - -class FormatHistoryPromptTemplate(PromptTemplate): - def format(self, **kwargs: Any) -> str: - kwargs = self._merge_partial_and_user_variables(**kwargs) - kwargs["history"] = get_buffer_string(kwargs["history"]) - return DEFAULT_FORMATTER_MAPPING[self.template_format](self.template, **kwargs) - - -class CustomStreamingCallbackHandler(BaseCallbackHandler): - def __init__(self, output_queue: asyncio.Queue) -> None: - super().__init__() - self.output_queue = output_queue - - def on_llm_new_token(self, token: str, **kwargs: Any) -> None: - """Run on new LLM token. Only available when streaming is enabled.""" - self.output_queue.put_nowait(CallbackOutput(token=token)) - - def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None: - """Run when LLM ends running.""" - self.output_queue.put_nowait(CallbackOutput(finish=True, response=response)) - - -class LlamacppAgent(RespondAgent[LlamacppAgentConfig]): - def __init__( - self, - agent_config: LlamacppAgentConfig, - ): - super().__init__(agent_config=agent_config) - - self.prompt: Union[PromptTemplate, ChatPromptTemplate] - if type(agent_config.prompt_template) is str: - if agent_config.prompt_template == "alpaca": - self.prompt = FormatHistoryPromptTemplate( - input_variables=["history", "input"], - template=ALPACA_TEMPLATE_WITH_HISTORY, - ) - else: - raise ValueError(f"Unknown prompt template {agent_config.prompt_template}") - else: - if agent_config.prompt_template is None: - self.prompt = ChatPromptTemplate.from_messages( - [ - MessagesPlaceholder(variable_name="history"), - HumanMessagePromptTemplate.from_template("{input}"), - ] - ) - else: - self.promt = typing.cast(PromptTemplate, agent_config.prompt_template) - - self.callback_queue: asyncio.Queue = asyncio.Queue() - callback = CustomStreamingCallbackHandler(self.callback_queue) - callback_manager = CallbackManager([callback]) - self.llm = LlamaCpp(callback_manager=callback_manager, **agent_config.llamacpp_kwargs) - - self.memory = ConversationBufferMemory(return_messages=True) - self.memory.chat_memory.messages.append( - SystemMessage(content=self.agent_config.prompt_preamble) - ) - - self.conversation = ConversationChain(memory=self.memory, prompt=self.prompt, llm=self.llm) - self.thread_pool_executor = ThreadPoolExecutor(max_workers=1) - - async def respond( - self, - human_input, - conversation_id: str, - is_interrupt: bool = False, - ) -> Tuple[str, bool]: - text = await asyncio.get_event_loop().run_in_executor( - self.thread_pool_executor, - lambda input: self.conversation.predict(input=input), - human_input, - ) - - logger.debug(f"LLM response: {text}") - return text, False - - async def llamacpp_get_tokens(self): - while True: - callback_output = await self.callback_queue.get() - if callback_output.finish: - break - yield callback_output.token - - async def generate_response( - self, - human_input: str, - conversation_id: str, - is_interrupt: bool = False, - ) -> AsyncGenerator[Tuple[str, bool], None]: - asyncio.get_event_loop().run_in_executor( - self.thread_pool_executor, - lambda input: self.conversation.predict(input=input), - human_input, - ) - - async for message in collate_response_async( - self.llamacpp_get_tokens(), - ): - yield str(message), True +# OLD CONFIG BELOW +# class LlamacppAgentConfig(AgentConfig, type=AgentType.LLAMACPP.value): # type: ignore +# prompt_preamble: str +# llamacpp_kwargs: dict = {} +# prompt_template: Optional[Union["PromptTemplate", str]] = None + +# ALPACA_TEMPLATE_WITH_HISTORY = """### Instruction: +# Your previous conversation history: +# {history} + +# Current instruction/message to respond to: {input} +# ### Response:""" + + +# class CallbackOutput(BaseModel): +# finish: bool = False +# response: Optional[LLMResult] = None +# token: str = "" + + +# class FormatHistoryPromptTemplate(PromptTemplate): +# def format(self, **kwargs: Any) -> str: +# kwargs = self._merge_partial_and_user_variables(**kwargs) +# kwargs["history"] = get_buffer_string(kwargs["history"]) +# return DEFAULT_FORMATTER_MAPPING[self.template_format](self.template, **kwargs) + + +# class CustomStreamingCallbackHandler(BaseCallbackHandler): +# def __init__(self, output_queue: asyncio.Queue) -> None: +# super().__init__() +# self.output_queue = output_queue + +# def on_llm_new_token(self, token: str, **kwargs: Any) -> None: +# """Run on new LLM token. Only available when streaming is enabled.""" +# self.output_queue.put_nowait(CallbackOutput(token=token)) + +# def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None: +# """Run when LLM ends running.""" +# self.output_queue.put_nowait(CallbackOutput(finish=True, response=response)) + + +# class LlamacppAgent(RespondAgent[LlamacppAgentConfig]): +# def __init__( +# self, +# agent_config: LlamacppAgentConfig, +# ): +# super().__init__(agent_config=agent_config) + +# self.prompt: Union[PromptTemplate, ChatPromptTemplate] +# if type(agent_config.prompt_template) is str: +# if agent_config.prompt_template == "alpaca": +# self.prompt = FormatHistoryPromptTemplate( +# input_variables=["history", "input"], +# template=ALPACA_TEMPLATE_WITH_HISTORY, +# ) +# else: +# raise ValueError(f"Unknown prompt template {agent_config.prompt_template}") +# else: +# if agent_config.prompt_template is None: +# self.prompt = ChatPromptTemplate.from_messages( +# [ +# MessagesPlaceholder(variable_name="history"), +# HumanMessagePromptTemplate.from_template("{input}"), +# ] +# ) +# else: +# self.promt = typing.cast(PromptTemplate, agent_config.prompt_template) + +# self.callback_queue: asyncio.Queue = asyncio.Queue() +# callback = CustomStreamingCallbackHandler(self.callback_queue) +# callback_manager = CallbackManager([callback]) +# self.llm = LlamaCpp(callback_manager=callback_manager, **agent_config.llamacpp_kwargs) + +# self.memory = ConversationBufferMemory(return_messages=True) +# self.memory.chat_memory.messages.append( +# SystemMessage(content=self.agent_config.prompt_preamble) +# ) + +# self.conversation = ConversationChain(memory=self.memory, prompt=self.prompt, llm=self.llm) +# self.thread_pool_executor = ThreadPoolExecutor(max_workers=1) + +# async def respond( +# self, +# human_input, +# conversation_id: str, +# is_interrupt: bool = False, +# ) -> Tuple[str, bool]: +# text = await asyncio.get_event_loop().run_in_executor( +# self.thread_pool_executor, +# lambda input: self.conversation.predict(input=input), +# human_input, +# ) + +# logger.debug(f"LLM response: {text}") +# return text, False + +# async def llamacpp_get_tokens(self): +# while True: +# callback_output = await self.callback_queue.get() +# if callback_output.finish: +# break +# yield callback_output.token + +# async def generate_response( +# self, +# human_input: str, +# conversation_id: str, +# is_interrupt: bool = False, +# ) -> AsyncGenerator[Tuple[str, bool], None]: +# asyncio.get_event_loop().run_in_executor( +# self.thread_pool_executor, +# lambda input: self.conversation.predict(input=input), +# human_input, +# ) + +# async for message in collate_response_async( +# self.llamacpp_get_tokens(), +# ): +# yield str(message), True diff --git a/vocode/streaming/models/agent.py b/vocode/streaming/models/agent.py index fb9832fba..7e5a3e6ba 100644 --- a/vocode/streaming/models/agent.py +++ b/vocode/streaming/models/agent.py @@ -1,7 +1,6 @@ from enum import Enum from typing import List, Literal, Optional, Union -from langchain.prompts import PromptTemplate from pydantic.v1 import validator from .model import BaseModel, TypedModel @@ -106,6 +105,11 @@ class LLMAgentConfig(AgentConfig, type=AgentType.LLM.value): # type: ignore max_tokens: int = LLM_AGENT_DEFAULT_MAX_TOKENS +class LLMFallback(BaseModel): + provider: Literal["openai", "azure"] + model_name: str + + class ChatGPTAgentConfig(AgentConfig, type=AgentType.CHAT_GPT.value): # type: ignore openai_api_key: Optional[str] = None prompt_preamble: str @@ -118,6 +122,7 @@ class ChatGPTAgentConfig(AgentConfig, type=AgentType.CHAT_GPT.value): # type: i use_backchannels: bool = False backchannel_probability: float = 0.7 first_response_filler_message: Optional[str] = None + llm_fallback: Optional[LLMFallback] = None class AnthropicAgentConfig(AgentConfig, type=AgentType.ANTHROPIC.value): # type: ignore @@ -133,12 +138,6 @@ class ChatVertexAIAgentConfig(AgentConfig, type=AgentType.CHAT_VERTEX_AI.value): generate_responses: bool = False # Google Vertex AI doesn't support streaming -class LlamacppAgentConfig(AgentConfig, type=AgentType.LLAMACPP.value): # type: ignore - prompt_preamble: str - llamacpp_kwargs: dict = {} - prompt_template: Optional[Union[PromptTemplate, str]] = None - - class InformationRetrievalAgentConfig( AgentConfig, type=AgentType.INFORMATION_RETRIEVAL.value # type: ignore ): diff --git a/vocode/streaming/models/transcriber.py b/vocode/streaming/models/transcriber.py index c666767fa..857e5b6c0 100644 --- a/vocode/streaming/models/transcriber.py +++ b/vocode/streaming/models/transcriber.py @@ -111,6 +111,7 @@ class DeepgramTranscriberConfig(TranscriberConfig, type=TranscriberType.DEEPGRAM tier: Optional[str] = None version: Optional[str] = None keywords: Optional[list] = None + api_key: Optional[str] = None on_prem: bool = False ws_url: str = DEEPGRAM_API_WS_URL diff --git a/vocode/streaming/streaming_conversation.py b/vocode/streaming/streaming_conversation.py index 13162bbdf..8e4798016 100644 --- a/vocode/streaming/streaming_conversation.py +++ b/vocode/streaming/streaming_conversation.py @@ -421,7 +421,7 @@ async def process(self, item: InterruptibleAgentResponseEvent[AgentResponse]): if self.last_agent_response_tracker is not None: await self.last_agent_response_tracker.wait() item.agent_response_tracker.set() - self.conversation.mark_terminated(bot_disconnect=True) + await self.conversation.mark_terminated(bot_disconnect=True) return agent_response_message = typing.cast(AgentResponseMessage, agent_response) @@ -674,6 +674,10 @@ def __init__( self.start_time: Optional[float] = None self.end_time: Optional[float] = None + self.idle_time_threshold = ( + self.agent.get_agent_config().allowed_idle_time_seconds or ALLOWED_IDLE_TIME + ) + def create_state_manager(self) -> ConversationStateManager: return ConversationStateManager(conversation=self) @@ -741,23 +745,23 @@ async def send_initial_message( ) await self.initial_message_tracker.wait() + async def action_on_idle(self): + logger.debug("Conversation idle for too long, terminating") + await self.mark_terminated(bot_disconnect=True) + return + async def check_for_idle(self): """Asks if human is still on the line if no activity is detected, and terminates the conversation if not.""" await self.initial_message_tracker.wait() check_human_present_count = 0 check_human_present_threshold = self.agent.get_agent_config().num_check_human_present_times - idle_time_threshold = ( - self.agent.get_agent_config().allowed_idle_time_seconds or ALLOWED_IDLE_TIME - ) while self.is_active(): if ( not self.check_for_idle_paused - ) and time.time() - self.last_action_timestamp > idle_time_threshold: + ) and time.time() - self.last_action_timestamp > self.idle_time_threshold: if check_human_present_count >= check_human_present_threshold: # Stop the phone call after some retries to prevent infinitely long call where human is just silent. - logger.debug("Conversation idle for too long, terminating") - self.mark_terminated(bot_disconnect=True) - return + await self.action_on_idle() await self.send_single_message( message=BaseMessage(text=random.choice(CHECK_HUMAN_PRESENT_MESSAGE_CHOICES)), ) @@ -957,11 +961,11 @@ async def get_chunks( synthesis_result.synthesis_total_span.finish() return message_sent, cut_off - def mark_terminated(self, bot_disconnect: bool = False): + async def mark_terminated(self, bot_disconnect: bool = False): self.active = False async def terminate(self): - self.mark_terminated() + await self.mark_terminated() self.broadcast_interrupt() self.events_manager.publish_event( TranscriptCompleteEvent( diff --git a/vocode/streaming/synthesizer/base_synthesizer.py b/vocode/streaming/synthesizer/base_synthesizer.py index 31a4928fb..e3e86661f 100644 --- a/vocode/streaming/synthesizer/base_synthesizer.py +++ b/vocode/streaming/synthesizer/base_synthesizer.py @@ -435,5 +435,22 @@ async def send_chunks(): finally: miniaudio_worker.terminate() + def _resample_chunk( + self, + chunk: bytes, + current_sample_rate: int, + target_sample_rate: int, + ) -> bytes: + resampled_chunk, _ = audioop.ratecv( + chunk, + 2, + 1, + current_sample_rate, + target_sample_rate, + None, + ) + + return resampled_chunk + async def tear_down(self): pass diff --git a/vocode/streaming/synthesizer/eleven_labs_synthesizer.py b/vocode/streaming/synthesizer/eleven_labs_synthesizer.py index e4af50c22..714b5bf72 100644 --- a/vocode/streaming/synthesizer/eleven_labs_synthesizer.py +++ b/vocode/streaming/synthesizer/eleven_labs_synthesizer.py @@ -37,6 +37,8 @@ def __init__( self.model_id = synthesizer_config.model_id self.optimize_streaming_latency = synthesizer_config.optimize_streaming_latency self.words_per_minute = 150 + self.upsample = None + self.sample_rate = self.synthesizer_config.sampling_rate if self.synthesizer_config.audio_encoding == AudioEncoding.LINEAR16: match self.synthesizer_config.sampling_rate: @@ -48,6 +50,10 @@ def __init__( self.output_format = "pcm_24000" case SamplingRate.RATE_44100: self.output_format = "pcm_44100" + case SamplingRate.RATE_48000: + self.output_format = "pcm_44100" + self.upsample = SamplingRate.RATE_48000.value + self.sample_rate = SamplingRate.RATE_44100.value case _: raise ValueError( f"Unsupported sampling rate: {self.synthesizer_config.sampling_rate}. Elevenlabs only supports 16000, 22050, 24000, and 44100 Hz." @@ -67,11 +73,15 @@ async def create_speech_uncached( is_sole_text_chunk: bool = False, ) -> SynthesisResult: self.total_chars += len(message.text) - voice = Voice(voice_id=self.voice_id) if self.stability is not None and self.similarity_boost is not None: - voice.settings = VoiceSettings( - stability=self.stability, similarity_boost=self.similarity_boost + voice = Voice( + voice_id=self.voice_id, + settings=VoiceSettings( + stability=self.stability, similarity_boost=self.similarity_boost + ), ) + else: + voice = Voice(voice_id=self.voice_id) url = ( ELEVEN_LABS_BASE_URL + f"text-to-speech/{self.voice_id}/stream?output_format={self.output_format}" @@ -137,6 +147,12 @@ async def get_chunks( logger.error(f"ElevenLabs API failed: {stream.status_code} {error.decode('utf-8')}") raise Exception(f"ElevenLabs API returned {stream.status_code} status code") async for chunk in stream.aiter_bytes(chunk_size): + if self.upsample: + chunk = self._resample_chunk( + chunk, + self.sample_rate, + self.upsample, + ) chunk_queue.put_nowait(chunk) except asyncio.CancelledError: pass diff --git a/vocode/streaming/synthesizer/eleven_labs_websocket_synthesizer.py b/vocode/streaming/synthesizer/eleven_labs_websocket_synthesizer.py index 0f0679713..c4644ad6c 100644 --- a/vocode/streaming/synthesizer/eleven_labs_websocket_synthesizer.py +++ b/vocode/streaming/synthesizer/eleven_labs_websocket_synthesizer.py @@ -109,6 +109,9 @@ def __init__( } self.end_of_turn = False + self.upsample = None + self.sample_rate = self.synthesizer_config.sampling_rate + # While this looks useless, we need to assign the response of `asyncio.gather` # to *something* or we risk garbage collection of the running coroutines spawned # by `asyncio.gather`. @@ -124,6 +127,10 @@ def __init__( self.output_format = "pcm_24000" case SamplingRate.RATE_44100: self.output_format = "pcm_44100" + case SamplingRate.RATE_48000: + self.output_format = "pcm_44100" + self.upsample = SamplingRate.RATE_48000.value + self.sample_rate = SamplingRate.RATE_44100.value case _: raise ValueError( f"Unsupported sampling rate: {self.synthesizer_config.sampling_rate}. Elevenlabs only supports 16000, 22050, 24000, and 44100 Hz." @@ -212,12 +219,21 @@ async def listen() -> None: message = await ws.recv() if "audio" not in message: continue - response = ElevenLabsWebsocketResponse.parse_raw(message) + response = ElevenLabsWebsocketResponse.model_validate_json(message) if response.audio: decoded = base64.b64decode(response.audio) seconds = len(decoded) / ( self.sample_width * self.synthesizer_config.sampling_rate ) + + if self.upsample: + decoded = self._resample_chunk( + decoded, + self.sample_rate, + self.upsample, + ) + seconds = len(decoded) / (self.sample_width * self.sample_rate) + if response.alignment: utterance_chunk = "".join(response.alignment.chars) + " " self.current_turn_utterances_by_chunk.append((utterance_chunk, seconds)) diff --git a/vocode/streaming/telephony/client/vonage_client.py b/vocode/streaming/telephony/client/vonage_client.py index 3a7e76a06..ffc70f7b3 100644 --- a/vocode/streaming/telephony/client/vonage_client.py +++ b/vocode/streaming/telephony/client/vonage_client.py @@ -1,8 +1,6 @@ import os from typing import Any, Dict, List, Optional -import vonage - from vocode.streaming.models.telephony import VonageConfig from vocode.streaming.telephony.client.abstract_telephony_client import AbstractTelephonyClient from vocode.streaming.telephony.constants import VONAGE_CONTENT_TYPE @@ -20,6 +18,11 @@ def __init__( maybe_vonage_config: Optional[VonageConfig] = None, record_calls: bool = False, ): + + import vonage + + self.vonage = vonage + super().__init__( base_url=base_url, ) @@ -31,7 +34,7 @@ def __init__( record=record_calls, ) # Vonage's sync client: only used for authentication helpers - self.client = vonage.Client( + self.client = self.vonage.Client( key=self.vonage_config.api_key, secret=self.vonage_config.api_secret, application_id=self.vonage_config.application_id, diff --git a/vocode/streaming/telephony/conversation/twilio_phone_conversation.py b/vocode/streaming/telephony/conversation/twilio_phone_conversation.py index 232efd41a..6145d53b0 100644 --- a/vocode/streaming/telephony/conversation/twilio_phone_conversation.py +++ b/vocode/streaming/telephony/conversation/twilio_phone_conversation.py @@ -115,6 +115,7 @@ async def attach_ws_and_start(self, ws: WebSocket): response = await self._handle_ws_message(message) if response == TwilioPhoneConversationWebsocketAction.CLOSE_WEBSOCKET: break + await ws.close(code=1000, reason=None) await self.terminate() async def _wait_for_twilio_start(self, ws: WebSocket): diff --git a/vocode/streaming/transcriber/azure_transcriber.py b/vocode/streaming/transcriber/azure_transcriber.py index 6a804c02e..c272fdf89 100644 --- a/vocode/streaming/transcriber/azure_transcriber.py +++ b/vocode/streaming/transcriber/azure_transcriber.py @@ -1,6 +1,5 @@ import queue from datetime import datetime, timezone -from typing import Optional import sentry_sdk from azure.cognitiveservices.speech.audio import ( diff --git a/vocode/streaming/transcriber/deepgram_transcriber.py b/vocode/streaming/transcriber/deepgram_transcriber.py index d602f0c8e..7af17237a 100644 --- a/vocode/streaming/transcriber/deepgram_transcriber.py +++ b/vocode/streaming/transcriber/deepgram_transcriber.py @@ -1,6 +1,5 @@ import asyncio import json -import os from datetime import datetime, timezone from typing import List, Optional, Tuple, Union from urllib.parse import urlencode @@ -11,6 +10,7 @@ from pydantic.v1 import BaseModel, Field from websockets.client import WebSocketClientProtocol +from vocode import getenv from vocode.streaming.models.audio import AudioEncoding from vocode.streaming.models.transcriber import ( DEEPGRAM_API_WS_URL, @@ -80,7 +80,11 @@ def __init__( transcriber_config: DeepgramTranscriberConfig, ): super().__init__(transcriber_config) - self.api_key = os.environ["DEEPGRAM_API_KEY"] + self.api_key = self.transcriber_config.api_key or getenv("DEEPGRAM_API_KEY") + if not self.api_key: + raise ValueError( + "Please set DEEPGRAM_API_KEY environment variable or pass it as a parameter" + ) self._ended = False self.is_ready = False self.audio_cursor = 0.0 diff --git a/vocode/streaming/utils/redis_conversation_message_queue.py b/vocode/streaming/utils/redis_conversation_message_queue.py index 4ec28edc8..a4c6e00ca 100644 --- a/vocode/streaming/utils/redis_conversation_message_queue.py +++ b/vocode/streaming/utils/redis_conversation_message_queue.py @@ -1,7 +1,7 @@ -from typing import Annotated, AsyncGenerator, Literal, Union +from typing import AsyncGenerator from loguru import logger -from pydantic.v1 import BaseModel, Field, parse_obj_as +from pydantic.v1 import BaseModel, parse_obj_as from redis.asyncio import Redis from vocode.streaming.utils.redis import initialize_redis diff --git a/vocode/streaming/vector_db/base_vector_db.py b/vocode/streaming/vector_db/base_vector_db.py index 032b29c05..19a0aa318 100644 --- a/vocode/streaming/vector_db/base_vector_db.py +++ b/vocode/streaming/vector_db/base_vector_db.py @@ -1,12 +1,14 @@ import os -from typing import Iterable, List, Optional, Tuple, Union +from typing import TYPE_CHECKING, Iterable, List, Optional, Tuple, Union import aiohttp -from langchain.docstore.document import Document from openai import AsyncAzureOpenAI, AsyncOpenAI from vocode.streaming.models.agent import AZURE_OPENAI_DEFAULT_API_VERSION +if TYPE_CHECKING: + from langchain.docstore.document import Document + DEFAULT_OPENAI_EMBEDDING_MODEL = "text-embedding-ada-002" @@ -64,7 +66,7 @@ async def similarity_search_with_score( query: str, filter: Optional[dict] = None, namespace: Optional[str] = None, - ) -> List[Tuple[Document, float]]: + ) -> List[Tuple["Document", float]]: raise NotImplementedError async def tear_down(self): diff --git a/vocode/streaming/vector_db/factory.py b/vocode/streaming/vector_db/factory.py index 3aa8eecd5..9ce03bab7 100644 --- a/vocode/streaming/vector_db/factory.py +++ b/vocode/streaming/vector_db/factory.py @@ -1,10 +1,12 @@ -from typing import Optional +from typing import TYPE_CHECKING, Optional import aiohttp from vocode.streaming.models.vector_db import PineconeConfig, VectorDBConfig from vocode.streaming.vector_db.base_vector_db import VectorDB -from vocode.streaming.vector_db.pinecone import PineconeDB + +if TYPE_CHECKING: + from vocode.streaming.vector_db.pinecone import PineconeDB class VectorDBFactory: @@ -14,5 +16,17 @@ def create_vector_db( aiohttp_session: Optional[aiohttp.ClientSession] = None, ) -> VectorDB: if isinstance(vector_db_config, PineconeConfig): - return PineconeDB(vector_db_config, aiohttp_session=aiohttp_session) + return self._get_pinecone_db(vector_db_config, aiohttp_session) raise Exception("Invalid vector db config", vector_db_config.type) + + def _get_pinecone_db( + self, vector_db_config: PineconeConfig, aiohttp_session: Optional[aiohttp.ClientSession] + ) -> "PineconeDB": + try: + from vocode.streaming.vector_db.pinecone import PineconeDB + + return PineconeDB(vector_db_config, aiohttp_session=aiohttp_session) + except ImportError as e: + raise ImportError( + f"Missing required dependancies for VectorDB {vector_db_config.type}" + ) from e diff --git a/vocode/turn_based/synthesizer/eleven_labs_synthesizer.py b/vocode/turn_based/synthesizer/eleven_labs_synthesizer.py index 742bea578..68b77fb7f 100644 --- a/vocode/turn_based/synthesizer/eleven_labs_synthesizer.py +++ b/vocode/turn_based/synthesizer/eleven_labs_synthesizer.py @@ -2,7 +2,7 @@ from typing import Optional from elevenlabs import Voice, VoiceSettings -from elevenlabs.client import AsyncElevenLabs +from elevenlabs.client import ElevenLabs from pydub import AudioSegment from vocode import getenv @@ -21,7 +21,7 @@ def __init__( self.voice_id = voice_id self.api_key = getenv("ELEVEN_LABS_API_KEY", api_key) - self.elevenlabs_client = AsyncElevenLabs( + self.elevenlabs_client = ElevenLabs( api_key=self.api_key, ) self.validate_stability_and_similarity_boost(stability, similarity_boost) @@ -35,11 +35,15 @@ def validate_stability_and_similarity_boost( raise ValueError("Both stability and similarity_boost must be set or not set.") def synthesize(self, text: str) -> AudioSegment: - voice = Voice(voice_id=self.voice_id) if self.stability is not None and self.similarity_boost is not None: - voice.settings = VoiceSettings( - stability=self.stability, similarity_boost=self.similarity_boost + voice = Voice( + voice_id=self.voice_id, + settings=VoiceSettings( + stability=self.stability, similarity_boost=self.similarity_boost + ), ) + else: + voice = Voice(voice_id=self.voice_id) audio = self.elevenlabs_client.generate(text=text, voice=voice) diff --git a/vocode/utils/sentry_utils.py b/vocode/utils/sentry_utils.py index f27829fd0..74da6a1f5 100644 --- a/vocode/utils/sentry_utils.py +++ b/vocode/utils/sentry_utils.py @@ -1,19 +1,12 @@ import functools from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Tuple +import sentry_sdk from loguru import logger +from sentry_sdk.tracing import Span, Transaction, _SpanRecorder from vocode import get_serialized_ctx_wrappers -try: - import sentry_sdk - from sentry_sdk.tracing import Span, Transaction, _SpanRecorder - - SENTRY_SDK_AVAILABLE = True -except ImportError: - logger.debug("Sentry SDK not detected -- disabling metrics!") - SENTRY_SDK_AVAILABLE = False - if TYPE_CHECKING: from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer @@ -86,14 +79,11 @@ def __init__(self, func: Callable, *args: Tuple, **kwargs: Dict) -> None: @property def is_configured(self) -> bool: """ - Checks if Sentry is available and configured. + Checks if Sentry is configured. Returns: bool: True if Sentry is configured, False otherwise. """ - if not SENTRY_SDK_AVAILABLE: - return False - client = sentry_sdk.Hub.current.client if client is not None and client.options is not None and "dsn" in client.options: return True From 740114038bf0d3d101417964daafe6734c89d263 Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Mon, 10 Jun 2024 12:01:47 -0700 Subject: [PATCH 12/25] [docs sprint] Updates docs for using transcribers (#9) --- docs/open-source/using-transcribers.mdx | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/docs/open-source/using-transcribers.mdx b/docs/open-source/using-transcribers.mdx index 8fdc71f7b..2a2c9d069 100644 --- a/docs/open-source/using-transcribers.mdx +++ b/docs/open-source/using-transcribers.mdx @@ -33,7 +33,7 @@ from vocode.streaming.models.transcriber import DeepgramTranscriberConfig, Punct server = InboundCallServer( ... transcriber_config=DeepgramTranscriberConfig.from_telephone_input_device( - endpointing_config=PunctuationEndpointingConfig() + endpointing_config=DeepgramEndpointingConfig() ), ... ) @@ -56,7 +56,7 @@ async def main(): output_device=speaker_output, transcriber=DeepgramTranscriber( DeepgramTranscriberConfig.from_input_device( - microphone_input, endpointing_config=PunctuationEndpointingConfig() + microphone_input, endpointing_config=DeepgramEndpointingConfig() ) ), ... @@ -70,7 +70,22 @@ The method takes a `microphone_input` object as an argument and extracts the `sa Endpointing is the process of understanding when someone has finished speaking. The `EndpointingConfig` controls how this is done. There are a couple of different ways to configure endpointing: +We provide `DeepgramEndpointingConfig()` which has some reasonable defaults and knobs to suit most use-cases (but only works with the Deepgram transcriber). + +``` +class DeepgramEndpointingConfig(EndpointingConfig, type="deepgram"): # type: ignore + vad_threshold_ms: int = 500 + utterance_cutoff_ms: int = 1000 + time_silent_config: Optional[TimeSilentConfig] = Field(default_factory=TimeSilentConfig) + use_single_utterance_endpointing_for_first_utterance: bool = False +``` + +- `vad_threshold_ms`: translates to [Deepgram's `endpointing` feature](https://developers.deepgram.com/docs/endpointing#enable-feature) +- `utterance_cutoff_ms`: uses [Deepgram's Utterance End features](https://developers.deepgram.com/docs/utterance-end) +- `time_silent_config`: is a Vocode specific parameter that marks an utterance final if we haven't seen any new words in X seconds +- `use_single_utterance_endpointing_for_first_utterance`: Uses `is_final` instead of `speech_final` for endpointing for the first utterance (works really well for outbound conversations, where the user's first utterance is something like "Hello?") - see [this doc on Deepgram](https://developers.deepgram.com/docs/understand-endpointing-interim-results) for more info. + +Endpointing is highly use-case specific - building a realistic experience for this greatly depends on the person speaking to the AI. Here are few paradigms that we've used to help you along the way: + - Time-based endpointing: This method considers the speaker to be finished when there is a certain duration of silence. - Punctuation-based endpointing: This method considers the speaker to be finished when there is a certain duration of silence after a punctuation mark. - -In the first example, the `PunctuationEndpointingConfig` is used to configure the Deepgram transcriber for punctuation-based endpointing. From dfa66d5a4cfad505ebe84bbed281a4b1d76c7bad Mon Sep 17 00:00:00 2001 From: Adnaan Sachidanandan Date: Mon, 10 Jun 2024 12:20:05 -0700 Subject: [PATCH 13/25] [docs sprint] phrase trigger documentation (#16) --- docs/mint.json | 13 +++- docs/open-source/action-phrase-triggers.mdx | 86 +++++++++++++++++++++ 2 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 docs/open-source/action-phrase-triggers.mdx diff --git a/docs/mint.json b/docs/mint.json index bd97c3dbd..13a12f59f 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -49,7 +49,11 @@ "navigation": [ { "group": "Getting Started", - "pages": ["welcome", "hosted-quickstart", "open-source-quickstart"] + "pages": [ + "welcome", + "hosted-quickstart", + "open-source-quickstart" + ] }, { "group": "Vocode 101", @@ -67,6 +71,7 @@ "open-source/create-your-own-agent", "open-source/langchain-agent", "open-source/action-agents", + "open-source/action-phrase-triggers", "open-source/local-conversation", "open-source/events-manager", "open-source/using-synthesizers", @@ -109,7 +114,9 @@ }, { "group": "Usage", - "pages": ["api-reference/usage/get-usage"] + "pages": [ + "api-reference/usage/get-usage" + ] }, { "group": "Actions", @@ -223,4 +230,4 @@ "twitter": "https://twitter.com/vocodehq", "website": "https://www.vocode.dev/" } -} +} \ No newline at end of file diff --git a/docs/open-source/action-phrase-triggers.mdx b/docs/open-source/action-phrase-triggers.mdx new file mode 100644 index 000000000..e7a8dc2c5 --- /dev/null +++ b/docs/open-source/action-phrase-triggers.mdx @@ -0,0 +1,86 @@ +--- +title: 'Action Triggers' +description: 'Activate actions with function calls or specific phrases' +--- +## What are function calls? +[Function calls](https://platform.openai.com/docs/guides/function-calling) allow modern Large Language Models (LLMs) like ChatGPT to perform tasks outside of text generation. +For example, if I create a math assistant with ChatGPT, I might make a "multiply" function that ChatGPT can call to multiply two numbers together. + +If you add an action to a vocode agent, its corresponding function calling schema is added to each ChatGPT query. If the function call is outputted by ChatGPT, the corresponding action is triggered automatically. + +***Note:*** *In vocode agents, ChatGPT can return a text response alongside a function call. In this scenario, the text is synthesized and played first, then the action is run.* + +## What are phrase triggers? + +Phrase triggers are text phrases that activate an action when produced by an agent. Phrase triggers are useful in production use-cases where consistency and reliability are important, since text outputs are easier to control in comparison to function calls. + +## Configuring action triggers +Each vocode action config contains an `action_trigger` field to specify how the action is triggered. The default trigger is function calling. The examples below demonstrate how to set action triggers for an `EndConversation` action config: + +**Function calls:** +```python +from vocode.streaming.action.end_conversation import EndConversationVocodeActionConfig +from vocode.streaming.models.actions import FunctionCallActionTrigger + +EndConversationVocodeActionConfig( + type="action_end_conversation", + action_trigger=FunctionCallActionTrigger( + type="action_trigger_function_call" + ) +) +``` +***Note:*** *You can also leave `action_trigger` field empty and vocode will default to function calls.* + +**Phrase triggers:** + +```python +from vocode.streaming.action.end_conversation import EndConversationVocodeActionConfig +from vocode.streaming.models.actions import PhraseBasedActionTrigger, PhraseBasedActionTriggerConfig, PhraseTrigger + +EndConversationVocodeActionConfig( + type="action_end_conversation", + action_trigger=PhraseBasedActionTrigger( + type = "action_trigger_phrase_based", + config: PhraseBasedActionTriggerConfig( + phrase_triggers = [ + PhraseTrigger( + phrase="Ending conversation now", + condition="phrase_condition_type_contains" + ), + # Additional phrase triggers can be listed here + ] + ) + ) +) +``` +For the code above, if the agent says 'Ending conversation now', the end conversation action will automatically be taken. +You can add multiple phrase triggers for an action by passing a list of `PhraseTrigger` instances. + +The `phrase_condition_type_contains` condition configures the agent to run the action if its output *contains* the phrase. So, the action will also be run if the agent +says 'I am ending conversation now'. + +## Example Scenario + +Let's assume we have an action called `TurnOnLight` that turns on your bedroom light when activated. Take the following conversation: +```plaintext +Human: Hello +AI: How can I assist you today? +Human: Please turn on the lights. +``` + +If the action is triggered via a function call, the bot may respond with: +```plaintext +AI: Sure! +BOT_ACTION_START: Running `action_turn_on_light` +``` +or it may run the action without saying anything. + +If we use a phrase trigger instead, we may do the following: +1. In our prompt, write "If the human asks to turn on the lights, say 'I will turn on the lights now' verbatim" +2. Configure `TurnOnLight` with "I will turn on the lights now" as its phrase trigger + +Then, the bot will respond with: +``` +AI: I will turn on the lights now. +BOT_ACTION_START: Running `action_turn_on_light` +``` \ No newline at end of file From dac505ae22a58dcd6f9fcbe729783df25cd8d376 Mon Sep 17 00:00:00 2001 From: Adnaan Sachidanandan Date: Mon, 10 Jun 2024 16:31:08 -0700 Subject: [PATCH 14/25] [docs sprint] update open source quickstarts (#15) --- Makefile | 6 + docs/mint.json | 1 - docs/open-source/agent-factory.mdx | 25 +- docs/open-source/language-support.mdx | 7 +- docs/open-source/playground.mdx | 11 +- docs/open-source/tracing.mdx | 95 ---- docs/open-source/turn-based-conversation.mdx | 73 ++- playground/streaming/benchmark.py | 535 ------------------- pyproject.toml | 3 +- 9 files changed, 69 insertions(+), 687 deletions(-) delete mode 100644 docs/open-source/tracing.mdx delete mode 100644 playground/streaming/benchmark.py diff --git a/Makefile b/Makefile index b58788087..c7dcc8ccf 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,12 @@ transcribe: synthesize: poetry run python playground/streaming/synthesizer/synthesize.py +turn_based_conversation: + poetry run python quickstarts/turn_based_conversation.py + +streaming_conversation: + poetry run python quickstarts/streaming_conversation.py + PYTHON_FILES=. lint: PYTHON_FILES=vocode/ quickstarts/ playground/ lint_diff typecheck_diff: PYTHON_FILES=$(shell git diff --name-only --diff-filter=d main | grep -E '\.py$$') diff --git a/docs/mint.json b/docs/mint.json index 13a12f59f..84b1ab4ad 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -80,7 +80,6 @@ "open-source/playground", "open-source/turn-based-conversation", "open-source/language-support", - "open-source/tracing", "open-source/agent-factory" ] }, diff --git a/docs/open-source/agent-factory.mdx b/docs/open-source/agent-factory.mdx index 7b0c25d7c..58b17af18 100644 --- a/docs/open-source/agent-factory.mdx +++ b/docs/open-source/agent-factory.mdx @@ -5,18 +5,18 @@ description: 'How to link a custom agent to your app' # Agent Factories -Agent factories specify which agents are available to your app. In order to connect an agent to your app, you must first define an agent factory. To do so, subclass the [`AgentFactory`](https://github.com/vocodedev/vocode-python/blob/main/vocode/streaming/agent/factory.py) class to specify how agents are created. Here you can import and use your own custom agents. +Agent factories specify which agents are available to your app. In order to connect an agent to your app, you must first define an agent factory. To do so, subclass the [`AbstractAgentFactory`](https://github.com/vocodedev/vocode-python/blob/main/vocode/streaming/agent/abstract_factory.py) class to specify how agents are created. Here you can import and use your own custom agents. ## Example -First define your `AgentFactory`: +First define your `AgentFactory`. In this example, we are creating a factory for a new type of agent called MyActionAgent: ```python -from vocode.streaming.agent.factory import AgentFactory +from vocode.streaming.agent.abstract_factory import AbstractAgentFactory +from vocode.streaming.action.my_action_factory import MyActionFactory -class MyAgentFactory(AgentFactory): - def __init__(self, agent_config: AgentConfig, action_factory: MyActionFactory): - self.agent_config = agent_config +class MyAgentFactory(AbstractAgentFactory): + def __init__(self, action_factory: MyActionFactory): self.action_factory = action_factory def create_agent( @@ -24,19 +24,24 @@ class MyAgentFactory(AgentFactory): ) -> BaseAgent: if agent_config.type == "MY_ACTION": return MyActionAgent( - agent_config=typing.cast(ActionAgentConfig, self.agent_config), + agent_config=agent_config, action_factory=self.action_factory ) - raise Exception("Invalid agent config") + elif agent_config.type == "other_agent_type": + ... + else: + raise Exception("Invalid agent config") ``` Then, in your app, you can connect the agent to the app: ```python +from vocode.streaming.telephony.server.base import TelephonyServer +from vocode.streaming.agent.my_agent_factory import MyAgentFactory +from vocode.streaming.action.my_action_factory import MyActionFactory telephony_server = TelephonyServer( - agent_factory=MyAgentFactory( - agent_config=agent_config, action_factory=action_factory), + agent_factory=MyAgentFactory(action_factory=MyActionFactory()) ... ) ``` diff --git a/docs/open-source/language-support.mdx b/docs/open-source/language-support.mdx index 694887fb6..004c5f089 100644 --- a/docs/open-source/language-support.mdx +++ b/docs/open-source/language-support.mdx @@ -22,11 +22,9 @@ synthesizer_config = AzureSynthesizerConfig( ) ``` -See the [full list of supported voices](https://docs.microsoft.com/en-us/azure/cognitive-services/speech-service/language-support?tabs=tts). - ## Transcription -The transcriber used in vocode is also configurable. By default, `DeepgramTranscriber` is used which supports [over 25 languages](https://developers.deepgram.com/docs/languages-overview). +The transcriber used in vocode is also configurable. By default, `DeepgramTranscriber` is used which supports [over 35 languages](https://developers.deepgram.com/docs/languages-overview). To configure a different language model, modify the language code passed to `TranscriberConfig` when initializing the config object (`en-US` is the default): @@ -35,10 +33,11 @@ from vocode.streaming.models.transcriber import DeepgramTranscriberConfig transcriber_config = DeepgramTranscriberConfig( language="es" # Spanish + model="nova-2" # Most languages are supported on the Nova 2 model ) ``` -See the [Deepgram docs](https://developers.deepgram.com/docs/languages-overview) for the list of supported lamguages. +***Note: the default model for Deepgram is Nova, so you must pass `model="nova-2"` to use that model.*** Other transcription services like Google Cloud Speech or Assembly AI could also be used by configuring the appropriate `TranscriberConfig`. diff --git a/docs/open-source/playground.mdx b/docs/open-source/playground.mdx index 662e8f97e..f6acb2da9 100644 --- a/docs/open-source/playground.mdx +++ b/docs/open-source/playground.mdx @@ -8,6 +8,11 @@ test transcribers, agents, and synthesizers. To begin, clone the [repo](https://github.com/vocodedev/vocode-python). +Install the core packages by running the following: +``` +poetry install +``` + # Streaming ## Transcriber @@ -32,9 +37,11 @@ make chat ## Synthesizer -1. Update your synthesizer configuration in `playground/streaming/synthesizer/synthesize.py` +1. Install the synthesizer packages by running `poetry install --extras=synthesizers` + +2. Update your synthesizer configuration in `playground/streaming/synthesizer/synthesize.py` -2. Run the following script to synthesize text to speech and play it to your speaker: +3. Run the following script to synthesize text to speech and play it to your speaker: ``` make synthesize diff --git a/docs/open-source/tracing.mdx b/docs/open-source/tracing.mdx deleted file mode 100644 index 537e32885..000000000 --- a/docs/open-source/tracing.mdx +++ /dev/null @@ -1,95 +0,0 @@ ---- -title: "Tracing" -description: "Time components of your Vocode conversations" ---- - -# [Beta] Benchmarking script - -The benchmarking script is located at `playground/streaming/benchmark.py`. You can execute the benchmarking script using the CLI which will enable you to evaluate and compare -transcribers, agents, and synthesizers. You can use it primarily to benchmark latency – but it can also be used to compare the quality of the different providers as well. The -feature is in Beta and will continue to be improved upon – feel free to open an issue with any ideas. - -### Using the CLI - -To access the options of the benchmarking script, run - -```bash -python playground/streaming/benchmark.py --help -``` - -This will display all available options. - -To conduct multiple trials and get averaged results, you can control `num_cycles` - -```bash ---{transcriber,agent,synthesizer}_num_cycles 3 # component specific ---all_num_cycles 3 # all components -``` - -To perform a comprehensive test across all supported transcribers, agents, and synthesizers, use the `--all` command. - -With the CLI, you can get the raw output, write them to a file, and create graphs. -To access your results and visualize them, they will be stored in the `benchmark_results` directory by default. You can also change this location using the `--results_dir` and `--results_file` options. If you want to create visual graphs, add the `--create_graphs` option when running your test. - -#### Example: comparing synthesizers - -To compare different synthesizers, use the `--synthesizers` flag followed by the names of the synthesizers you wish to compare. For instance, - -```bash -python playground/streaming/benchmark.py --synthesizers Google Azure --synthesizer_text "Your text here" -``` - -#### Example: comparing transcribers - -To compare different transcribers, you can use the `--transcribers` flag followed by the names of the transcribers you wish to compare. For example, - -```bash -python playground/streaming/benchmark.py --transcribers deepgram assemblyai --transcriber_audio sample.wav -``` - -You can specify `transcriber_use_mic` instead of `--transcriber_audio` to use your microphone as the audio source. - -#### Example: comparing agents - -To compare different agents, use the `--agents` flag followed by the names of the agents you want to compare. For example, - -```bash -python playground/streaming/benchmark.py --agents openai anthropic -``` - -You can set the prompt preamble with the `--agent_prompt_preamble` argument and the first input with the `--agent_first_input` option. - -# Tracing your application - -At the top of `quickstarts/streaming_conversation.py`, include the following code: - -```python -from opentelemetry import trace -from opentelemetry.sdk.trace import TracerProvider -from opentelemetry.sdk.trace.export import SimpleSpanProcessor, SpanExporter -from opentelemetry.sdk.resources import Resource - - -class PrintDurationSpanExporter(SpanExporter): - def __init__(self): - super().__init__() - self.spans = defaultdict(list) - - def export(self, spans): - for span in spans: - duration_ns = span.end_time - span.start_time - duration_s = duration_ns / 1e9 - self.spans[span.name].append(duration_s) - - def shutdown(self): - for name, durations in self.spans.items(): - print(f"{name}: {sum(durations) / len(durations)}") - - -trace.set_tracer_provider(TracerProvider(resource=Resource.create({}))) -trace.get_tracer_provider().add_span_processor( - SimpleSpanProcessor(PrintDurationSpanExporter()) -) -``` - -This will print out stats about the conversation after it ends. diff --git a/docs/open-source/turn-based-conversation.mdx b/docs/open-source/turn-based-conversation.mdx index 18177ba93..d2e6a03e3 100644 --- a/docs/open-source/turn-based-conversation.mdx +++ b/docs/open-source/turn-based-conversation.mdx @@ -9,55 +9,64 @@ A turn-based conversation is a communication system designed for applications wh This model differs from streaming conversations that try to mimic natural human discourse. Instead, it fits applications triggered by some kind of user input. For example, consider a voice memo application where the user records a message, and the agent generates a complete response. -A turn-based conversation system is perfect for applications that don't require real-time responses or constant back-and-forths. -This design reduces complexity and allows for a more controlled conversation flow. Each user input is treated as a discrete event, +A turn-based conversation system is perfect for applications that don't require interruptions and have a controlled conversation flow. Each user input is treated as a discrete event, giving the system time to generate and deliver a full and meaningful response. ## Turn-based quickstart -The code can be found [here](https://github.com/vocodedev/vocode-python/blob/main/quickstarts/turn_based_conversation.py) +The example below demonstrates a turn-based conversation, using a ChatGPT agent for text generation, WhisperTranscriber for speech-to-text, +and AzureSynthesizer for text-to-speech. User interactions trigger the beginning and end of the recording, signaling the system when to listen and when to respond. You can run it with +``` +make turn_based_conversation +``` -```python -import logging -from dotenv import load_dotenv -from vocode import getenv -from vocode.helpers import create_turn_based_microphone_input_and_speaker_output -from vocode.turn_based.agent.chat_gpt_agent import ChatGPTAgent -from vocode.turn_based.synthesizer.azure_synthesizer import AzureSynthesizer -from vocode.turn_based.synthesizer.eleven_labs_synthesizer import ElevenLabsSynthesizer -from vocode.turn_based.transcriber.whisper_transcriber import WhisperTranscriber -from vocode.turn_based.turn_based_conversation import TurnBasedConversation +*Remember to replace OPENAI_API_KEY and AZURE_SPEECH_KEY with your actual API keys and set the appropriate Azure region. You can also set these variables in a `.env` file and source it in your terminal. +You can also customize the voice, system prompt, and initial message as needed. The code can be found [here](https://github.com/vocodedev/vocode-python/blob/main/quickstarts/turn_based_conversation.py).* -logging.basicConfig() -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) +```python +class Settings(BaseSettings): + """ + Settings for the turn-based conversation quickstart. + These parameters can be configured with environment variables. + """ + + openai_api_key: str = "ENTER_YOUR_OPENAI_API_KEY_HERE" + azure_speech_key: str = "ENTER_YOUR_AZURE_KEY_HERE" + + azure_speech_region: str = "eastus" + + # This means a .env file can be used to overload these settings + # ex: "OPENAI_API_KEY=my_key" will set openai_api_key over the default above + model_config = SettingsConfigDict( + env_file=".env", + env_file_encoding="utf-8", + ) -load_dotenv() -# See https://api.elevenlabs.io/v1/voices -ADAM_VOICE_ID = "pNInz6obpgDQGcFmaJgB" +settings = Settings() if __name__ == "__main__": ( microphone_input, speaker_output, - ) = create_turn_based_microphone_input_and_speaker_output(use_default_devices=False) + ) = create_turn_based_microphone_input_and_speaker_output( + use_default_devices=False, + ) conversation = TurnBasedConversation( input_device=microphone_input, output_device=speaker_output, - transcriber=WhisperTranscriber(api_key=getenv("OPENAI_API_KEY")), + transcriber=WhisperTranscriber(api_key=settings.openai_api_key), agent=ChatGPTAgent( system_prompt="The AI is having a pleasant conversation about life", initial_message="Hello!", - api_key=getenv("OPENAI_API_KEY"), + api_key=settings.openai_api_key, ), synthesizer=AzureSynthesizer( - api_key=getenv("AZURE_SPEECH_KEY"), - region=getenv("AZURE_SPEECH_REGION"), + api_key=settings.azure_speech_key, + region=settings.azure_speech_region, voice_name="en-US-SteffanNeural", ), - logger=logger, ) print("Starting conversation. Press Ctrl+C to exit.") while True: @@ -68,16 +77,4 @@ if __name__ == "__main__": conversation.end_speech_and_respond() except KeyboardInterrupt: break -``` - -This example demonstrates a turn-based conversation, using a ChatGPT agent for text generation, WhisperTranscriber for speech-to-text, -and AzureSynthesizer for text-to-speech. User interactions trigger the beginning and end of the recording, signaling the system when to listen and when to respond. - -Remember to replace OPENAI_API_KEY and AZURE_SPEECH_KEY with your actual API keys and set the appropriate Azure region. -You can also customize the voice, system prompt, and initial message as needed. - -## React turn-based quickstart - -🚧 Under construction - -If you want to work on a sample react app for this, reach out to us! +``` \ No newline at end of file diff --git a/playground/streaming/benchmark.py b/playground/streaming/benchmark.py deleted file mode 100644 index 26b2dbf97..000000000 --- a/playground/streaming/benchmark.py +++ /dev/null @@ -1,535 +0,0 @@ -raise DeprecationWarning("This playground script is deprecated and will be removed in the future.") - -import argparse -import asyncio -import json -import os -from collections import defaultdict - -import sounddevice as sd -from loguru import logger -from opentelemetry import metrics, trace -from opentelemetry.sdk.metrics import MeterProvider -from opentelemetry.sdk.metrics.export import InMemoryMetricReader -from opentelemetry.sdk.resources import Resource -from opentelemetry.sdk.trace import TracerProvider -from opentelemetry.sdk.trace.export import SimpleSpanProcessor -from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter -from playground.streaming.tracing_utils import get_final_metrics -from tqdm import tqdm - -from vocode.streaming.agent import ChatGPTAgent -from vocode.streaming.agent.base_agent import TranscriptionAgentInput -from vocode.streaming.input_device.file_input_device import FileInputDevice -from vocode.streaming.input_device.microphone_input import MicrophoneInput -from vocode.streaming.models.agent import AzureOpenAIConfig, ChatGPTAgentConfig -from vocode.streaming.models.message import BaseMessage -from vocode.streaming.models.synthesizer import ( # BarkSynthesizerConfig,; CoquiSynthesizerConfig,; CoquiTTSSynthesizerConfig, - AzureSynthesizerConfig, - ElevenLabsSynthesizerConfig, - PlayHtSynthesizerConfig, - RimeSynthesizerConfig, -) -from vocode.streaming.models.transcriber import ( - AssemblyAITranscriberConfig, - DeepgramTranscriberConfig, - PunctuationEndpointingConfig, - Transcription, -) -from vocode.streaming.models.transcript import Transcript -from vocode.streaming.output_device.file_output_device import FileOutputDevice -from vocode.streaming.synthesizer.azure_synthesizer import AzureSynthesizer -from vocode.streaming.synthesizer.eleven_labs_websocket_synthesizer import ElevenLabsWSSynthesizer -from vocode.streaming.synthesizer.elevenlabs_synthesizer import ElevenLabsSynthesizer -from vocode.streaming.synthesizer.play_ht_synthesizer import PlayHtSynthesizer -from vocode.streaming.synthesizer.play_ht_synthesizer_v2 import PlayHtSynthesizerV2 -from vocode.streaming.synthesizer.rime_synthesizer import RimeSynthesizer -from vocode.streaming.transcriber.assembly_ai_transcriber import AssemblyAITranscriber -from vocode.streaming.transcriber.deepgram_transcriber import DeepgramTranscriber -from vocode.streaming.utils import get_chunk_size_per_second, remove_non_letters_digits - -tracer = trace.get_tracer(__name__) -meter = metrics.get_meter(__name__) - - -# Create the parser -parser = argparse.ArgumentParser( - description="Benchmark Vocode's transcribers, agents, and synthesizers.\n" - + "Example usage: python playground/streaming/benchmark.py --all --all_num_cycles 3 --create_graphs", -) - -synthesizer_classes = { - "elevenlabs": (ElevenLabsSynthesizer, ElevenLabsSynthesizerConfig), - "elevenlabsws": (ElevenLabsWSSynthesizer, ElevenLabsSynthesizerConfig), - "azure": (AzureSynthesizer, AzureSynthesizerConfig), - # "bark": (BarkSynthesizer, BarkSynthesizerConfig), - # "coqui": (CoquiSynthesizer, CoquiSynthesizerConfig), - # "coquitts": (CoquiTTSSynthesizer, CoquiTTSSynthesizerConfig), - # "google": (GoogleSynthesizer, GoogleSynthesizerConfig), - # "gtts": (GTTSSynthesizer, GTTSSynthesizerConfig), - "playht": (PlayHtSynthesizer, PlayHtSynthesizerConfig), - "playht2": (PlayHtSynthesizerV2, PlayHtSynthesizerConfig), - "rime": (RimeSynthesizer, RimeSynthesizerConfig), - # "streamelements": (StreamElementsSynthesizer, StreamElementsSynthesizerConfig), -} - - -# These synthesizers stream output so they need to be traced within this file. -STREAMING_SYNTHESIZERS = ["azure", "elevenlabs", "playht2", "elevenlabsws"] - - -TRANSCRIBER_CHOICES = ["deepgram", "assemblyai"] -AGENT_CHOICES = [ - "gpt_gpt-3.5-turbo", - "gpt_gpt-4", - "azuregpt_gpt-35-turbo", -] -SYNTHESIZER_CHOICES = list(synthesizer_classes) - -parser.add_argument( - "--transcribers", - type=str, - nargs="*", - default=[], - choices=TRANSCRIBER_CHOICES + ["all"], - help="The list of transcribers to benchmark", -) -parser.add_argument( - "--agents", - type=str, - nargs="*", - default=[], - choices=AGENT_CHOICES + ["all"], - help="The list of agents to benchmark. Each agent should be of the form _.", -) -parser.add_argument( - "--synthesizers", - type=str, - nargs="*", - default=[], - choices=SYNTHESIZER_CHOICES + ["all"], - help="The list of synthesizers to benchmark", -) -parser.add_argument( - "--transcriber_audio", - type=str, - default=f"{os.path.join(os.path.dirname(os.path.realpath(__file__)), 'test.wav')}", - help="Path to the audio file to transcribe", -) -parser.add_argument( - "--transcriber_use_mic", - action="store_true", - help="Use the microphone as the input device for the transcriber. " - + "Overrides --transcriber_audio. Be silent for ≈5 seconds to end transcription.", -) -parser.add_argument( - "--synthesizer_text", - type=str, - default="Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, “and what is the use of a book,” thought Alice “without pictures or conversations?”", - help="The text for synthesizers to synthesize", -) -parser.add_argument( - "--agent_prompt_preamble", - type=str, - default="The AI is having a very short and pleasant conversation about life", - help="The prompt preamble to use for the agent", -) -parser.add_argument( - "--agent_first_input", - type=str, - default="What is the meaning of life?", - help="The initial message sent to the agent (this is a transcribed sentence that the agent should respond to).", -) -parser.add_argument( - "--no_generate_responses", - action="store_true", - help="Disable streaming generated responses for agents", -) -parser.add_argument( - "--transcriber_num_cycles", - type=int, - default=1, - help="The number of transcriber runs to perform. Results are averaged over the runs.", -) -parser.add_argument( - "--synthesizer_num_cycles", - type=int, - default=1, - help="The number of synthesizer runs to perform. Results are averaged over the runs.", -) -parser.add_argument( - "--all_num_cycles", - type=int, - default=None, - help="The number of transcriber, agent, and synthesizer runs to perform. Overrides all other num_cycle arguments.", -) -parser.add_argument( - "--agent_num_cycles", - type=int, - default=1, - help="The number of agent runs to perform. Results are averaged over the runs.", -) -parser.add_argument( - "--all", - action="store_true", - help="Run all supported transcribers, agents, and synthesizers. Ignores other arguments.", -) -parser.add_argument( - "--create_graphs", - action="store_true", - help="Create graphs from the benchmark results. Requires matplotlib.", -) -parser.add_argument( - "--just_graphs", - action="store_true", - help="Skips computing statistics. Loads the last saved benchmark result " - + "JSON file and creates graphs from it.", -) -parser.add_argument( - "--results_file", - type=str, - default="benchmark_results.json", - help="The file to save the benchmark JSON results to", -) -parser.add_argument( - "--results_dir", - type=str, - default="benchmark_results", - help="The directory to save the text-to-speech output and JSON results to", -) -args = parser.parse_args() -if args.all: - print("--all is set! Running all supported transcribers, agents, and synthesizers.") - args.transcribers = TRANSCRIBER_CHOICES - args.agents = AGENT_CHOICES - args.synthesizers = SYNTHESIZER_CHOICES - -if "all" in args.transcribers: - args.transcribers = TRANSCRIBER_CHOICES -if "all" in args.agents: - args.agents = AGENT_CHOICES -if "all" in args.synthesizers: - args.synthesizers = SYNTHESIZER_CHOICES - -if args.all_num_cycles is not None: - args.transcriber_num_cycles = args.all_num_cycles - args.agent_num_cycles = args.all_num_cycles - args.synthesizer_num_cycles = args.all_num_cycles - -if args.create_graphs or args.just_graphs: - try: - import matplotlib.pyplot as plt - except ImportError: - print( - "ERROR: The --create_graphs flag requires matplotlib. Please " - + "install matplotlib and try again.", - ) - exit(1) - -if args.just_graphs: - print( - "--just_graphs is set! Skipping computing statistics and instead " - + "generating graphs from the last saved benchmark result JSON file.", - ) - -should_generate_responses = not args.no_generate_responses - -os.makedirs(args.results_dir, exist_ok=True) - - -def get_transcriber(transcriber_name, file_input): - if transcriber_name == "deepgram": - transcriber = DeepgramTranscriber( - DeepgramTranscriberConfig.from_input_device( - file_input, - endpointing_config=PunctuationEndpointingConfig(), - ), - ) - elif transcriber_name == "assemblyai": - transcriber = AssemblyAITranscriber( - AssemblyAITranscriberConfig.from_input_device( - file_input, - ), - ) - return transcriber - - -trace.set_tracer_provider(TracerProvider(resource=Resource.create({}))) -span_exporter = InMemorySpanExporter() -trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(span_exporter)) # type: ignore - -reader = InMemoryMetricReader() -provider = MeterProvider(metric_readers=[reader]) -metrics.set_meter_provider(provider) - - -async def run_agents(): - for agent_name in tqdm(args.agents, desc="Agents"): - company, model_name = agent_name.rsplit("_", 1) - length_meter = meter.create_counter( - remove_non_letters_digits(f"agent.agent_chat_{company}-{model_name}.total_characters"), - ) - for _ in tqdm(range(args.agent_num_cycles), desc="Agent Cycles"): - if company == "gpt": - agent = ChatGPTAgent( - ChatGPTAgentConfig( - initial_message=None, - prompt_preamble=args.agent_prompt_preamble, - allow_agent_to_be_cut_off=False, - model_name=model_name, - generate_responses=should_generate_responses, - ), - ) - elif company == "azuregpt": - agent = ChatGPTAgent( - ChatGPTAgentConfig( - initial_message=None, - prompt_preamble=args.agent_prompt_preamble, - allow_agent_to_be_cut_off=False, - azure_params=AzureOpenAIConfig(deployment_name=model_name), - generate_responses=should_generate_responses, - ), - ) - agent.attach_transcript(Transcript()) - agent_task = agent.start() # noqa: F841 - message = TranscriptionAgentInput( - transcription=Transcription( - message=args.agent_first_input, - confidence=1.0, - is_final=True, - ), - conversation_id=0, - ) - agent.consume_nonblocking( - agent.interruptible_event_factory.create_interruptible_event(message), - ) - - while True: - try: - message = await asyncio.wait_for(agent.output_queue.get(), timeout=15) - if isinstance(message.payload.message, BaseMessage): - length_meter.add(len(message.payload.message.text)) - logger.debug( - f"[Agent: {agent_name}] Response from API: {message.payload.message.text}", - ) - except asyncio.TimeoutError: - logger.debug(f"[Agent: {agent_name}] Agent queue is empty, stopping...") - break - - -async def run_synthesizers(): - def create_file_output_device(synthesizer_name, extra_info=""): - return FileOutputDevice( - os.path.join(args.results_dir, f"{synthesizer_name}{extra_info}.wav"), - ) - - for synthesizer_name in args.synthesizers: - file_output = create_file_output_device(synthesizer_name) - synthesizer_class, synthesizer_config_class = synthesizer_classes[synthesizer_name] - extra_config = {} - if synthesizer_name == "playht": - extra_config["voice_id"] = "larry" - elif synthesizer_name == "rime": - extra_config["speaker"] = "young_male-1" - elif synthesizer_name == "playht2": - extra_config["voice_id"] = ( - "s3://voice-cloning-zero-shot/d9ff78ba-d016-47f6-b0ef-dd630f59414e/female-cs/manifest.json" - ) - extra_config["version"] = "2" - elif synthesizer_name == "elevenlabs": - extra_config["experimental_streaming"] = True - elif synthesizer_name == "elevenlabsws": - extra_config["experimental_websocket"] = True - config = synthesizer_config_class.from_output_device(file_output, **extra_config) - synthesizer = synthesizer_class(config) - - chunk_size = 0.1 * get_chunk_size_per_second( - synthesizer.get_synthesizer_config().audio_encoding, - synthesizer.get_synthesizer_config().sampling_rate, - ) - - current_synthesizer_is_streaming = synthesizer_name in STREAMING_SYNTHESIZERS - for _ in tqdm( - range(args.synthesizer_num_cycles), - desc=f"Synthesizer Cycles ({synthesizer_name})", - ): - if current_synthesizer_is_streaming: - total_synthesis_span = tracer.start_span( - f"synthesizer.{synthesizer_name}.create_total", - ) - first_synthesis_span = tracer.start_span( - f"synthesizer.{synthesizer_name}.create_first", - ) - - try: - synthesis_result = await synthesizer.create_speech_uncached( - message=BaseMessage(text=args.synthesizer_text), - chunk_size=int(chunk_size), - ) - except asyncio.TimeoutError: - logger.error( - f"[Synthesizer: {synthesizer_name}] Timed out while synthesizing. Skipping {synthesizer_name}...", - ) - continue - except Exception as e: - logger.error( - f"[Synthesizer: {synthesizer_name}] Exception while synthesizing: {e}. Skipping {synthesizer_name}...", - ) - continue - chunk_generator = synthesis_result.chunk_generator - - with tqdm(desc=f"{synthesizer_name.title()} Synthesizing") as pbar: - first_chunk = True - while True: - pbar.update(1) - try: - chunk_result = await chunk_generator.__anext__() - if current_synthesizer_is_streaming and first_chunk: - first_chunk = False - first_synthesis_span.end() - file_output.consume_nonblocking(chunk_result.chunk) - except StopAsyncIteration: - break - if chunk_result.is_last_chunk: - break - - if current_synthesizer_is_streaming: - total_synthesis_span.end() - - await synthesizer.tear_down() - - -async def run_transcribers(): - sample_rate = 44100 - chunk_size = 2048 - sleep_time = chunk_size / sample_rate - if args.transcriber_use_mic: - input_device_info = sd.query_devices(kind="input") - input_device = MicrophoneInput(input_device_info) - else: - input_device = FileInputDevice( - args.transcriber_audio, - chunk_size=chunk_size, - silent_duration=0.01, - skip_initial_load=True, - ) - - for transcriber_cycle_idx in tqdm( - range(args.transcriber_num_cycles), - desc="Transcriber Cycles", - ): - for transcriber_name in tqdm(args.transcribers, desc="Transcribers"): - transcriber = get_transcriber(transcriber_name, input_device) - if not args.transcriber_use_mic: - input_device.load() - transcriber_task = transcriber.start() # noqa: F841 - - if args.transcriber_use_mic: - - async def record_audio_task(): - while True: - chunk = await input_device.get_audio() - transcriber.send_audio(chunk) - - send_audio = asyncio.create_task(record_audio_task()) - else: - - async def send_audio_task(): - while not input_device.is_done(): - chunk = await input_device.get_audio() - transcriber.send_audio(chunk) - await asyncio.sleep(sleep_time) - - send_audio = asyncio.create_task(send_audio_task()) - - # `get` from `transcriber.output_queue` until it's empty for 5 seconds - pbar = tqdm( - desc=f"{transcriber_name.title()} Transcribing", - total=input_device.duration if not args.transcriber_use_mic else None, - unit="chunk", - ) - while True: - try: - transcription = await asyncio.wait_for( # noqa: F841 - transcriber.output_queue.get(), - timeout=5, - ) - # update the progress bar status - pbar.update(round(transcriber.audio_cursor - pbar.n, 2)) - except asyncio.TimeoutError: - logger.debug( - f"[Transcriber: {transcriber_name}] Transcriber queue is empty, stopping transcription...", - ) - send_audio.cancel() - break - if not args.transcriber_use_mic: - pbar.update(pbar.total - pbar.n) - transcriber.terminate() - - -def create_graphs(final_results): - logger.info("Creating graphs from benchmark results...") - results_split = [] - for name, value in final_results.items(): - first_name = name.split(".", 1) - second_name = first_name[1].rsplit(".", 1) - results_split.append((first_name[0], *second_name, value)) - - graph_data = defaultdict(lambda: defaultdict(list)) - for category, name, metric, value in results_split: - graph_data[f"{category} - {metric}"]["labels"].append(name) - graph_data[f"{category} - {metric}"]["values"].append(value) - - graph_dir = os.path.join(args.results_dir, "graphs") - os.makedirs(graph_dir, exist_ok=True) - - for graph_title, data in graph_data.items(): - plt.title(graph_title) - plt.bar(data["labels"], data["values"]) - plt.xticks(rotation=45) - plt.tight_layout() - plt.savefig(os.path.join(graph_dir, f"{graph_title}.png")) - plt.clf() - - -async def main(): - result_file_path = os.path.join(args.results_dir, args.results_file) - if not args.just_graphs: - if args.agents: - await run_agents() - if args.transcribers: - await run_transcribers() - if args.synthesizers: - await run_synthesizers() - - trace_results = span_exporter.get_finished_spans() - final_spans = defaultdict(list) - for span in trace_results: - duration_ns = span.end_time - span.start_time - duration_s = duration_ns / 1e9 - final_spans[span.name].append(duration_s) - - scope_metrics = reader.get_metrics_data().resource_metrics[0].scope_metrics - final_metrics = get_final_metrics(scope_metrics, final_spans=final_spans) - - final_spans = {k: sum(v) / len(v) for k, v in final_spans.items() if len(v) > 0} - if len(scope_metrics) > 0: - final_results = {**final_spans, **final_metrics} - else: - final_results = final_spans - print(json.dumps(final_results, indent=4)) - if args.results_file: - with open(result_file_path, "w") as f: - json.dump(final_results, f, indent=4) - else: - with open(result_file_path, "r") as f: - final_results = json.load(f) - - if args.create_graphs or args.just_graphs: - create_graphs(final_results) - - print("Benchmarking complete!") - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/pyproject.toml b/pyproject.toml index fe9c29741..592d95b0d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,11 +33,11 @@ sounddevice = "^0.4.7" tiktoken = "^0.7.0" uvicorn = "^0.30.0" websockets = "^12.0" +nltk = "^3.8.1" # Synthesizers google-cloud-texttospeech = { version = "^2.16.3", optional = true } miniaudio = { version = "^1.59", optional = true } -nltk = { version = "^3.8.1", optional = true } pvkoala = { version = "^2.0.1", optional = true } pydub = { version = "^0.25.1", optional = true } @@ -79,7 +79,6 @@ pytest-mock = "^3.14.0" synthesizers = [ "google-cloud-texttospeech", "miniaudio", - "nltk", "pvkoala", "pydub", ] From ddfd6dc6d48c8fdab5178f9c67636353f30249a6 Mon Sep 17 00:00:00 2001 From: Mac Wilkinson Date: Mon, 10 Jun 2024 19:36:07 -0700 Subject: [PATCH 15/25] [docs sprint] Add Documentation on Using Vocode's Loguru Implementation (#19) * [docs sprint] Add Documentation on Using Vocode's Loguru Implementation * Remove Tracing --------- Co-authored-by: srhinos <6531393+srhinos@users.noreply.github.com> --- docs/mint.json | 1 + docs/open-source/logging-with-loguru.mdx | 73 ++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 docs/open-source/logging-with-loguru.mdx diff --git a/docs/mint.json b/docs/mint.json index 84b1ab4ad..ecb65113d 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -80,6 +80,7 @@ "open-source/playground", "open-source/turn-based-conversation", "open-source/language-support", + "open-source/logging-with-loguru", "open-source/agent-factory" ] }, diff --git a/docs/open-source/logging-with-loguru.mdx b/docs/open-source/logging-with-loguru.mdx new file mode 100644 index 000000000..4205468e1 --- /dev/null +++ b/docs/open-source/logging-with-loguru.mdx @@ -0,0 +1,73 @@ +--- +title: "Logging with Loguru" +description: "Make logging set up less painful for local and production usage!" +--- + +Loguru is a powerful and flexible logging library for Python that simplifies logging setup and usage. It provides a more intuitive and feature-rich alternative to Python's built-in logging module. + +## Why Use Loguru? + +Loguru offers several advantages over the standard logging module: + +- **Ease of Use**: Loguru simplifies the process of setting up and using loggers. +- **Rich Features**: It provides advanced features like automatic exception catching, structured logging, and more. +- **Flexibility**: Loguru allows for easy configuration of different logging formats and destinations. + +## Using the Vocode Implementation + +The Vocode implementation of Loguru provides a seamless way to integrate logging into your application. It includes custom handlers and configuration functions to streamline the setup process. When utilizing the JSON logging configuration, it'll also pull relevant environment variables such as `conversation_id` and include them in the JSON output for better production debugging! + +### Setting Up Logging + +To set up logging in your application, you can use the provided configuration functions. Here's how to configure pretty printing for local development and JSON logging for production: + +#### Pretty Printing Locally + +To enable pretty printing locally, use the `configure_pretty_logging` function. This will set up Loguru to output logs with colored formatting, making them easier to read during development. + +```python +from vocode.logging import configure_pretty_logging + +configure_pretty_logging() +``` + +#### JSON Logging in Production + +For production environments, you may want to log in JSON format for better integration with logging systems and easier parsing. Use the `configure_json_logging` function to set this up. + +```python +from vocode.logging import configure_json_logging + +configure_json_logging() +``` + +### Why Use Different Setups? + +Using different logging setups for local and production environments can be beneficial for several reasons: + +- **Readability**: Pretty printing makes logs easier to read during development, helping you quickly identify issues. +- **Structured Logging**: JSON logging provides structured logs that are easier to parse and analyze in production, especially when using log aggregation and monitoring tools. + +## Example Snippet + +Here's an example of how you can set up logging in your application: + +```python +import os +from vocode.logging import configure_pretty_logging, configure_json_logging + +DEPLOYED_ENVIRONMENTS = ["production", "staging"] +ENVIRONMENT = os.environ.get("ENVIRONMENT", "development") + +def configure_logging() -> None: # pragma: no cover + """Configures logging.""" + if ENVIRONMENT in DEPLOYED_ENVIRONMENTS: + configure_json_logging() + else: + configure_pretty_logging() + +# Configure logging based on the environment +configure_logging() + +# Your application code here +``` From 45b37491ede8d5979320fe2f8d37a086d267f6d1 Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Wed, 12 Jun 2024 13:03:57 -0700 Subject: [PATCH 16/25] [docs sprint] Updates docs for using synthesizers (#8) * [docs sprint] using synthesizers docs update * update docs for elevenlabs ws * Apply suggestions from code review Co-authored-by: Adnaan Sachidanandan --------- Co-authored-by: Adnaan Sachidanandan --- docs/open-source/using-synthesizers.mdx | 64 ++++++++++++++++--------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/docs/open-source/using-synthesizers.mdx b/docs/open-source/using-synthesizers.mdx index 99c51eaee..013ce2372 100644 --- a/docs/open-source/using-synthesizers.mdx +++ b/docs/open-source/using-synthesizers.mdx @@ -16,10 +16,10 @@ Vocode currently supports the following synthesizers: 3. Eleven Labs 4. Rime 5. Play.ht -6. Coqui TTS -7. GTTS (Google Text-to-Speech) -8. Stream Elements -9. Bark +6. GTTS (Google Text-to-Speech) +7. Stream Elements +8. Bark +9. Amazon Polly These synthesizers are defined using their respective configuration classes, which are subclasses of the `SynthesizerConfig` class. @@ -46,6 +46,43 @@ server = InboundCallServer( In this example, the `ElevenLabsSynthesizerConfig.from_telephone_output_device()` method is used to create a configuration object for the Eleven Labs synthesizer. The method hardcodes some values like the `sampling_rate` and `audio_encoding` for compatibility with telephone output devices. +#### ElevenLabs Input Streaming + +You can try out our experimental implementation of ElevenLabs' [input streaming API](https://elevenlabs.io/docs/api-reference/websockets) by passing in `experimental_websocket=True` into the config and using the `ElevenLabsWSSynthesizer`, like: + +```python +from vocode.streaming.synthesizer.eleven_labs_websocket_synthesizer import ElevenLabsWSSynthesizer +from vocode.streaming.models.synthesizer import ElevenLabsSynthesizerConfig + +... +synthesizer_config=ElevenLabsSynthesizerConfig.from_telephone_output_device( + api_key=os.getenv("ELEVENLABS_API_KEY"), + voice_id=os.getenv("YOUR VOICE ID"), + experimental_websocket=True +) +... +synthesizer=ElevenLabsWSSynthesizer(ElevenLabsSynthesizerConfig.from_output_device( + speaker_output, + api_key=os.getenv("ELEVENLABS_API_KEY"), + voice_id=os.getenv("YOUR VOICE ID"), + experimental_websocket=True +)) +... +``` + +#### Play.ht v2 + +We now support Play.ht's new [gRPC streaming API](https://docs.play.ht/reference/python-sdk-audio-streaming), which runs much faster than their HTTP API and is designed for realtime communication. + +```python +... +synthesizer_config=PlayHtSynthesizerConfig.from_telephone_output_device( + api_key=os.getenv("PLAY_HT_API_KEY"), + user_id=os.getenv("PLAY_HT_USER_ID"), +) +... +``` + ### Example 2: Using Azure in StreamingConversation locally ```python @@ -67,22 +104,3 @@ conversation = StreamingConversation( In this example, the `AzureSynthesizerConfig.from_output_device()` method is used to create a configuration object for the Azure synthesizer. The method takes a `speaker_output` object as an argument, and extracts the `sampling_rate` and `audio_encoding` from the output device. - -## When to Use Configs vs. Synthesizer Objects - -- For everything except `StreamingConversation`, you must use configuration objects. -- For `StreamingConversation`, you can use the actual synthesizer object, but you still need to initialize it with a configuration object. - -## Synthesizer Comparisons - -| Provider | Latency | Voice Cloning | Natural Sounding | Notes | -| ----------------- | ------- | ------------- | ---------------- | ----------- | -| Azure (Microsoft) | Low | No | | | -| Google | Low | No | | | -| Eleven Labs | High | Yes | | | -| Rime | Low | No | | | -| Play.ht | High | Yes | | | -| Coqui TTS | | | | Open source | -| GTTS | | | | | -| Stream Elements | | | | | -| Bark | | | | | From 67eaf1fe34326a00c7dc3ab14a420367407fdd48 Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Wed, 12 Jun 2024 13:04:08 -0700 Subject: [PATCH 17/25] [docs sprint] Updates docs for react quickstart (#10) * [docs sprint] Updates docs for react quickstart * PR feedback --- docs/open-source/react-quickstart.mdx | 40 ++++++++++----------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/docs/open-source/react-quickstart.mdx b/docs/open-source/react-quickstart.mdx index 1b3a7372d..08f89cf6e 100644 --- a/docs/open-source/react-quickstart.mdx +++ b/docs/open-source/react-quickstart.mdx @@ -13,7 +13,7 @@ Or, start from our [Replit template](https://replit.com/@vocode/Simple-Conversat ## Setting up the conversation -Our self-hosted backend allows you to expose a websocket route in the same format that our hosted backend does. This allows you to deploy any agent you'd like into the conversation. +Our self-hosted backend allows you to expose a websocket route that operates like `StreamingConversation`. To get started, clone the Vocode repo or copy the [client backend app](https://github.com/vocodedev/vocode-python/tree/main/apps/client_backend) directory. @@ -56,35 +56,25 @@ uvicorn main:app --port 3000 You now have a server with a Vocode websocket route at localhost:3000! You can now use the `useConversation` hook with your self-hosted backend as follows: -```javascript -const { status, start, stop, analyserNode } = useConversation({ +```typescript +import { useConversation } from "vocode"; + +const { status, start, stop, error, analyserNode } = useConversation({ backendUrl: "", // looks like ws://localhost:3000/conversation or wss://asdf1234.ngrok.app/conversation if using ngrok audioDeviceConfig: {}, }); ``` -# Demo installation and setup - -Clone the `vocode-react-demo` [repository](https://github.com/vocodedev/vocode-react-demo). - -``` -$ git clone https://github.com/vocodedev/vocode-react-demo.git -``` - -Run npm install inside the directory to download all of the dependencies. - -``` -$ npm install -``` - -Set your Client SDK key inside of your `.env` +Use the `status`, `start`, and `stop` objects within your React components to control conversations with your self-hosted backend, e.g. -``` -REACT_APP_VOCODE_API_KEY=YOUR KEY HERE -``` - -Start the application +```jsx +<> + {status === "idle" &&

Press me to talk!

} + {status == "error" && error &&

{error.message}

} -``` -$ npm start + + ``` From 508a472610f4f75b08140c32f0ef05c278808357 Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Wed, 12 Jun 2024 13:06:25 -0700 Subject: [PATCH 18/25] changes azure to override create_speech_uncached (#21) --- vocode/streaming/synthesizer/azure_synthesizer.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/vocode/streaming/synthesizer/azure_synthesizer.py b/vocode/streaming/synthesizer/azure_synthesizer.py index 7c9b60033..f2aaf2122 100644 --- a/vocode/streaming/synthesizer/azure_synthesizer.py +++ b/vocode/streaming/synthesizer/azure_synthesizer.py @@ -229,7 +229,7 @@ def get_message_up_to( return ssml_fragment.split(">")[-1] return message - async def create_speech( + async def create_speech_uncached( self, message: BaseMessage, chunk_size: int, @@ -294,5 +294,3 @@ async def chunk_generator( message.text, ssml, seconds, word_boundary_event_pool ), ) - - create_speech_uncached = create_speech From 0af160710be45101e71c611e0d615fccbce6441d Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Wed, 12 Jun 2024 13:10:58 -0700 Subject: [PATCH 19/25] [docs sprint] Adds docs for conversation mechanics and moves endpointing docs from transcribers (#11) * [docs sprint] Updates docs for using transcribers * Adds docs for conversation mechanics and moves endpointing docs from transcribers * Update docs/open-source/conversation-mechanics.md Co-authored-by: Adnaan Sachidanandan * use mdx * PR feedback --------- Co-authored-by: Adnaan Sachidanandan --- docs/mint.json | 1 + docs/open-source/conversation-mechanics.mdx | 53 +++++++++++++++++++++ docs/open-source/using-transcribers.mdx | 24 +--------- 3 files changed, 55 insertions(+), 23 deletions(-) create mode 100644 docs/open-source/conversation-mechanics.mdx diff --git a/docs/mint.json b/docs/mint.json index ecb65113d..f3f7a19d1 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -69,6 +69,7 @@ "open-source/python-quickstart", "open-source/telephony", "open-source/create-your-own-agent", + "open-source/conversation-mechanics", "open-source/langchain-agent", "open-source/action-agents", "open-source/action-phrase-triggers", diff --git a/docs/open-source/conversation-mechanics.mdx b/docs/open-source/conversation-mechanics.mdx new file mode 100644 index 000000000..513eef503 --- /dev/null +++ b/docs/open-source/conversation-mechanics.mdx @@ -0,0 +1,53 @@ +--- +title: "Conversation Mechanics" +description: "How to tune the responsiveness in Vocode conversations" +--- + +Building two-way conversations with an AI is a highly use-case specific task - how realistic the conversation is depends greatly on the nature of the conversation itself. In this guide, we'll cover some of the dials you can turn to configure the mechanics of a conversation in Vocode. + +# Endpointing + +Endpointing is the process of understanding when someone has finished speaking. The `EndpointingConfig` controls how this is done. There are a couple of different ways to configure endpointing: + +We provide `DeepgramEndpointingConfig()` which has some reasonable defaults and knobs to suit most use-cases (but only works with the Deepgram transcriber). + +``` +class DeepgramEndpointingConfig(EndpointingConfig, type="deepgram"): # type: ignore + vad_threshold_ms: int = 500 + utterance_cutoff_ms: int = 1000 + time_silent_config: Optional[TimeSilentConfig] = Field(default_factory=TimeSilentConfig) + use_single_utterance_endpointing_for_first_utterance: bool = False +``` + +- `vad_threshold_ms`: translates to [Deepgram's `endpointing` feature](https://developers.deepgram.com/docs/endpointing#enable-feature) +- `utterance_cutoff_ms`: uses [Deepgram's Utterance End features](https://developers.deepgram.com/docs/utterance-end) +- `time_silent_config`: is a Vocode specific parameter that marks an utterance final if we haven't seen any new words in X seconds +- `use_single_utterance_endpointing_for_first_utterance`: Uses `is_final` instead of `speech_final` for endpointing for the first utterance (works really well for outbound conversations, where the user's first utterance is something like "Hello?") - see [this doc on Deepgram](https://developers.deepgram.com/docs/understand-endpointing-interim-results) for more info. + +Endpointing is highly use-case specific - building a realistic experience for this greatly depends on the person speaking to the AI. Here are few paradigms that we've used to help you along the way: + +- Time-based endpointing: This method considers the speaker to be finished when there is a certain duration of silence. +- Punctuation-based endpointing: This method considers the speaker to be finished when there is a certain duration of silence after a punctuation mark. + +# Interruptions + +When the AI speaks in a `StreamingConversation`, it can be interrupted by the user. `AgentConfig` itself provides a parameter called `interrupt_sensitivity` that can be used to control how sensitive the AI is to interruptions. Interrupt sensitivity has two options: low (default) and high. Low sensitivity makes the bot ignore backchannels (e.g. “sure”, “uh-huh”) while the bot is speaking. High sensitivity makes the agent treat any word from the human as an interruption. + +The implementation of this configuration is in `StreamingConversation.TranscriptionsWorker` - in order to make this work well, you may need to fork Vocode and override this behavior, but it provides a good starting place for most use-cases. + +Stay tuned, more dials to come here soon! + +# Conversation Speed + +`StreamingConversation` also exposes a parameter called `conversation_speed`, which controls the length of endpointing pauses, i.e. how long the bot will wait before responding to the human. This includes normal utterances from the human as well as interruptions. + +The amount of time the bot waits inversely scales with the `conversation_speed` value. So a bot with `conversation_speed` of 2 responds in half the time compared to a `conversation_speed` of 1. Likewise a `conversation_speed` of 0.5 means the bot takes twice as long to respond. + +```python +conversation = StreamingConversation( + speed_coefficient=2 + ... +) +``` + +Based on the speed of the user's speech (we calculate the WPM from each final utterance that goes through the pipeline), the `speed_coefficient` updates throughout the course of the conversation - see `vocode.streaming.utils.speed_manager` to see this implementation! diff --git a/docs/open-source/using-transcribers.mdx b/docs/open-source/using-transcribers.mdx index 2a2c9d069..f4a272478 100644 --- a/docs/open-source/using-transcribers.mdx +++ b/docs/open-source/using-transcribers.mdx @@ -66,26 +66,4 @@ async def main(): In this example, the `DeepgramTranscriberConfig.from_input_device()` method is used to create a configuration object for the Deepgram transcriber for use in a local `StreamingConversation`. The method takes a `microphone_input` object as an argument and extracts the `sampling_rate`, `audio_encoding`, and `chunk_size` from the input device. -## Endpointing - -Endpointing is the process of understanding when someone has finished speaking. The `EndpointingConfig` controls how this is done. There are a couple of different ways to configure endpointing: - -We provide `DeepgramEndpointingConfig()` which has some reasonable defaults and knobs to suit most use-cases (but only works with the Deepgram transcriber). - -``` -class DeepgramEndpointingConfig(EndpointingConfig, type="deepgram"): # type: ignore - vad_threshold_ms: int = 500 - utterance_cutoff_ms: int = 1000 - time_silent_config: Optional[TimeSilentConfig] = Field(default_factory=TimeSilentConfig) - use_single_utterance_endpointing_for_first_utterance: bool = False -``` - -- `vad_threshold_ms`: translates to [Deepgram's `endpointing` feature](https://developers.deepgram.com/docs/endpointing#enable-feature) -- `utterance_cutoff_ms`: uses [Deepgram's Utterance End features](https://developers.deepgram.com/docs/utterance-end) -- `time_silent_config`: is a Vocode specific parameter that marks an utterance final if we haven't seen any new words in X seconds -- `use_single_utterance_endpointing_for_first_utterance`: Uses `is_final` instead of `speech_final` for endpointing for the first utterance (works really well for outbound conversations, where the user's first utterance is something like "Hello?") - see [this doc on Deepgram](https://developers.deepgram.com/docs/understand-endpointing-interim-results) for more info. - -Endpointing is highly use-case specific - building a realistic experience for this greatly depends on the person speaking to the AI. Here are few paradigms that we've used to help you along the way: - -- Time-based endpointing: This method considers the speaker to be finished when there is a certain duration of silence. -- Punctuation-based endpointing: This method considers the speaker to be finished when there is a certain duration of silence after a punctuation mark. +See [Conversation Mechanics](/open-source/conversation-mechanics) for more information about endpointing. From 221b69a12a7b4a1c5c1549cfd5361b6bfb1c0733 Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Wed, 12 Jun 2024 13:11:05 -0700 Subject: [PATCH 20/25] updates docs for events manager (#7) --- docs/open-source/events-manager.mdx | 103 ++++++++++------------------ 1 file changed, 38 insertions(+), 65 deletions(-) diff --git a/docs/open-source/events-manager.mdx b/docs/open-source/events-manager.mdx index d947e9848..b7558cb0b 100644 --- a/docs/open-source/events-manager.mdx +++ b/docs/open-source/events-manager.mdx @@ -5,87 +5,60 @@ description: "How events are emitted and consumed." ## What is the Events Manager -The Events Manager is a class designed to facilitate asynchronous handling of events in the application. It allows for non-blocking actions on events, such as processing transcripts, managing phone calls, and other tasks. The main components of the Events Manager are the `EventsManager` class and several `Event` subclasses representing various event types. +The Events Manager consumes realtime events during conversations - it provides a framework to consume and take action on these events asychronously. -## EventsManager Class - -The `EventsManager` class is responsible for managing the event queue and handling events asynchronously. The class provides methods for publishing events, starting the event loop, handling events, and ending the event loop. - -### Initialization +## Current Event Types -```python -def __init__(self, subscriptions: List[EventType] = []): - self.queue = asyncio.Queue() - self.subscriptions = set(subscriptions) - self.active = False -``` +The current event types include: -The `EventsManager` constructor accepts an optional list of `EventType` subscriptions. By default, it initializes an empty set of subscriptions, an asynchronous queue, and sets the `active` attribute to `False`. +1. `TRANSCRIPT`: Indicates a partial transcript for the conversation has been received. +2. `TRANSCRIPT_COMPLETE`: Indicates the transcript is complete (ie conversation has ended). +3. `ACTION`: Indicates that a Vocode action has begun or completed. +4. `PHONE_CALL_CONNECTED`: Indicates a phone call has been connected (only gets sent during `PhoneConversation`s) +5. `PHONE_CALL_ENDED`: Indicates a phone call has ended. -### Publishing Events +## Usage -```python -def publish_event(self, event: Event): - if event.type in self.subscriptions: - self.queue.put_nowait(event) -``` +Using the events manager to take particular action when events fire requires that you subclass `vocode.streaming.utils.EventsManager` and override the `handle_event` method. -The `publish_event` method takes an `Event` object as input and adds it to the queue if its type is in the set of subscribed event types. +You can also configure which events your `EventsManager` is subscribed to by using the `subscriptions` property (see example). -### Starting the Event Loop +### Example ```python -async def start(self): - self.active = True - while self.active: - try: - event: Event = await self.queue.get() - except asyncio.QueueEmpty: - await asyncio.sleep(1) - self.handle_event(event) -``` +from vocode.streaming.models.events import Event, EventType -## Current Event Types +from vocode.streaming.models.events import Event, EventType +from vocode.streaming.models.transcript import TranscriptCompleteEvent +from vocode.streaming.utils.events_manager import EventsManager -The current event types include: -1. `TRANSCRIPT`: Indicates a partial transcript for the conversation has been received. -2. `TRANSCRIPT_COMPLETE`: Indicates the transcript is complete (ie conversation has ended). -3. `PHONE_CALL_CONNECTED`: Indicates a phone call has been connected. -4. `PHONE_CALL_ENDED`: Indicates a phone call has ended. -5. `RECORDING`: (Vonage Only) Indicates a secure URL containing a recording of the call is available. Requires `recording=true` in `VonageConfig`. +class CustomEventsManager(EventsManager): + def __init__(self): + super().__init__([EventType.TRANSCRIPT_COMPLETE]) -## Example Usage + async def handle_event(self, event: Event): + if isinstance(event, TranscriptCompleteEvent): + print("The call has finished, the transcript was", event.transcript.to_string()) +``` -The following example demonstrates how the `EventsManager` class can be used to consume the `TRANSCRIPT_COMPLETE` event and save the transcript to a file using the `add_transcript` method: +In this example, we create a custom `EventsManager` subclass is created with a subscription to the `TRANSCRIPT_COMPLETE` event and then print the transcript when we receive the event. -```python -import logging -from fastapi import FastAPI -from vocode.streaming.models.events import Event, EventType, TranscriptCompleteEvent -from vocode.streaming.utils import events_manager -from call_transcript_utils import add_transcript +To use `CustomEventsManager`, you can pass it into any Conversation, e.g. -app = FastAPI(docs_url=None) +``` +... +conversation = StreamingConversation( + ..., + events_manager=CustomEventsManager() +) +``` -logging.basicConfig() -logger = logging.getLogger(__name__) -logger.setLevel(logging.DEBUG) +You can also pass it into a `TelephonyServer`, like: -class CustomEventsManager(events_manager.EventsManager): - def __init__(self): - super().__init__(subscriptions=[EventType.TRANSCRIPT_COMPLETE]) - - def handle_event(self, event: Event): - if event.type == EventType.TRANSCRIPT_COMPLETE: - transcript_complete_event = typing.cast(TranscriptCompleteEvent, event) - add_transcript( - transcript_complete_event.conversation_id, - transcript_complete_event.transcript, - ) - -events_manager_instance = CustomEventsManager() -await events_manager_instance.start() ``` - -In this example, a custom `EventsManager` subclass is created with a subscription to the `TRANSCRIPT_COMPLETE` event. The `handle_event` method is overridden to save the transcript to a file using the `add_transcript` method when the `TRANSCRIPT_COMPLETE` event is received. +server = TelephonyServer( + ..., + events_manager=CustomEventsManager() +) +``` From 5dc841a54fa1ad14acb0463486ef081fe1e79363 Mon Sep 17 00:00:00 2001 From: rjheeta Date: Wed, 12 Jun 2024 16:56:10 -0400 Subject: [PATCH 21/25] add cartesia synthesizer (#17) * add cartesia synthesizer * make Cartesia dependency optional, add it to the synthesizers extra group * lazy import cartesia * improved lazy loading, and added api_key as a config parameter * improvements to cartesia synth * use create_speech_uncached * use existing abstractions default encoding and sample rates * Remove redundant api_key assignment Co-authored-by: Ajay Raj * Remove default setting of sampling rate Co-authored-by: Ajay Raj * Remove default setting of audio_encoding Co-authored-by: Ajay Raj * remove default setting of sampling rate Co-authored-by: Ajay Raj * Remove redundant setting of audio enconding the output device handles this Co-authored-by: Ajay Raj * build failed with poetry.lock file. re-updating it --------- Co-authored-by: Ajay Raj --- poetry.lock | 99 +++++++++------ pyproject.toml | 3 + vocode/streaming/models/synthesizer.py | 11 ++ .../synthesizer/cartesia_synthesizer.py | 114 ++++++++++++++++++ .../streaming/synthesizer/default_factory.py | 4 + 5 files changed, 192 insertions(+), 39 deletions(-) create mode 100644 vocode/streaming/synthesizer/cartesia_synthesizer.py diff --git a/poetry.lock b/poetry.lock index e9786cffe..dc6d8c3cb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.1 and should not be changed by hand. [[package]] name = "aiohttp" @@ -153,7 +153,7 @@ files = [ name = "anthropic" version = "0.28.0" description = "The official Python library for the anthropic API" -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "anthropic-0.28.0-py3-none-any.whl", hash = "sha256:2b620b21aee3d20c5d8005483c34df239d53ae895687113b26b8a36892a7e20f"}, @@ -199,7 +199,7 @@ trio = ["trio (>=0.23)"] name = "asttokens" version = "2.4.1" description = "Annotate AST trees with source code positions" -optional = true +optional = false python-versions = "*" files = [ {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, @@ -247,7 +247,7 @@ tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "p name = "azure-cognitiveservices-speech" version = "1.37.0" description = "Microsoft Cognitive Services Speech SDK for Python" -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "azure_cognitiveservices_speech-1.37.0-py3-none-macosx_10_14_x86_64.whl", hash = "sha256:906d6bf65176e93464e2d763dd074ca00c48cfe1a896371fcdcb155a500910f7"}, @@ -315,6 +315,28 @@ files = [ {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, ] +[[package]] +name = "cartesia" +version = "0.1.1" +description = "The official Python library for the Cartesia API." +optional = true +python-versions = ">=3.8.0" +files = [ + {file = "cartesia-0.1.1-py2.py3-none-any.whl", hash = "sha256:7a7365f17e220247ee2af1efdb88e69b0aa332e390c85775bf356b5e7b882498"}, + {file = "cartesia-0.1.1.tar.gz", hash = "sha256:c584770f4698e6dc826a75b7b5fd39bfce749c88ad9786dca46edd9527710002"}, +] + +[package.dependencies] +aiohttp = "*" +httpx = "*" +pytest-asyncio = "*" +requests = "*" +websockets = "*" + +[package.extras] +all = ["numpy", "pytest (>=8.0.2)", "pytest-cov (>=4.1.0)", "setuptools", "twine", "wheel"] +dev = ["numpy", "pytest (>=8.0.2)", "pytest-cov (>=4.1.0)", "setuptools", "twine", "wheel"] + [[package]] name = "certifi" version = "2024.6.2" @@ -654,7 +676,7 @@ typing-inspect = ">=0.4.0,<1" name = "decorator" version = "5.1.1" description = "Decorators for Humans" -optional = true +optional = false python-versions = ">=3.5" files = [ {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, @@ -682,7 +704,7 @@ dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] name = "distro" version = "1.9.0" description = "Distro - an OS platform information API" -optional = true +optional = false python-versions = ">=3.6" files = [ {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, @@ -713,7 +735,7 @@ wmi = ["wmi (>=1.5.1)"] name = "elevenlabs" version = "1.2.2" description = "" -optional = true +optional = false python-versions = "<4.0,>=3.8" files = [ {file = "elevenlabs-1.2.2-py3-none-any.whl", hash = "sha256:60b92b0e2aabdfba93a43569f207f8a2ad397492519b8e11a2eebb32807ddefa"}, @@ -761,7 +783,7 @@ test = ["pytest (>=6)"] name = "executing" version = "2.0.1" description = "Get the currently executing AST node of a frame, and other information" -optional = true +optional = false python-versions = ">=3.5" files = [ {file = "executing-2.0.1-py2.py3-none-any.whl", hash = "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc"}, @@ -842,7 +864,7 @@ standard = ["fastapi", "uvicorn[standard] (>=0.15.0)"] name = "filelock" version = "3.14.0" description = "A platform independent file lock." -optional = true +optional = false python-versions = ">=3.8" files = [ {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"}, @@ -944,7 +966,7 @@ files = [ name = "fsspec" version = "2024.6.0" description = "File-system specification" -optional = true +optional = false python-versions = ">=3.8" files = [ {file = "fsspec-2024.6.0-py3-none-any.whl", hash = "sha256:58d7122eb8a1a46f7f13453187bfea4972d66bf01618d37366521b1998034cee"}, @@ -1159,7 +1181,7 @@ test = ["objgraph", "psutil"] name = "grpcio" version = "1.64.1" description = "HTTP/2-based RPC framework" -optional = true +optional = false python-versions = ">=3.8" files = [ {file = "grpcio-1.64.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:55697ecec192bc3f2f3cc13a295ab670f51de29884ca9ae6cd6247df55df2502"}, @@ -1337,7 +1359,7 @@ socks = ["socksio (==1.*)"] name = "huggingface-hub" version = "0.23.3" description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" -optional = true +optional = false python-versions = ">=3.8.0" files = [ {file = "huggingface_hub-0.23.3-py3-none-any.whl", hash = "sha256:22222c41223f1b7c209ae5511d2d82907325a0e3cdbce5f66949d43c598ff3bc"}, @@ -1412,7 +1434,7 @@ files = [ name = "ipython" version = "8.25.0" description = "IPython: Productive Interactive Computing" -optional = true +optional = false python-versions = ">=3.10" files = [ {file = "ipython-8.25.0-py3-none-any.whl", hash = "sha256:53eee7ad44df903a06655871cbab66d156a051fd86f3ec6750470ac9604ac1ab"}, @@ -1478,7 +1500,7 @@ typing-extensions = ">=3.7.4.3" name = "jedi" version = "0.19.1" description = "An autocompletion tool for Python that can be used for text editors." -optional = true +optional = false python-versions = ">=3.6" files = [ {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"}, @@ -1514,7 +1536,7 @@ i18n = ["Babel (>=2.7)"] name = "jiter" version = "0.4.1" description = "Fast iterable JSON parser." -optional = true +optional = false python-versions = ">=3.8" files = [ {file = "jiter-0.4.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3c2370cd8826b484f3fc6ed729cb58510ba24b4bc277c92323a57d35cf4df223"}, @@ -1905,7 +1927,7 @@ tests = ["pytest", "pytz", "simplejson"] name = "matplotlib-inline" version = "0.1.7" description = "Inline Matplotlib backend for Jupyter" -optional = true +optional = false python-versions = ">=3.8" files = [ {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"}, @@ -2221,7 +2243,7 @@ files = [ name = "openai" version = "1.31.0" description = "The official Python library for the openai API" -optional = true +optional = false python-versions = ">=3.7.1" files = [ {file = "openai-1.31.0-py3-none-any.whl", hash = "sha256:82044ee3122113f2a468a1f308a8882324d09556ba5348687c535d3655ee331c"}, @@ -2355,7 +2377,7 @@ files = [ name = "parso" version = "0.8.4" description = "A Python Parser" -optional = true +optional = false python-versions = ">=3.6" files = [ {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, @@ -2381,7 +2403,7 @@ files = [ name = "pexpect" version = "4.9.0" description = "Pexpect allows easy control of interactive console applications." -optional = true +optional = false python-versions = "*" files = [ {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, @@ -2437,7 +2459,7 @@ testing = ["pytest", "pytest-benchmark"] name = "prompt-toolkit" version = "3.0.46" description = "Library for building powerful interactive command lines in Python" -optional = true +optional = false python-versions = ">=3.7.0" files = [ {file = "prompt_toolkit-3.0.46-py3-none-any.whl", hash = "sha256:45abe60a8300f3c618b23c16c4bb98c6fc80af8ce8b17c7ae92db48db3ee63c1"}, @@ -2468,7 +2490,7 @@ testing = ["google-api-core[grpc] (>=1.31.5)"] name = "protobuf" version = "4.25.3" description = "" -optional = true +optional = false python-versions = ">=3.8" files = [ {file = "protobuf-4.25.3-cp310-abi3-win32.whl", hash = "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa"}, @@ -2488,7 +2510,7 @@ files = [ name = "ptyprocess" version = "0.7.0" description = "Run a subprocess in a pseudo terminal" -optional = true +optional = false python-versions = "*" files = [ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, @@ -2499,7 +2521,7 @@ files = [ name = "pure-eval" version = "0.2.2" description = "Safely evaluate AST nodes without side effects" -optional = true +optional = false python-versions = "*" files = [ {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, @@ -2728,7 +2750,7 @@ windows-terminal = ["colorama (>=0.4.6)"] name = "pyht" version = "0.0.28" description = "" -optional = true +optional = false python-versions = "<4.0,>=3.8" files = [ {file = "pyht-0.0.28-py3-none-any.whl", hash = "sha256:ad8801acaa906eff5d6b39ce5ca76a08c154f705a2d0b2b6e841b219ef7875be"}, @@ -3008,7 +3030,7 @@ rpds-py = ">=0.7.0" name = "regex" version = "2024.5.15" description = "Alternative regular expression module, to replace re." -optional = true +optional = false python-versions = ">=3.8" files = [ {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f"}, @@ -3257,7 +3279,7 @@ pyasn1 = ">=0.1.3" name = "sentry-sdk" version = "2.4.0" description = "Python client for Sentry (https://sentry.io)" -optional = true +optional = false python-versions = ">=3.6" files = [ {file = "sentry_sdk-2.4.0-py2.py3-none-any.whl", hash = "sha256:a42b70981cd4ed7da3c85d0360502d2ac932a15a4a420b360e1ebded2fc19a92"}, @@ -3319,7 +3341,7 @@ files = [ name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -optional = true +optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, @@ -3459,7 +3481,7 @@ sqlcipher = ["sqlcipher3_binary"] name = "stack-data" version = "0.6.3" description = "Extract data from python stack frames and tracebacks for informative displays" -optional = true +optional = false python-versions = "*" files = [ {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, @@ -3510,7 +3532,7 @@ test = ["pytest", "tornado (>=4.5)", "typeguard"] name = "tiktoken" version = "0.7.0" description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" -optional = true +optional = false python-versions = ">=3.8" files = [ {file = "tiktoken-0.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485f3cc6aba7c6b6ce388ba634fbba656d9ee27f766216f45146beb4ac18b25f"}, @@ -3562,7 +3584,7 @@ blobfile = ["blobfile (>=2)"] name = "tokenizers" version = "0.19.1" description = "" -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "tokenizers-0.19.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:952078130b3d101e05ecfc7fc3640282d74ed26bcf691400f872563fca15ac97"}, @@ -3690,7 +3712,7 @@ files = [ name = "tqdm" version = "4.66.4" description = "Fast, Extensible Progress Meter" -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "tqdm-4.66.4-py3-none-any.whl", hash = "sha256:b75ca56b413b030bc3f00af51fd2c1a1a5eac6a0c1cca83cbb37a5c52abce644"}, @@ -3710,7 +3732,7 @@ telegram = ["requests"] name = "traitlets" version = "5.14.3" description = "Traitlets Python configuration system" -optional = true +optional = false python-versions = ">=3.8" files = [ {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}, @@ -4174,7 +4196,7 @@ anyio = ">=3.0.0" name = "wcwidth" version = "0.2.13" description = "Measures the displayed width of unicode strings in a terminal" -optional = true +optional = false python-versions = "*" files = [ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, @@ -4474,14 +4496,13 @@ doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linke test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [extras] -agents = ["anthropic", "openai", "tiktoken"] -all = ["anthropic", "azure-cognitiveservices-speech", "elevenlabs", "google-cloud-speech", "google-cloud-texttospeech", "langchain", "langchain-community", "miniaudio", "nltk", "openai", "pvkoala", "pydub", "pyht", "redis", "sentry-sdk", "tiktoken", "twilio", "vonage"] -misc = ["langchain", "langchain-community", "sentry-sdk"] -synthesizers = ["azure-cognitiveservices-speech", "elevenlabs", "google-cloud-texttospeech", "miniaudio", "nltk", "pvkoala", "pydub", "pyht"] -telephony = ["redis", "twilio", "vonage"] +all = ["cartesia", "google-cloud-speech", "google-cloud-texttospeech", "langchain", "langchain-community", "miniaudio", "nltk", "pvkoala", "pydub", "twilio", "vonage"] +misc = ["langchain", "langchain-community"] +synthesizers = ["cartesia", "google-cloud-texttospeech", "miniaudio", "nltk", "pvkoala", "pydub"] +telephony = ["twilio", "vonage"] transcribers = ["google-cloud-speech"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<4.0" -content-hash = "0b362b102f8d84dd63633857a97c7ae7922358bfbb1e66b070e40c10643b7667" +content-hash = "0153515588beee9a13a33a4fb32d26dad863de37b6c55f903148f9c88904dc82" diff --git a/pyproject.toml b/pyproject.toml index 592d95b0d..32785b226 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,7 @@ google-cloud-texttospeech = { version = "^2.16.3", optional = true } miniaudio = { version = "^1.59", optional = true } pvkoala = { version = "^2.0.1", optional = true } pydub = { version = "^0.25.1", optional = true } +cartesia = { version = "^0.1.1", optional = true } # Transcribers google-cloud-speech = { version = "^2.26.0", optional = true } @@ -81,6 +82,7 @@ synthesizers = [ "miniaudio", "pvkoala", "pydub", + "cartesia", ] transcribers = ["google-cloud-speech"] telephony = ["twilio", "vonage"] @@ -96,6 +98,7 @@ all = [ "vonage", "langchain", "langchain-community", + "cartesia" ] [tool.mypy] diff --git a/vocode/streaming/models/synthesizer.py b/vocode/streaming/models/synthesizer.py index 24616bb8b..6820543c2 100644 --- a/vocode/streaming/models/synthesizer.py +++ b/vocode/streaming/models/synthesizer.py @@ -23,6 +23,7 @@ class SynthesizerType(str, Enum): COQUI = "synthesizer_coqui" BARK = "synthesizer_bark" POLLY = "synthesizer_polly" + CARTESIA = "synthesizer_cartesia" class SentimentConfig(BaseModel): @@ -226,3 +227,13 @@ class PollySynthesizerConfig(SynthesizerConfig, type=SynthesizerType.POLLY.value language_code: str = DEFAULT_POLLY_LANGUAGE_CODE voice_id: str = DEFAULT_POLLY_VOICE_ID sampling_rate: int = DEFAULT_POLLY_SAMPLING_RATE + + +DEFAULT_CARTESIA_MODEL_ID = 'upbeat-moon' +DEFAULT_CARTESIA_VOICE_ID = '5345cf08-6f37-424d-a5d9-8ae1101b9377' + + +class CartesiaSynthesizerConfig(SynthesizerConfig, type=SynthesizerType.CARTESIA.value): # type: ignore + api_key: Optional[str] = None + model_id: str = DEFAULT_CARTESIA_MODEL_ID + voice_id: str = DEFAULT_CARTESIA_VOICE_ID diff --git a/vocode/streaming/synthesizer/cartesia_synthesizer.py b/vocode/streaming/synthesizer/cartesia_synthesizer.py new file mode 100644 index 000000000..9e1392e6a --- /dev/null +++ b/vocode/streaming/synthesizer/cartesia_synthesizer.py @@ -0,0 +1,114 @@ +import io +import wave +import hashlib + +from vocode import getenv +from vocode.streaming.models.audio import AudioEncoding, SamplingRate +from vocode.streaming.models.message import BaseMessage +from vocode.streaming.models.synthesizer import CartesiaSynthesizerConfig +from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer, SynthesisResult +from vocode.streaming.utils.create_task import asyncio_create_task_with_done_error_log + + +class CartesiaSynthesizer(BaseSynthesizer[CartesiaSynthesizerConfig]): + def __init__( + self, + synthesizer_config: CartesiaSynthesizerConfig, + ): + super().__init__(synthesizer_config) + + # Lazy import the cartesia module + try: + from cartesia.tts import AsyncCartesiaTTS + except ImportError as e: + raise ImportError( + f"Missing required dependancies for CartesiaSynthesizer" + ) from e + + self.cartesia_tts = AsyncCartesiaTTS + + self.api_key = synthesizer_config.api_key or getenv("CARTESIA_API_KEY") + if not self.api_key: + raise ValueError("Missing Cartesia API key") + + + if synthesizer_config.audio_encoding == AudioEncoding.LINEAR16: + self.channel_width = 2 + match synthesizer_config.sampling_rate: + case SamplingRate.RATE_44100: + self.sampling_rate = 44100 + self.output_format = "pcm_44100" + case SamplingRate.RATE_22050: + self.sampling_rate = 22050 + self.output_format = "pcm_22050" + case SamplingRate.RATE_16000: + self.sampling_rate = 16000 + self.output_format = "pcm_16000" + case _: + raise ValueError( + f"Unsupported PCM sampling rate {synthesizer_config.sampling_rate}" + ) + elif synthesizer_config.audio_encoding == AudioEncoding.MULAW: + # Cartesia has issues with MuLaw/8000. Use pcm/16000 and + # create_synthesis_result_from_wav will handle the conversion to mulaw/8000 + self.channel_width = 2 + self.output_format = "pcm_16000" + self.sampling_rate = 16000 + else: + raise ValueError( + f"Unsupported audio encoding {synthesizer_config.audio_encoding}" + ) + + self.num_channels = 1 + self.model_id = synthesizer_config.model_id + self.voice_id = synthesizer_config.voice_id + self.client = self.cartesia_tts(api_key=self.api_key) + self.voice_embedding = self.client.get_voice_embedding(voice_id=self.voice_id) + + + async def create_speech_uncached( + self, + message: BaseMessage, + chunk_size: int, + is_first_text_chunk: bool = False, + is_sole_text_chunk: bool = False, + ) -> SynthesisResult: + generator = await self.client.generate( + transcript=message.text, + voice=self.voice_embedding, + stream=True, + model_id=self.model_id, + data_rtype='bytes', + output_format=self.output_format + ) + + audio_file = io.BytesIO() + with wave.open(audio_file, 'wb') as wav_file: + wav_file.setnchannels(self.num_channels) + wav_file.setsampwidth(self.channel_width) + wav_file.setframerate(self.sampling_rate) + async for chunk in generator: + wav_file.writeframes(chunk['audio']) + audio_file.seek(0) + + result = self.create_synthesis_result_from_wav( + synthesizer_config=self.synthesizer_config, + file=audio_file, + message=message, + chunk_size=chunk_size, + ) + + return result + + @classmethod + def get_voice_identifier(cls, synthesizer_config: CartesiaSynthesizerConfig): + hashed_api_key = hashlib.sha256(f"{synthesizer_config.api_key}".encode("utf-8")).hexdigest() + return ":".join( + ( + "cartesia", + hashed_api_key, + str(synthesizer_config.voice_id), + str(synthesizer_config.model_id), + synthesizer_config.audio_encoding + ) + ) \ No newline at end of file diff --git a/vocode/streaming/synthesizer/default_factory.py b/vocode/streaming/synthesizer/default_factory.py index 7539cf1dd..16574d4e5 100644 --- a/vocode/streaming/synthesizer/default_factory.py +++ b/vocode/streaming/synthesizer/default_factory.py @@ -1,6 +1,7 @@ from typing import Type from vocode.streaming.models.synthesizer import ( AzureSynthesizerConfig, + CartesiaSynthesizerConfig, ElevenLabsSynthesizerConfig, PlayHtSynthesizerConfig, RimeSynthesizerConfig, @@ -10,6 +11,7 @@ from vocode.streaming.synthesizer.abstract_factory import AbstractSynthesizerFactory from vocode.streaming.synthesizer.azure_synthesizer import AzureSynthesizer from vocode.streaming.synthesizer.base_synthesizer import BaseSynthesizer +from vocode.streaming.synthesizer.cartesia_synthesizer import CartesiaSynthesizer from vocode.streaming.synthesizer.eleven_labs_synthesizer import ElevenLabsSynthesizer from vocode.streaming.synthesizer.eleven_labs_websocket_synthesizer import ElevenLabsWSSynthesizer from vocode.streaming.synthesizer.play_ht_synthesizer import PlayHtSynthesizer @@ -25,6 +27,8 @@ def create_synthesizer( ): if isinstance(synthesizer_config, AzureSynthesizerConfig): return AzureSynthesizer(synthesizer_config) + elif isinstance(synthesizer_config, CartesiaSynthesizerConfig): + return CartesiaSynthesizer(synthesizer_config) elif isinstance(synthesizer_config, ElevenLabsSynthesizerConfig): eleven_labs_synthesizer_class_type: Type[BaseSynthesizer] = ElevenLabsSynthesizer if synthesizer_config.experimental_websocket: From 4625cdef1f54e56dae6c8e3deae2c78e731f9b1a Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Thu, 13 Jun 2024 11:16:47 -0700 Subject: [PATCH 22/25] Unset docs / README changes --- README.md | 188 +++++++++++++------ docs/injecting-context.mdx | 6 +- docs/mint.json | 16 +- docs/open-source/agent-factory.mdx | 25 +-- docs/open-source/events-manager.mdx | 103 ++++++---- docs/open-source/language-support.mdx | 7 +- docs/open-source/playground.mdx | 11 +- docs/open-source/react-quickstart.mdx | 40 ++-- docs/open-source/tracing.mdx | 95 ++++++++++ docs/open-source/turn-based-conversation.mdx | 73 +++---- docs/open-source/using-synthesizers.mdx | 64 +++---- docs/open-source/using-transcribers.mdx | 13 +- 12 files changed, 409 insertions(+), 232 deletions(-) create mode 100644 docs/open-source/tracing.mdx diff --git a/README.md b/README.md index 882b3621b..a01434cdf 100644 --- a/README.md +++ b/README.md @@ -1,82 +1,152 @@ -# 🚀 Vocode 0.0.112 Early Preview +
-👋 Hey there, Vocode Explorer! +![Hero](https://user-images.githubusercontent.com/6234599/228337850-e32bb01d-3701-47ef-a433-3221c9e0e56e.png) -Congratulations! You've stumbled upon the Vocode 0.0.112 Early Preview Repo! Whether we (the Vocode team) sent you this link or you found it through your own detective work, we want to celebrate your awesomeness in the Vocode community with this sneak peek of our latest work! +[![Twitter](https://img.shields.io/twitter/url/https/twitter.com/vocodehq.svg?style=social&label=Follow%20%40vocodehq)](https://twitter.com/vocodehq) [![GitHub Repo stars](https://img.shields.io/github/stars/vocodedev/vocode-python?style=social)](https://github.com/vocodedev/vocode-python) +[![Downloads](https://static.pepy.tech/badge/vocode/month)](https://pepy.tech/project/vocode) -## 🎉 What's Next? +[Community](https://discord.gg/NaU4mMgcnC) | [Docs](https://docs.vocode.dev) | [Dashboard](https://app.vocode.dev) -We'd love to invite you to our private channel on Discord! [(Join us here!)](https://discord.gg/MVQD5bmf49) This is your VIP pass to chat with Vocode team members, get help, ask questions, and maybe even contribute to the 0.0.112 release! +
-## 🚨 Need Access? +#   vocode -If you can see this but don't have access to the new channels, just reach out to Mac, Ajay, George, or any other Vocode team member. We'll make sure you get in! +### **Build voice-based LLM apps in minutes** -## 🤐 Keep It Under Wraps +Vocode is an open source library that makes it easy to build voice-based LLM apps. Using Vocode, you can build real-time streaming conversations with LLMs and deploy them to phone calls, Zoom meetings, and more. You can also build personal assistants or apps like voice-based chess. Vocode provides easy abstractions and integrations so that everything you need is in a single library. -We’re super excited to share this with you, but we’d appreciate it if you could keep this on the down-low for now. While we know you might share this with close friends, please avoid posting it in public places. We're still polishing things up for the big public launch! +We're actively looking for community maintainers, so please reach out if interested! -## 📜 Viewing Preview Docs +# ⭐️ Features -We'll be updating our existing documentation and adding guides for new functionality (see below) in this fork itself. To view them, use the [Mintlify CLI](https://mintlify.com/docs/development): +- 🗣 [Spin up a conversation with your system audio](https://docs.vocode.dev/python-quickstart) +- ➡️ 📞 [Set up a phone number that responds with a LLM-based agent](https://docs.vocode.dev/telephony#inbound-calls) +- 📞 ➡️ [Send out phone calls from your phone number managed by an LLM-based agent](https://docs.vocode.dev/telephony#outbound-calls) +- 🧑‍💻 [Dial into a Zoom call](https://github.com/vocodedev/vocode-python/blob/main/vocode/streaming/telephony/hosted/zoom_dial_in.py) +- 🤖 [Use an outbound call to a real phone number in a Langchain agent](https://docs.vocode.dev/langchain-agent) +- Out of the box integrations with: + - Transcription services, including: + - [AssemblyAI](https://www.assemblyai.com/) + - [Deepgram](https://deepgram.com/) + - [Gladia](https://gladia.io) + - [Google Cloud](https://cloud.google.com/speech-to-text) + - [Microsoft Azure](https://azure.microsoft.com/en-us/products/cognitive-services/speech-to-text) + - [RevAI](https://www.rev.ai/) + - [Whisper](https://openai.com/blog/introducing-chatgpt-and-whisper-apis) + - [Whisper.cpp](https://github.com/ggerganov/whisper.cpp) + + - LLMs, including: + - [ChatGPT](https://openai.com/blog/chatgpt) + - [GPT-4](https://platform.openai.com/docs/models/gpt-4) + - [Anthropic](https://www.anthropic.com/) + - [GPT4All](https://github.com/nomic-ai/gpt4all) + - Synthesis services, including: + - [Rime.ai](https://rime.ai) + - [Microsoft Azure](https://azure.microsoft.com/en-us/products/cognitive-services/text-to-speech/) + - [Google Cloud](https://cloud.google.com/text-to-speech) + - [Play.ht](https://play.ht) + - [Eleven Labs](https://elevenlabs.io/) + - [Coqui](https://coqui.ai/) + - [Coqui (OSS)](https://github.com/coqui-ai/TTS) + - [gTTS](https://gtts.readthedocs.io/) + - [StreamElements](https://streamelements.com/) + - [Bark](https://github.com/suno-ai/bark) + - [AWS Polly](https://aws.amazon.com/polly/) -``` -/path/to/vocode-python > cd docs -/path/to/vocode-python/docs > mintlify dev -``` - -## 📝 Brief Changelog - -### 🧱Vocode Core Abstractions Revamp - -- Improved Abstractions to enable faster customization of: - - Agents - - Transcribers - - Synthesizers - - Telephony Providers +Check out our React SDK [here](https://github.com/vocodedev/vocode-react-sdk)! -### 👥 Conversation Mechanics (guide to follow!) +# 🫂 Contribution and Roadmap -- Better endpointing (agnostic of transcribers) -- Better interruption handling +We're an open source project and are extremely open to contributors adding new features, integrations, and documentation! Please don't hesitate to reach out and get started building with us. -### 🕵️ Agents +For more information on contributing, see our [Contribution Guide](https://github.com/vocodedev/vocode-python/blob/main/contributing.md). -- ✨NEW✨ Anthropic-based Agent - - Supports all Claude 3 Models -- OpenAI GPT-4o Support -- Azure OpenAI revamp +And check out our [Roadmap](https://github.com/vocodedev/vocode-python/blob/main/roadmap.md). -### 💪 Actions +We'd love to talk to you on [Discord](https://discord.gg/NaU4mMgcnC) about new ideas and contributing! -- ✨NEW✨ External Actions (guide to follow!) -- Improved Call Transfer -- ✨NEW✨ Wait Actions (IVR Navigation) -- ✨NEW✨ Phrase triggers for actions (instead of function calls) (guide to follow!) +# 🚀 Quickstart -### 🗣️ Synthesizers - -- ElevenLabs - - ✨NEW✨ Websocket-based Client - - Updated RESTful client -- ✨NEW✨ PlayHT Synthesizer “v2” with [PlayHT On-Prem](https://docs.play.ht/reference/on-prem) Support -- [Rime Mist](https://rimelabs.mintlify.app/api-reference/models) support - -### ✍️ Transcribers +```bash +pip install 'vocode' +``` -- ✨NEW✨ Deepgram [built-in endpointing](https://developers.deepgram.com/docs/endpointing) +```python +import asyncio +import logging +import signal +from vocode.streaming.streaming_conversation import StreamingConversation +from vocode.helpers import create_streaming_microphone_input_and_speaker_output +from vocode.streaming.transcriber import * +from vocode.streaming.agent import * +from vocode.streaming.synthesizer import * +from vocode.streaming.models.transcriber import * +from vocode.streaming.models.agent import * +from vocode.streaming.models.synthesizer import * +from vocode.streaming.models.message import BaseMessage +import vocode + +# these can also be set as environment variables +vocode.setenv( + OPENAI_API_KEY="", + DEEPGRAM_API_KEY="", + AZURE_SPEECH_KEY="", + AZURE_SPEECH_REGION="", +) + + +logging.basicConfig() +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) + + +async def main(): + ( + microphone_input, + speaker_output, + ) = create_streaming_microphone_input_and_speaker_output( + use_default_devices=False, + logger=logger, + use_blocking_speaker_output=True + ) + + conversation = StreamingConversation( + output_device=speaker_output, + transcriber=DeepgramTranscriber( + DeepgramTranscriberConfig.from_input_device( + microphone_input, + endpointing_config=PunctuationEndpointingConfig(), + ) + ), + agent=ChatGPTAgent( + ChatGPTAgentConfig( + initial_message=BaseMessage(text="What up"), + prompt_preamble="""The AI is having a pleasant conversation about life""", + ) + ), + synthesizer=AzureSynthesizer( + AzureSynthesizerConfig.from_output_device(speaker_output) + ), + logger=logger, + ) + await conversation.start() + print("Conversation started, press Ctrl+C to end") + signal.signal( + signal.SIGINT, lambda _0, _1: asyncio.create_task(conversation.terminate()) + ) + while conversation.is_active(): + chunk = await microphone_input.get_audio() + conversation.receive_audio(chunk) + + +if __name__ == "__main__": + asyncio.run(main()) +``` -### 📞 Telephony +# 📞 Phone call quickstarts -- Twilio - - Stronger interruption handling by [clearing audio queues](https://www.twilio.com/docs/voice/media-streams/websocket-messages#send-a-clear-message) -- Vonage - - Koala Noise Suppression (guide to follow!) +- [Telephony Server - Self-hosted](https://docs.vocode.dev/telephony) -### 🎉 Miscellaneous +# 🌱 Documentation -- ✨NEW✨  Loguru for improved logging formatting - - Some new utilities to make setting up loguru in your projects fast and easy 😉 (guide to follow!) -- Sentry for Metric / Error Collection (guide to follow!) -- Clean handling of content filters in ChatGPT agents -- Redis Message Queue for tracking mid-call events across different instances +[docs.vocode.dev](https://docs.vocode.dev/) diff --git a/docs/injecting-context.mdx b/docs/injecting-context.mdx index 75341f349..c14776655 100644 --- a/docs/injecting-context.mdx +++ b/docs/injecting-context.mdx @@ -30,8 +30,10 @@ name_prompt = "You are talking to ${name}" number = vocode_client.numbers.update_number( phone_number="YOUR_NUMBER", inbound_agent=AgentUpdateParams( - prompt=PromptUpdateParams(content=name_prompt), - context_endpoint="YOUR_CONTEXT_URL", + prompt=PromptUpdateParams( + content=name_prompt, + context_endpoint="YOUR_CONTEXT_URL", + ) ), ) ``` diff --git a/docs/mint.json b/docs/mint.json index f3f7a19d1..bd97c3dbd 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -49,11 +49,7 @@ "navigation": [ { "group": "Getting Started", - "pages": [ - "welcome", - "hosted-quickstart", - "open-source-quickstart" - ] + "pages": ["welcome", "hosted-quickstart", "open-source-quickstart"] }, { "group": "Vocode 101", @@ -69,10 +65,8 @@ "open-source/python-quickstart", "open-source/telephony", "open-source/create-your-own-agent", - "open-source/conversation-mechanics", "open-source/langchain-agent", "open-source/action-agents", - "open-source/action-phrase-triggers", "open-source/local-conversation", "open-source/events-manager", "open-source/using-synthesizers", @@ -81,7 +75,7 @@ "open-source/playground", "open-source/turn-based-conversation", "open-source/language-support", - "open-source/logging-with-loguru", + "open-source/tracing", "open-source/agent-factory" ] }, @@ -115,9 +109,7 @@ }, { "group": "Usage", - "pages": [ - "api-reference/usage/get-usage" - ] + "pages": ["api-reference/usage/get-usage"] }, { "group": "Actions", @@ -231,4 +223,4 @@ "twitter": "https://twitter.com/vocodehq", "website": "https://www.vocode.dev/" } -} \ No newline at end of file +} diff --git a/docs/open-source/agent-factory.mdx b/docs/open-source/agent-factory.mdx index 58b17af18..7b0c25d7c 100644 --- a/docs/open-source/agent-factory.mdx +++ b/docs/open-source/agent-factory.mdx @@ -5,18 +5,18 @@ description: 'How to link a custom agent to your app' # Agent Factories -Agent factories specify which agents are available to your app. In order to connect an agent to your app, you must first define an agent factory. To do so, subclass the [`AbstractAgentFactory`](https://github.com/vocodedev/vocode-python/blob/main/vocode/streaming/agent/abstract_factory.py) class to specify how agents are created. Here you can import and use your own custom agents. +Agent factories specify which agents are available to your app. In order to connect an agent to your app, you must first define an agent factory. To do so, subclass the [`AgentFactory`](https://github.com/vocodedev/vocode-python/blob/main/vocode/streaming/agent/factory.py) class to specify how agents are created. Here you can import and use your own custom agents. ## Example -First define your `AgentFactory`. In this example, we are creating a factory for a new type of agent called MyActionAgent: +First define your `AgentFactory`: ```python -from vocode.streaming.agent.abstract_factory import AbstractAgentFactory -from vocode.streaming.action.my_action_factory import MyActionFactory +from vocode.streaming.agent.factory import AgentFactory -class MyAgentFactory(AbstractAgentFactory): - def __init__(self, action_factory: MyActionFactory): +class MyAgentFactory(AgentFactory): + def __init__(self, agent_config: AgentConfig, action_factory: MyActionFactory): + self.agent_config = agent_config self.action_factory = action_factory def create_agent( @@ -24,24 +24,19 @@ class MyAgentFactory(AbstractAgentFactory): ) -> BaseAgent: if agent_config.type == "MY_ACTION": return MyActionAgent( - agent_config=agent_config, + agent_config=typing.cast(ActionAgentConfig, self.agent_config), action_factory=self.action_factory ) - elif agent_config.type == "other_agent_type": - ... - else: - raise Exception("Invalid agent config") + raise Exception("Invalid agent config") ``` Then, in your app, you can connect the agent to the app: ```python -from vocode.streaming.telephony.server.base import TelephonyServer -from vocode.streaming.agent.my_agent_factory import MyAgentFactory -from vocode.streaming.action.my_action_factory import MyActionFactory telephony_server = TelephonyServer( - agent_factory=MyAgentFactory(action_factory=MyActionFactory()) + agent_factory=MyAgentFactory( + agent_config=agent_config, action_factory=action_factory), ... ) ``` diff --git a/docs/open-source/events-manager.mdx b/docs/open-source/events-manager.mdx index b7558cb0b..d947e9848 100644 --- a/docs/open-source/events-manager.mdx +++ b/docs/open-source/events-manager.mdx @@ -5,60 +5,87 @@ description: "How events are emitted and consumed." ## What is the Events Manager -The Events Manager consumes realtime events during conversations - it provides a framework to consume and take action on these events asychronously. +The Events Manager is a class designed to facilitate asynchronous handling of events in the application. It allows for non-blocking actions on events, such as processing transcripts, managing phone calls, and other tasks. The main components of the Events Manager are the `EventsManager` class and several `Event` subclasses representing various event types. -## Current Event Types +## EventsManager Class -The current event types include: +The `EventsManager` class is responsible for managing the event queue and handling events asynchronously. The class provides methods for publishing events, starting the event loop, handling events, and ending the event loop. -1. `TRANSCRIPT`: Indicates a partial transcript for the conversation has been received. -2. `TRANSCRIPT_COMPLETE`: Indicates the transcript is complete (ie conversation has ended). -3. `ACTION`: Indicates that a Vocode action has begun or completed. -4. `PHONE_CALL_CONNECTED`: Indicates a phone call has been connected (only gets sent during `PhoneConversation`s) -5. `PHONE_CALL_ENDED`: Indicates a phone call has ended. +### Initialization + +```python +def __init__(self, subscriptions: List[EventType] = []): + self.queue = asyncio.Queue() + self.subscriptions = set(subscriptions) + self.active = False +``` + +The `EventsManager` constructor accepts an optional list of `EventType` subscriptions. By default, it initializes an empty set of subscriptions, an asynchronous queue, and sets the `active` attribute to `False`. -## Usage +### Publishing Events -Using the events manager to take particular action when events fire requires that you subclass `vocode.streaming.utils.EventsManager` and override the `handle_event` method. +```python +def publish_event(self, event: Event): + if event.type in self.subscriptions: + self.queue.put_nowait(event) +``` -You can also configure which events your `EventsManager` is subscribed to by using the `subscriptions` property (see example). +The `publish_event` method takes an `Event` object as input and adds it to the queue if its type is in the set of subscribed event types. -### Example +### Starting the Event Loop ```python -from vocode.streaming.models.events import Event, EventType +async def start(self): + self.active = True + while self.active: + try: + event: Event = await self.queue.get() + except asyncio.QueueEmpty: + await asyncio.sleep(1) + self.handle_event(event) +``` -from vocode.streaming.models.events import Event, EventType -from vocode.streaming.models.transcript import TranscriptCompleteEvent -from vocode.streaming.utils.events_manager import EventsManager +## Current Event Types +The current event types include: -class CustomEventsManager(EventsManager): - def __init__(self): - super().__init__([EventType.TRANSCRIPT_COMPLETE]) +1. `TRANSCRIPT`: Indicates a partial transcript for the conversation has been received. +2. `TRANSCRIPT_COMPLETE`: Indicates the transcript is complete (ie conversation has ended). +3. `PHONE_CALL_CONNECTED`: Indicates a phone call has been connected. +4. `PHONE_CALL_ENDED`: Indicates a phone call has ended. +5. `RECORDING`: (Vonage Only) Indicates a secure URL containing a recording of the call is available. Requires `recording=true` in `VonageConfig`. - async def handle_event(self, event: Event): - if isinstance(event, TranscriptCompleteEvent): - print("The call has finished, the transcript was", event.transcript.to_string()) -``` +## Example Usage -In this example, we create a custom `EventsManager` subclass is created with a subscription to the `TRANSCRIPT_COMPLETE` event and then print the transcript when we receive the event. +The following example demonstrates how the `EventsManager` class can be used to consume the `TRANSCRIPT_COMPLETE` event and save the transcript to a file using the `add_transcript` method: -To use `CustomEventsManager`, you can pass it into any Conversation, e.g. +```python +import logging +from fastapi import FastAPI +from vocode.streaming.models.events import Event, EventType, TranscriptCompleteEvent +from vocode.streaming.utils import events_manager +from call_transcript_utils import add_transcript -``` -... -conversation = StreamingConversation( - ..., - events_manager=CustomEventsManager() -) -``` +app = FastAPI(docs_url=None) -You can also pass it into a `TelephonyServer`, like: +logging.basicConfig() +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) +class CustomEventsManager(events_manager.EventsManager): + def __init__(self): + super().__init__(subscriptions=[EventType.TRANSCRIPT_COMPLETE]) + + def handle_event(self, event: Event): + if event.type == EventType.TRANSCRIPT_COMPLETE: + transcript_complete_event = typing.cast(TranscriptCompleteEvent, event) + add_transcript( + transcript_complete_event.conversation_id, + transcript_complete_event.transcript, + ) + +events_manager_instance = CustomEventsManager() +await events_manager_instance.start() ``` -server = TelephonyServer( - ..., - events_manager=CustomEventsManager() -) -``` + +In this example, a custom `EventsManager` subclass is created with a subscription to the `TRANSCRIPT_COMPLETE` event. The `handle_event` method is overridden to save the transcript to a file using the `add_transcript` method when the `TRANSCRIPT_COMPLETE` event is received. diff --git a/docs/open-source/language-support.mdx b/docs/open-source/language-support.mdx index 004c5f089..694887fb6 100644 --- a/docs/open-source/language-support.mdx +++ b/docs/open-source/language-support.mdx @@ -22,9 +22,11 @@ synthesizer_config = AzureSynthesizerConfig( ) ``` +See the [full list of supported voices](https://docs.microsoft.com/en-us/azure/cognitive-services/speech-service/language-support?tabs=tts). + ## Transcription -The transcriber used in vocode is also configurable. By default, `DeepgramTranscriber` is used which supports [over 35 languages](https://developers.deepgram.com/docs/languages-overview). +The transcriber used in vocode is also configurable. By default, `DeepgramTranscriber` is used which supports [over 25 languages](https://developers.deepgram.com/docs/languages-overview). To configure a different language model, modify the language code passed to `TranscriberConfig` when initializing the config object (`en-US` is the default): @@ -33,11 +35,10 @@ from vocode.streaming.models.transcriber import DeepgramTranscriberConfig transcriber_config = DeepgramTranscriberConfig( language="es" # Spanish - model="nova-2" # Most languages are supported on the Nova 2 model ) ``` -***Note: the default model for Deepgram is Nova, so you must pass `model="nova-2"` to use that model.*** +See the [Deepgram docs](https://developers.deepgram.com/docs/languages-overview) for the list of supported lamguages. Other transcription services like Google Cloud Speech or Assembly AI could also be used by configuring the appropriate `TranscriberConfig`. diff --git a/docs/open-source/playground.mdx b/docs/open-source/playground.mdx index f6acb2da9..662e8f97e 100644 --- a/docs/open-source/playground.mdx +++ b/docs/open-source/playground.mdx @@ -8,11 +8,6 @@ test transcribers, agents, and synthesizers. To begin, clone the [repo](https://github.com/vocodedev/vocode-python). -Install the core packages by running the following: -``` -poetry install -``` - # Streaming ## Transcriber @@ -37,11 +32,9 @@ make chat ## Synthesizer -1. Install the synthesizer packages by running `poetry install --extras=synthesizers` - -2. Update your synthesizer configuration in `playground/streaming/synthesizer/synthesize.py` +1. Update your synthesizer configuration in `playground/streaming/synthesizer/synthesize.py` -3. Run the following script to synthesize text to speech and play it to your speaker: +2. Run the following script to synthesize text to speech and play it to your speaker: ``` make synthesize diff --git a/docs/open-source/react-quickstart.mdx b/docs/open-source/react-quickstart.mdx index 08f89cf6e..1b3a7372d 100644 --- a/docs/open-source/react-quickstart.mdx +++ b/docs/open-source/react-quickstart.mdx @@ -13,7 +13,7 @@ Or, start from our [Replit template](https://replit.com/@vocode/Simple-Conversat ## Setting up the conversation -Our self-hosted backend allows you to expose a websocket route that operates like `StreamingConversation`. +Our self-hosted backend allows you to expose a websocket route in the same format that our hosted backend does. This allows you to deploy any agent you'd like into the conversation. To get started, clone the Vocode repo or copy the [client backend app](https://github.com/vocodedev/vocode-python/tree/main/apps/client_backend) directory. @@ -56,25 +56,35 @@ uvicorn main:app --port 3000 You now have a server with a Vocode websocket route at localhost:3000! You can now use the `useConversation` hook with your self-hosted backend as follows: -```typescript -import { useConversation } from "vocode"; - -const { status, start, stop, error, analyserNode } = useConversation({ +```javascript +const { status, start, stop, analyserNode } = useConversation({ backendUrl: "", // looks like ws://localhost:3000/conversation or wss://asdf1234.ngrok.app/conversation if using ngrok audioDeviceConfig: {}, }); ``` -Use the `status`, `start`, and `stop` objects within your React components to control conversations with your self-hosted backend, e.g. +# Demo installation and setup + +Clone the `vocode-react-demo` [repository](https://github.com/vocodedev/vocode-react-demo). + +``` +$ git clone https://github.com/vocodedev/vocode-react-demo.git +``` + +Run npm install inside the directory to download all of the dependencies. + +``` +$ npm install +``` + +Set your Client SDK key inside of your `.env` -```jsx -<> - {status === "idle" &&

Press me to talk!

} - {status == "error" && error &&

{error.message}

} +``` +REACT_APP_VOCODE_API_KEY=YOUR KEY HERE +``` + +Start the application - - +``` +$ npm start ``` diff --git a/docs/open-source/tracing.mdx b/docs/open-source/tracing.mdx new file mode 100644 index 000000000..537e32885 --- /dev/null +++ b/docs/open-source/tracing.mdx @@ -0,0 +1,95 @@ +--- +title: "Tracing" +description: "Time components of your Vocode conversations" +--- + +# [Beta] Benchmarking script + +The benchmarking script is located at `playground/streaming/benchmark.py`. You can execute the benchmarking script using the CLI which will enable you to evaluate and compare +transcribers, agents, and synthesizers. You can use it primarily to benchmark latency – but it can also be used to compare the quality of the different providers as well. The +feature is in Beta and will continue to be improved upon – feel free to open an issue with any ideas. + +### Using the CLI + +To access the options of the benchmarking script, run + +```bash +python playground/streaming/benchmark.py --help +``` + +This will display all available options. + +To conduct multiple trials and get averaged results, you can control `num_cycles` + +```bash +--{transcriber,agent,synthesizer}_num_cycles 3 # component specific +--all_num_cycles 3 # all components +``` + +To perform a comprehensive test across all supported transcribers, agents, and synthesizers, use the `--all` command. + +With the CLI, you can get the raw output, write them to a file, and create graphs. +To access your results and visualize them, they will be stored in the `benchmark_results` directory by default. You can also change this location using the `--results_dir` and `--results_file` options. If you want to create visual graphs, add the `--create_graphs` option when running your test. + +#### Example: comparing synthesizers + +To compare different synthesizers, use the `--synthesizers` flag followed by the names of the synthesizers you wish to compare. For instance, + +```bash +python playground/streaming/benchmark.py --synthesizers Google Azure --synthesizer_text "Your text here" +``` + +#### Example: comparing transcribers + +To compare different transcribers, you can use the `--transcribers` flag followed by the names of the transcribers you wish to compare. For example, + +```bash +python playground/streaming/benchmark.py --transcribers deepgram assemblyai --transcriber_audio sample.wav +``` + +You can specify `transcriber_use_mic` instead of `--transcriber_audio` to use your microphone as the audio source. + +#### Example: comparing agents + +To compare different agents, use the `--agents` flag followed by the names of the agents you want to compare. For example, + +```bash +python playground/streaming/benchmark.py --agents openai anthropic +``` + +You can set the prompt preamble with the `--agent_prompt_preamble` argument and the first input with the `--agent_first_input` option. + +# Tracing your application + +At the top of `quickstarts/streaming_conversation.py`, include the following code: + +```python +from opentelemetry import trace +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import SimpleSpanProcessor, SpanExporter +from opentelemetry.sdk.resources import Resource + + +class PrintDurationSpanExporter(SpanExporter): + def __init__(self): + super().__init__() + self.spans = defaultdict(list) + + def export(self, spans): + for span in spans: + duration_ns = span.end_time - span.start_time + duration_s = duration_ns / 1e9 + self.spans[span.name].append(duration_s) + + def shutdown(self): + for name, durations in self.spans.items(): + print(f"{name}: {sum(durations) / len(durations)}") + + +trace.set_tracer_provider(TracerProvider(resource=Resource.create({}))) +trace.get_tracer_provider().add_span_processor( + SimpleSpanProcessor(PrintDurationSpanExporter()) +) +``` + +This will print out stats about the conversation after it ends. diff --git a/docs/open-source/turn-based-conversation.mdx b/docs/open-source/turn-based-conversation.mdx index d2e6a03e3..18177ba93 100644 --- a/docs/open-source/turn-based-conversation.mdx +++ b/docs/open-source/turn-based-conversation.mdx @@ -9,64 +9,55 @@ A turn-based conversation is a communication system designed for applications wh This model differs from streaming conversations that try to mimic natural human discourse. Instead, it fits applications triggered by some kind of user input. For example, consider a voice memo application where the user records a message, and the agent generates a complete response. -A turn-based conversation system is perfect for applications that don't require interruptions and have a controlled conversation flow. Each user input is treated as a discrete event, +A turn-based conversation system is perfect for applications that don't require real-time responses or constant back-and-forths. +This design reduces complexity and allows for a more controlled conversation flow. Each user input is treated as a discrete event, giving the system time to generate and deliver a full and meaningful response. ## Turn-based quickstart -The example below demonstrates a turn-based conversation, using a ChatGPT agent for text generation, WhisperTranscriber for speech-to-text, -and AzureSynthesizer for text-to-speech. User interactions trigger the beginning and end of the recording, signaling the system when to listen and when to respond. You can run it with -``` -make turn_based_conversation -``` - -*Remember to replace OPENAI_API_KEY and AZURE_SPEECH_KEY with your actual API keys and set the appropriate Azure region. You can also set these variables in a `.env` file and source it in your terminal. -You can also customize the voice, system prompt, and initial message as needed. The code can be found [here](https://github.com/vocodedev/vocode-python/blob/main/quickstarts/turn_based_conversation.py).* +The code can be found [here](https://github.com/vocodedev/vocode-python/blob/main/quickstarts/turn_based_conversation.py) ```python -class Settings(BaseSettings): - """ - Settings for the turn-based conversation quickstart. - These parameters can be configured with environment variables. - """ - - openai_api_key: str = "ENTER_YOUR_OPENAI_API_KEY_HERE" - azure_speech_key: str = "ENTER_YOUR_AZURE_KEY_HERE" - - azure_speech_region: str = "eastus" - - # This means a .env file can be used to overload these settings - # ex: "OPENAI_API_KEY=my_key" will set openai_api_key over the default above - model_config = SettingsConfigDict( - env_file=".env", - env_file_encoding="utf-8", - ) +import logging +from dotenv import load_dotenv +from vocode import getenv +from vocode.helpers import create_turn_based_microphone_input_and_speaker_output +from vocode.turn_based.agent.chat_gpt_agent import ChatGPTAgent +from vocode.turn_based.synthesizer.azure_synthesizer import AzureSynthesizer +from vocode.turn_based.synthesizer.eleven_labs_synthesizer import ElevenLabsSynthesizer +from vocode.turn_based.transcriber.whisper_transcriber import WhisperTranscriber +from vocode.turn_based.turn_based_conversation import TurnBasedConversation + +logging.basicConfig() +logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) +load_dotenv() -settings = Settings() +# See https://api.elevenlabs.io/v1/voices +ADAM_VOICE_ID = "pNInz6obpgDQGcFmaJgB" if __name__ == "__main__": ( microphone_input, speaker_output, - ) = create_turn_based_microphone_input_and_speaker_output( - use_default_devices=False, - ) + ) = create_turn_based_microphone_input_and_speaker_output(use_default_devices=False) conversation = TurnBasedConversation( input_device=microphone_input, output_device=speaker_output, - transcriber=WhisperTranscriber(api_key=settings.openai_api_key), + transcriber=WhisperTranscriber(api_key=getenv("OPENAI_API_KEY")), agent=ChatGPTAgent( system_prompt="The AI is having a pleasant conversation about life", initial_message="Hello!", - api_key=settings.openai_api_key, + api_key=getenv("OPENAI_API_KEY"), ), synthesizer=AzureSynthesizer( - api_key=settings.azure_speech_key, - region=settings.azure_speech_region, + api_key=getenv("AZURE_SPEECH_KEY"), + region=getenv("AZURE_SPEECH_REGION"), voice_name="en-US-SteffanNeural", ), + logger=logger, ) print("Starting conversation. Press Ctrl+C to exit.") while True: @@ -77,4 +68,16 @@ if __name__ == "__main__": conversation.end_speech_and_respond() except KeyboardInterrupt: break -``` \ No newline at end of file +``` + +This example demonstrates a turn-based conversation, using a ChatGPT agent for text generation, WhisperTranscriber for speech-to-text, +and AzureSynthesizer for text-to-speech. User interactions trigger the beginning and end of the recording, signaling the system when to listen and when to respond. + +Remember to replace OPENAI_API_KEY and AZURE_SPEECH_KEY with your actual API keys and set the appropriate Azure region. +You can also customize the voice, system prompt, and initial message as needed. + +## React turn-based quickstart + +🚧 Under construction + +If you want to work on a sample react app for this, reach out to us! diff --git a/docs/open-source/using-synthesizers.mdx b/docs/open-source/using-synthesizers.mdx index 013ce2372..99c51eaee 100644 --- a/docs/open-source/using-synthesizers.mdx +++ b/docs/open-source/using-synthesizers.mdx @@ -16,10 +16,10 @@ Vocode currently supports the following synthesizers: 3. Eleven Labs 4. Rime 5. Play.ht -6. GTTS (Google Text-to-Speech) -7. Stream Elements -8. Bark -9. Amazon Polly +6. Coqui TTS +7. GTTS (Google Text-to-Speech) +8. Stream Elements +9. Bark These synthesizers are defined using their respective configuration classes, which are subclasses of the `SynthesizerConfig` class. @@ -46,43 +46,6 @@ server = InboundCallServer( In this example, the `ElevenLabsSynthesizerConfig.from_telephone_output_device()` method is used to create a configuration object for the Eleven Labs synthesizer. The method hardcodes some values like the `sampling_rate` and `audio_encoding` for compatibility with telephone output devices. -#### ElevenLabs Input Streaming - -You can try out our experimental implementation of ElevenLabs' [input streaming API](https://elevenlabs.io/docs/api-reference/websockets) by passing in `experimental_websocket=True` into the config and using the `ElevenLabsWSSynthesizer`, like: - -```python -from vocode.streaming.synthesizer.eleven_labs_websocket_synthesizer import ElevenLabsWSSynthesizer -from vocode.streaming.models.synthesizer import ElevenLabsSynthesizerConfig - -... -synthesizer_config=ElevenLabsSynthesizerConfig.from_telephone_output_device( - api_key=os.getenv("ELEVENLABS_API_KEY"), - voice_id=os.getenv("YOUR VOICE ID"), - experimental_websocket=True -) -... -synthesizer=ElevenLabsWSSynthesizer(ElevenLabsSynthesizerConfig.from_output_device( - speaker_output, - api_key=os.getenv("ELEVENLABS_API_KEY"), - voice_id=os.getenv("YOUR VOICE ID"), - experimental_websocket=True -)) -... -``` - -#### Play.ht v2 - -We now support Play.ht's new [gRPC streaming API](https://docs.play.ht/reference/python-sdk-audio-streaming), which runs much faster than their HTTP API and is designed for realtime communication. - -```python -... -synthesizer_config=PlayHtSynthesizerConfig.from_telephone_output_device( - api_key=os.getenv("PLAY_HT_API_KEY"), - user_id=os.getenv("PLAY_HT_USER_ID"), -) -... -``` - ### Example 2: Using Azure in StreamingConversation locally ```python @@ -104,3 +67,22 @@ conversation = StreamingConversation( In this example, the `AzureSynthesizerConfig.from_output_device()` method is used to create a configuration object for the Azure synthesizer. The method takes a `speaker_output` object as an argument, and extracts the `sampling_rate` and `audio_encoding` from the output device. + +## When to Use Configs vs. Synthesizer Objects + +- For everything except `StreamingConversation`, you must use configuration objects. +- For `StreamingConversation`, you can use the actual synthesizer object, but you still need to initialize it with a configuration object. + +## Synthesizer Comparisons + +| Provider | Latency | Voice Cloning | Natural Sounding | Notes | +| ----------------- | ------- | ------------- | ---------------- | ----------- | +| Azure (Microsoft) | Low | No | | | +| Google | Low | No | | | +| Eleven Labs | High | Yes | | | +| Rime | Low | No | | | +| Play.ht | High | Yes | | | +| Coqui TTS | | | | Open source | +| GTTS | | | | | +| Stream Elements | | | | | +| Bark | | | | | diff --git a/docs/open-source/using-transcribers.mdx b/docs/open-source/using-transcribers.mdx index f4a272478..8fdc71f7b 100644 --- a/docs/open-source/using-transcribers.mdx +++ b/docs/open-source/using-transcribers.mdx @@ -33,7 +33,7 @@ from vocode.streaming.models.transcriber import DeepgramTranscriberConfig, Punct server = InboundCallServer( ... transcriber_config=DeepgramTranscriberConfig.from_telephone_input_device( - endpointing_config=DeepgramEndpointingConfig() + endpointing_config=PunctuationEndpointingConfig() ), ... ) @@ -56,7 +56,7 @@ async def main(): output_device=speaker_output, transcriber=DeepgramTranscriber( DeepgramTranscriberConfig.from_input_device( - microphone_input, endpointing_config=DeepgramEndpointingConfig() + microphone_input, endpointing_config=PunctuationEndpointingConfig() ) ), ... @@ -66,4 +66,11 @@ async def main(): In this example, the `DeepgramTranscriberConfig.from_input_device()` method is used to create a configuration object for the Deepgram transcriber for use in a local `StreamingConversation`. The method takes a `microphone_input` object as an argument and extracts the `sampling_rate`, `audio_encoding`, and `chunk_size` from the input device. -See [Conversation Mechanics](/open-source/conversation-mechanics) for more information about endpointing. +## Endpointing + +Endpointing is the process of understanding when someone has finished speaking. The `EndpointingConfig` controls how this is done. There are a couple of different ways to configure endpointing: + +- Time-based endpointing: This method considers the speaker to be finished when there is a certain duration of silence. +- Punctuation-based endpointing: This method considers the speaker to be finished when there is a certain duration of silence after a punctuation mark. + +In the first example, the `PunctuationEndpointingConfig` is used to configure the Deepgram transcriber for punctuation-based endpointing. From 065607b4e62b98a97bdd10d460ce9325618eb465 Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Thu, 13 Jun 2024 11:19:58 -0700 Subject: [PATCH 23/25] Unset docs changes (cont.) --- docs/open-source/action-phrase-triggers.mdx | 86 --------------------- docs/open-source/conversation-mechanics.mdx | 53 ------------- docs/open-source/logging-with-loguru.mdx | 73 ----------------- 3 files changed, 212 deletions(-) delete mode 100644 docs/open-source/action-phrase-triggers.mdx delete mode 100644 docs/open-source/conversation-mechanics.mdx delete mode 100644 docs/open-source/logging-with-loguru.mdx diff --git a/docs/open-source/action-phrase-triggers.mdx b/docs/open-source/action-phrase-triggers.mdx deleted file mode 100644 index e7a8dc2c5..000000000 --- a/docs/open-source/action-phrase-triggers.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: 'Action Triggers' -description: 'Activate actions with function calls or specific phrases' ---- -## What are function calls? -[Function calls](https://platform.openai.com/docs/guides/function-calling) allow modern Large Language Models (LLMs) like ChatGPT to perform tasks outside of text generation. -For example, if I create a math assistant with ChatGPT, I might make a "multiply" function that ChatGPT can call to multiply two numbers together. - -If you add an action to a vocode agent, its corresponding function calling schema is added to each ChatGPT query. If the function call is outputted by ChatGPT, the corresponding action is triggered automatically. - -***Note:*** *In vocode agents, ChatGPT can return a text response alongside a function call. In this scenario, the text is synthesized and played first, then the action is run.* - -## What are phrase triggers? - -Phrase triggers are text phrases that activate an action when produced by an agent. Phrase triggers are useful in production use-cases where consistency and reliability are important, since text outputs are easier to control in comparison to function calls. - -## Configuring action triggers -Each vocode action config contains an `action_trigger` field to specify how the action is triggered. The default trigger is function calling. The examples below demonstrate how to set action triggers for an `EndConversation` action config: - -**Function calls:** -```python -from vocode.streaming.action.end_conversation import EndConversationVocodeActionConfig -from vocode.streaming.models.actions import FunctionCallActionTrigger - -EndConversationVocodeActionConfig( - type="action_end_conversation", - action_trigger=FunctionCallActionTrigger( - type="action_trigger_function_call" - ) -) -``` -***Note:*** *You can also leave `action_trigger` field empty and vocode will default to function calls.* - -**Phrase triggers:** - -```python -from vocode.streaming.action.end_conversation import EndConversationVocodeActionConfig -from vocode.streaming.models.actions import PhraseBasedActionTrigger, PhraseBasedActionTriggerConfig, PhraseTrigger - -EndConversationVocodeActionConfig( - type="action_end_conversation", - action_trigger=PhraseBasedActionTrigger( - type = "action_trigger_phrase_based", - config: PhraseBasedActionTriggerConfig( - phrase_triggers = [ - PhraseTrigger( - phrase="Ending conversation now", - condition="phrase_condition_type_contains" - ), - # Additional phrase triggers can be listed here - ] - ) - ) -) -``` -For the code above, if the agent says 'Ending conversation now', the end conversation action will automatically be taken. -You can add multiple phrase triggers for an action by passing a list of `PhraseTrigger` instances. - -The `phrase_condition_type_contains` condition configures the agent to run the action if its output *contains* the phrase. So, the action will also be run if the agent -says 'I am ending conversation now'. - -## Example Scenario - -Let's assume we have an action called `TurnOnLight` that turns on your bedroom light when activated. Take the following conversation: -```plaintext -Human: Hello -AI: How can I assist you today? -Human: Please turn on the lights. -``` - -If the action is triggered via a function call, the bot may respond with: -```plaintext -AI: Sure! -BOT_ACTION_START: Running `action_turn_on_light` -``` -or it may run the action without saying anything. - -If we use a phrase trigger instead, we may do the following: -1. In our prompt, write "If the human asks to turn on the lights, say 'I will turn on the lights now' verbatim" -2. Configure `TurnOnLight` with "I will turn on the lights now" as its phrase trigger - -Then, the bot will respond with: -``` -AI: I will turn on the lights now. -BOT_ACTION_START: Running `action_turn_on_light` -``` \ No newline at end of file diff --git a/docs/open-source/conversation-mechanics.mdx b/docs/open-source/conversation-mechanics.mdx deleted file mode 100644 index 513eef503..000000000 --- a/docs/open-source/conversation-mechanics.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: "Conversation Mechanics" -description: "How to tune the responsiveness in Vocode conversations" ---- - -Building two-way conversations with an AI is a highly use-case specific task - how realistic the conversation is depends greatly on the nature of the conversation itself. In this guide, we'll cover some of the dials you can turn to configure the mechanics of a conversation in Vocode. - -# Endpointing - -Endpointing is the process of understanding when someone has finished speaking. The `EndpointingConfig` controls how this is done. There are a couple of different ways to configure endpointing: - -We provide `DeepgramEndpointingConfig()` which has some reasonable defaults and knobs to suit most use-cases (but only works with the Deepgram transcriber). - -``` -class DeepgramEndpointingConfig(EndpointingConfig, type="deepgram"): # type: ignore - vad_threshold_ms: int = 500 - utterance_cutoff_ms: int = 1000 - time_silent_config: Optional[TimeSilentConfig] = Field(default_factory=TimeSilentConfig) - use_single_utterance_endpointing_for_first_utterance: bool = False -``` - -- `vad_threshold_ms`: translates to [Deepgram's `endpointing` feature](https://developers.deepgram.com/docs/endpointing#enable-feature) -- `utterance_cutoff_ms`: uses [Deepgram's Utterance End features](https://developers.deepgram.com/docs/utterance-end) -- `time_silent_config`: is a Vocode specific parameter that marks an utterance final if we haven't seen any new words in X seconds -- `use_single_utterance_endpointing_for_first_utterance`: Uses `is_final` instead of `speech_final` for endpointing for the first utterance (works really well for outbound conversations, where the user's first utterance is something like "Hello?") - see [this doc on Deepgram](https://developers.deepgram.com/docs/understand-endpointing-interim-results) for more info. - -Endpointing is highly use-case specific - building a realistic experience for this greatly depends on the person speaking to the AI. Here are few paradigms that we've used to help you along the way: - -- Time-based endpointing: This method considers the speaker to be finished when there is a certain duration of silence. -- Punctuation-based endpointing: This method considers the speaker to be finished when there is a certain duration of silence after a punctuation mark. - -# Interruptions - -When the AI speaks in a `StreamingConversation`, it can be interrupted by the user. `AgentConfig` itself provides a parameter called `interrupt_sensitivity` that can be used to control how sensitive the AI is to interruptions. Interrupt sensitivity has two options: low (default) and high. Low sensitivity makes the bot ignore backchannels (e.g. “sure”, “uh-huh”) while the bot is speaking. High sensitivity makes the agent treat any word from the human as an interruption. - -The implementation of this configuration is in `StreamingConversation.TranscriptionsWorker` - in order to make this work well, you may need to fork Vocode and override this behavior, but it provides a good starting place for most use-cases. - -Stay tuned, more dials to come here soon! - -# Conversation Speed - -`StreamingConversation` also exposes a parameter called `conversation_speed`, which controls the length of endpointing pauses, i.e. how long the bot will wait before responding to the human. This includes normal utterances from the human as well as interruptions. - -The amount of time the bot waits inversely scales with the `conversation_speed` value. So a bot with `conversation_speed` of 2 responds in half the time compared to a `conversation_speed` of 1. Likewise a `conversation_speed` of 0.5 means the bot takes twice as long to respond. - -```python -conversation = StreamingConversation( - speed_coefficient=2 - ... -) -``` - -Based on the speed of the user's speech (we calculate the WPM from each final utterance that goes through the pipeline), the `speed_coefficient` updates throughout the course of the conversation - see `vocode.streaming.utils.speed_manager` to see this implementation! diff --git a/docs/open-source/logging-with-loguru.mdx b/docs/open-source/logging-with-loguru.mdx deleted file mode 100644 index 4205468e1..000000000 --- a/docs/open-source/logging-with-loguru.mdx +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: "Logging with Loguru" -description: "Make logging set up less painful for local and production usage!" ---- - -Loguru is a powerful and flexible logging library for Python that simplifies logging setup and usage. It provides a more intuitive and feature-rich alternative to Python's built-in logging module. - -## Why Use Loguru? - -Loguru offers several advantages over the standard logging module: - -- **Ease of Use**: Loguru simplifies the process of setting up and using loggers. -- **Rich Features**: It provides advanced features like automatic exception catching, structured logging, and more. -- **Flexibility**: Loguru allows for easy configuration of different logging formats and destinations. - -## Using the Vocode Implementation - -The Vocode implementation of Loguru provides a seamless way to integrate logging into your application. It includes custom handlers and configuration functions to streamline the setup process. When utilizing the JSON logging configuration, it'll also pull relevant environment variables such as `conversation_id` and include them in the JSON output for better production debugging! - -### Setting Up Logging - -To set up logging in your application, you can use the provided configuration functions. Here's how to configure pretty printing for local development and JSON logging for production: - -#### Pretty Printing Locally - -To enable pretty printing locally, use the `configure_pretty_logging` function. This will set up Loguru to output logs with colored formatting, making them easier to read during development. - -```python -from vocode.logging import configure_pretty_logging - -configure_pretty_logging() -``` - -#### JSON Logging in Production - -For production environments, you may want to log in JSON format for better integration with logging systems and easier parsing. Use the `configure_json_logging` function to set this up. - -```python -from vocode.logging import configure_json_logging - -configure_json_logging() -``` - -### Why Use Different Setups? - -Using different logging setups for local and production environments can be beneficial for several reasons: - -- **Readability**: Pretty printing makes logs easier to read during development, helping you quickly identify issues. -- **Structured Logging**: JSON logging provides structured logs that are easier to parse and analyze in production, especially when using log aggregation and monitoring tools. - -## Example Snippet - -Here's an example of how you can set up logging in your application: - -```python -import os -from vocode.logging import configure_pretty_logging, configure_json_logging - -DEPLOYED_ENVIRONMENTS = ["production", "staging"] -ENVIRONMENT = os.environ.get("ENVIRONMENT", "development") - -def configure_logging() -> None: # pragma: no cover - """Configures logging.""" - if ENVIRONMENT in DEPLOYED_ENVIRONMENTS: - configure_json_logging() - else: - configure_pretty_logging() - -# Configure logging based on the environment -configure_logging() - -# Your application code here -``` From 449cbdb67319ae7ca7a7b3a67bcd2a8c83d8e9f1 Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Thu, 13 Jun 2024 11:21:27 -0700 Subject: [PATCH 24/25] unset poetry version change --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 32785b226..b613eb7bf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "vocode" -version = "0.1.111" +version = "0.1.112a0" description = "The all-in-one voice SDK" authors = ["Ajay Raj "] license = "MIT License" From 9e932965c1be4ad6c9c8d6813f52c8b5755a43b2 Mon Sep 17 00:00:00 2001 From: Ajay Raj Date: Thu, 13 Jun 2024 11:22:33 -0700 Subject: [PATCH 25/25] update poetry.lock --- poetry.lock | 625 +++++++++++++++------------------------------------- 1 file changed, 177 insertions(+), 448 deletions(-) diff --git a/poetry.lock b/poetry.lock index dc6d8c3cb..c1b8234c6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. [[package]] name = "aiohttp" @@ -195,24 +195,6 @@ doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphin test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] trio = ["trio (>=0.23)"] -[[package]] -name = "asttokens" -version = "2.4.1" -description = "Annotate AST trees with source code positions" -optional = false -python-versions = "*" -files = [ - {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, - {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, -] - -[package.dependencies] -six = ">=1.12.0" - -[package.extras] -astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] -test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] - [[package]] name = "async-timeout" version = "4.0.3" @@ -245,17 +227,17 @@ tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "p [[package]] name = "azure-cognitiveservices-speech" -version = "1.37.0" +version = "1.38.0" description = "Microsoft Cognitive Services Speech SDK for Python" optional = false python-versions = ">=3.7" files = [ - {file = "azure_cognitiveservices_speech-1.37.0-py3-none-macosx_10_14_x86_64.whl", hash = "sha256:906d6bf65176e93464e2d763dd074ca00c48cfe1a896371fcdcb155a500910f7"}, - {file = "azure_cognitiveservices_speech-1.37.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:54ec8dd55d4dbd9058c61909e08485d3761d6d30954da189e1b17d84daf5e2e0"}, - {file = "azure_cognitiveservices_speech-1.37.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:685424689725d2d4115485998c0888c8b5b502259037ff533e5a834575f80b66"}, - {file = "azure_cognitiveservices_speech-1.37.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:384f66786c2335165035270897b34d0b91736a1fdf38f7696e9a227075cb2489"}, - {file = "azure_cognitiveservices_speech-1.37.0-py3-none-win32.whl", hash = "sha256:343d5f449ccd6c9b53cd37dd46a70ece0905243517df7a0c047779e55072254c"}, - {file = "azure_cognitiveservices_speech-1.37.0-py3-none-win_amd64.whl", hash = "sha256:a18fb45490cdcd681407ccaad9560fb14dda1c8276de297e219ea1a880467e28"}, + {file = "azure_cognitiveservices_speech-1.38.0-py3-none-macosx_10_14_x86_64.whl", hash = "sha256:18dce915ab032711f687abb3297dd19176b9cbea562b322ee6fa7365ef4a5091"}, + {file = "azure_cognitiveservices_speech-1.38.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:9dd0800fbc4a8438c6dfd5747a658251914fe2d205a29e9b46158cadac6ab381"}, + {file = "azure_cognitiveservices_speech-1.38.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:1c344e8a6faadb063cea451f0301e13b44d9724e1242337039bff601e81e6f86"}, + {file = "azure_cognitiveservices_speech-1.38.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:1e002595a749471efeac3a54c80097946570b76c13049760b97a4b881d9d24af"}, + {file = "azure_cognitiveservices_speech-1.38.0-py3-none-win32.whl", hash = "sha256:16a530e6c646eb49ea0bc05cb45a9d28b99e4b67613f6c3a6c54e26e6bf65241"}, + {file = "azure_cognitiveservices_speech-1.38.0-py3-none-win_amd64.whl", hash = "sha256:1d38d8c056fb3f513a9ff27ab4e77fd08ca487f8788cc7a6df772c1ab2c97b54"}, ] [[package]] @@ -659,30 +641,19 @@ test-randomorder = ["pytest-randomly"] [[package]] name = "dataclasses-json" -version = "0.6.6" +version = "0.6.7" description = "Easily serialize dataclasses to and from JSON." optional = true python-versions = "<4.0,>=3.7" files = [ - {file = "dataclasses_json-0.6.6-py3-none-any.whl", hash = "sha256:e54c5c87497741ad454070ba0ed411523d46beb5da102e221efb873801b0ba85"}, - {file = "dataclasses_json-0.6.6.tar.gz", hash = "sha256:0c09827d26fffda27f1be2fed7a7a01a29c5ddcd2eb6393ad5ebf9d77e9deae8"}, + {file = "dataclasses_json-0.6.7-py3-none-any.whl", hash = "sha256:0dbf33f26c8d5305befd61b39d2b3414e8a407bedc2834dea9b8d642666fb40a"}, + {file = "dataclasses_json-0.6.7.tar.gz", hash = "sha256:b6b3e528266ea45b9535223bc53ca645f5208833c29229e847b3f26a1cc55fc0"}, ] [package.dependencies] marshmallow = ">=3.18.0,<4.0.0" typing-inspect = ">=0.4.0,<1" -[[package]] -name = "decorator" -version = "5.1.1" -description = "Decorators for Humans" -optional = false -python-versions = ">=3.5" -files = [ - {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, - {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, -] - [[package]] name = "deprecated" version = "1.2.14" @@ -733,18 +704,17 @@ wmi = ["wmi (>=1.5.1)"] [[package]] name = "elevenlabs" -version = "1.2.2" +version = "1.3.0" description = "" optional = false python-versions = "<4.0,>=3.8" files = [ - {file = "elevenlabs-1.2.2-py3-none-any.whl", hash = "sha256:60b92b0e2aabdfba93a43569f207f8a2ad397492519b8e11a2eebb32807ddefa"}, - {file = "elevenlabs-1.2.2.tar.gz", hash = "sha256:ebd02869b95602b8956874dd727981bb49ad16b9a3c2f5901193d838213694aa"}, + {file = "elevenlabs-1.3.0-py3-none-any.whl", hash = "sha256:a4191799f83641be39c845a413381cc8881225eb53c290f1f8821d1648e0688e"}, + {file = "elevenlabs-1.3.0.tar.gz", hash = "sha256:5bb1b21497f60785a8b7b36fac165e7610ef249356947dd4272714825a6c26d4"}, ] [package.dependencies] httpx = ">=0.21.2" -ipython = ">=7.0" pydantic = ">=1.9.2" requests = ">=2.20" typing_extensions = ">=4.0.0" @@ -779,20 +749,6 @@ files = [ [package.extras] test = ["pytest (>=6)"] -[[package]] -name = "executing" -version = "2.0.1" -description = "Get the currently executing AST node of a frame, and other information" -optional = false -python-versions = ">=3.5" -files = [ - {file = "executing-2.0.1-py2.py3-none-any.whl", hash = "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc"}, - {file = "executing-2.0.1.tar.gz", hash = "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147"}, -] - -[package.extras] -tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] - [[package]] name = "fakeredis" version = "2.23.2" @@ -862,18 +818,18 @@ standard = ["fastapi", "uvicorn[standard] (>=0.15.0)"] [[package]] name = "filelock" -version = "3.14.0" +version = "3.15.1" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"}, - {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"}, + {file = "filelock-3.15.1-py3-none-any.whl", hash = "sha256:71b3102950e91dfc1bb4209b64be4dc8854f40e5f534428d8684f953ac847fac"}, + {file = "filelock-3.15.1.tar.gz", hash = "sha256:58a2549afdf9e02e10720eaa4d4470f56386d7a6f72edd7d0596337af8ed7ad8"}, ] [package.extras] docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] typing = ["typing-extensions (>=4.8)"] [[package]] @@ -1034,13 +990,13 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] [[package]] name = "google-auth" -version = "2.29.0" +version = "2.30.0" description = "Google Authentication Library" optional = true python-versions = ">=3.7" files = [ - {file = "google-auth-2.29.0.tar.gz", hash = "sha256:672dff332d073227550ffc7457868ac4218d6c500b155fe6cc17d2b13602c360"}, - {file = "google_auth-2.29.0-py2.py3-none-any.whl", hash = "sha256:d452ad095688cd52bae0ad6fafe027f6a6d6f560e810fec20914e17a09526415"}, + {file = "google-auth-2.30.0.tar.gz", hash = "sha256:ab630a1320f6720909ad76a7dbdb6841cdf5c66b328d690027e4867bdfb16688"}, + {file = "google_auth-2.30.0-py2.py3-none-any.whl", hash = "sha256:8df7da660f62757388b8a7f249df13549b3373f24388cb5d2f1dd91cc18180b5"}, ] [package.dependencies] @@ -1430,44 +1386,6 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] -[[package]] -name = "ipython" -version = "8.25.0" -description = "IPython: Productive Interactive Computing" -optional = false -python-versions = ">=3.10" -files = [ - {file = "ipython-8.25.0-py3-none-any.whl", hash = "sha256:53eee7ad44df903a06655871cbab66d156a051fd86f3ec6750470ac9604ac1ab"}, - {file = "ipython-8.25.0.tar.gz", hash = "sha256:c6ed726a140b6e725b911528f80439c534fac915246af3efc39440a6b0f9d716"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -decorator = "*" -exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} -jedi = ">=0.16" -matplotlib-inline = "*" -pexpect = {version = ">4.3", markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\""} -prompt-toolkit = ">=3.0.41,<3.1.0" -pygments = ">=2.4.0" -stack-data = "*" -traitlets = ">=5.13.0" -typing-extensions = {version = ">=4.6", markers = "python_version < \"3.12\""} - -[package.extras] -all = ["ipython[black,doc,kernel,matplotlib,nbconvert,nbformat,notebook,parallel,qtconsole]", "ipython[test,test-extra]"] -black = ["black"] -doc = ["docrepr", "exceptiongroup", "intersphinx-registry", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "tomli", "typing-extensions"] -kernel = ["ipykernel"] -matplotlib = ["matplotlib"] -nbconvert = ["nbconvert"] -nbformat = ["nbformat"] -notebook = ["ipywidgets", "notebook"] -parallel = ["ipyparallel"] -qtconsole = ["qtconsole"] -test = ["pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath"] -test-extra = ["curio", "ipython[test]", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "trio"] - [[package]] name = "isort" version = "5.13.2" @@ -1496,25 +1414,6 @@ files = [ [package.dependencies] typing-extensions = ">=3.7.4.3" -[[package]] -name = "jedi" -version = "0.19.1" -description = "An autocompletion tool for Python that can be used for text editors." -optional = false -python-versions = ">=3.6" -files = [ - {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"}, - {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"}, -] - -[package.dependencies] -parso = ">=0.8.3,<0.9.0" - -[package.extras] -docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] -qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] -testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] - [[package]] name = "jinja2" version = "3.1.4" @@ -1534,79 +1433,79 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "jiter" -version = "0.4.1" +version = "0.4.2" description = "Fast iterable JSON parser." optional = false python-versions = ">=3.8" files = [ - {file = "jiter-0.4.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3c2370cd8826b484f3fc6ed729cb58510ba24b4bc277c92323a57d35cf4df223"}, - {file = "jiter-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3587af23140a2eb282bba980010dae60f3b8b1579a034c5e869e9b94220a5972"}, - {file = "jiter-0.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df8788d34545d47de864032a78bae49a14b66b67196c73cd95f1c1e3081d9c73"}, - {file = "jiter-0.4.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91bf2d31e906a3ca26fc8ee0cb979e0e51b12aa7e83999c6afea047538f95e5c"}, - {file = "jiter-0.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8586e68702666b6acd919c65f718a09603adcfd8b4c7026bade2441d9e7bd34e"}, - {file = "jiter-0.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:639b766bde088546b5205fd31608502b5b42abee3294b43cc95c6ea8f9a257c3"}, - {file = "jiter-0.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5cb32457296351c98da289d21a092a6c53c75beb80e7127c8e16224ee342c7c7"}, - {file = "jiter-0.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:583263bd81bce5426806cf27ba85e4b97746797fae13c71e50a8689e06e57f81"}, - {file = "jiter-0.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c0e413999a819ccef9b5fd22ef4b9b8c48a98e49da4d09b43ebce286d0d80e26"}, - {file = "jiter-0.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5e50468d5acfef335ba8bc3892bb304354c38ba18acb3f7ae428451e47136e49"}, - {file = "jiter-0.4.1-cp310-none-win32.whl", hash = "sha256:b2ac90b94dd717644c61c8ed0c2ec6e9505bd7314b91a1549680d7f1cb8f1da4"}, - {file = "jiter-0.4.1-cp310-none-win_amd64.whl", hash = "sha256:2509868b8dacf4f65d04b4d951d390f30f403a87a997a14e2db2d232c7a468a7"}, - {file = "jiter-0.4.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b56e4f2fa5767976f2332e9e067010ddfe1379b6456b5458123ba50657c33e02"}, - {file = "jiter-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f813b49db21c946aa010accc54b8e5c9d0007be252bda4738159fa6c65d6d396"}, - {file = "jiter-0.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2933c04ebd77b3e9cf34f80ba45c093739c687c9c5a4fd0a8c701a3bfd90940"}, - {file = "jiter-0.4.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b02ddd65513705ec38211ea48ffc0fde41aa46166d9f7706972daf97b57c8599"}, - {file = "jiter-0.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:88d06af883524e5429d75395bb4ee6ddeda4c30818b2f3e3b8f4afa2dd8f28c0"}, - {file = "jiter-0.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd333eca1090cf21e6359721eecbb2a7fe031cc4db3dd595081430b4a59371c5"}, - {file = "jiter-0.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdc90017cd22dca6b40f2f8518b38363e78aee3cb32f84e1cb08900a598ca91b"}, - {file = "jiter-0.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aedce5b11ca58853d46461e1880079836bfab4e132be2b7d2093ec193081bbc8"}, - {file = "jiter-0.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e55b2f4d2d5066979b0e0e58d85e3fffd0f6e6a0523aab7e0ce75950259387da"}, - {file = "jiter-0.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b3c85c586f1cd71c2a1e78756f6857119947b532379bd9be4338bf3dacf1e87f"}, - {file = "jiter-0.4.1-cp311-none-win32.whl", hash = "sha256:37875f56222f2bb61410e15196d9b91510ccca322c391f3d20c91d667130d15e"}, - {file = "jiter-0.4.1-cp311-none-win_amd64.whl", hash = "sha256:b71758befea8dbdc10e0fb40a776e085eed0e74afef42468ebb58562289e9190"}, - {file = "jiter-0.4.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:93a8869c18a3721e41d7adb289c5c71aea8887eb368a3411219a0afb62955cbe"}, - {file = "jiter-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0ffbc61349f2f27676d40d68e8ef83fc2a9dd2c1464962b1d1b1d8504bccbf85"}, - {file = "jiter-0.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5f1f33e9fd4de4369a8d00fdf2571a8246a942095fb2a9d4cd25135ee675c85"}, - {file = "jiter-0.4.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d8f91a19eba23b4a1bb1e5b64c19cfdbf46604180e5dee40548b53ca13afd2d9"}, - {file = "jiter-0.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a60f8e495448d8e02d291fa9a8522cfe775a10210ba428994f383965e6f6e65"}, - {file = "jiter-0.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7387998c6585ce0f02ae4f5338fabf72b99494860c347f27bc34720290eafb15"}, - {file = "jiter-0.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7cbf41da6506b42db21a1a0befa48e16384591e84e80db002a826ccf07668f1"}, - {file = "jiter-0.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:793ae2499722b9fc31e300abd07418902512109bca17f617598a31a9e17bddce"}, - {file = "jiter-0.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:19f7953b8ada7ee109764ad91d4afb1a9f69b77cde0b890844744c513612dbf8"}, - {file = "jiter-0.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:dcd3d6a142d7b267a8c5f1e28d02759e2e29343b095f6d8aaf463333a842e1f8"}, - {file = "jiter-0.4.1-cp312-none-win32.whl", hash = "sha256:fffdf137c3ab7f0c5facb7c478b57ad3e1eb9b149daff48687844de77b78ab70"}, - {file = "jiter-0.4.1-cp312-none-win_amd64.whl", hash = "sha256:fde004e47a801512c4167f188a6372960374fbd59e635753b3ee536e81953eb3"}, - {file = "jiter-0.4.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b429ba25e05ca28d5e7efa4249032746ac28ec6ad68017ed3ea009989c597911"}, - {file = "jiter-0.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:27df9925d0282c80bdd41613ace7cd799bd6355acdfe25cc48ec16843541999e"}, - {file = "jiter-0.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb68736a0e2b00eda83937c1937f999e8d7dab68820c04343ac2e2eb2c5c2193"}, - {file = "jiter-0.4.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c218458ac32ce0b495f013293867649b40c067a4d7533fa0d70a46f7194febae"}, - {file = "jiter-0.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ebead86e80e352753f6e6f78ca96c12d764a8dbbc7c4b25938ce657ab0e4e879"}, - {file = "jiter-0.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf58f878d43294bea400a9df86ef7796dd2e67969109bce22d337ca77372c69"}, - {file = "jiter-0.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba671e60570cd99b8ed83ce0d82703040dc34c793229ac607f09683ba1981163"}, - {file = "jiter-0.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef0bd8b68ad14f045544989b6ad3758bee6dc01f6924bce5b4fd7060b0a09b1b"}, - {file = "jiter-0.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7888f165a0fe285e015ee18cfcb8b5432c4fa389235b4c24c339ca0cc51ba979"}, - {file = "jiter-0.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7d9c443b2a71a8c3ab6578f5faf7725ad5f63dbb92d87f820eec56de9da0560f"}, - {file = "jiter-0.4.1-cp38-none-win32.whl", hash = "sha256:6f618d1b04493bc9196e466ef59e0a6388eb85e936d1a61833449677643bbdd9"}, - {file = "jiter-0.4.1-cp38-none-win_amd64.whl", hash = "sha256:46b6364a0b2a81cc259768bda131e8528aa3af4312f23f7e10aa04d24f54bbb1"}, - {file = "jiter-0.4.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:6680785a9273a87e463c86a962042d620c00c7bb8100dde1a4c78b2184cdd613"}, - {file = "jiter-0.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:36b10d945b9ccd2e9f2720e37395daf9e63cfa47e5e0e2887c4931888f0800cd"}, - {file = "jiter-0.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78820599693bda34be17119abf9fad1f02e501b4816e47addbee9c5c768fb361"}, - {file = "jiter-0.4.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68697317170d8f851dfe978ba278b886e54e837ecd2a80c4a33ae780a0f19526"}, - {file = "jiter-0.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d126ffc3876cfc1fba6ae2be37f2532b5db593a96cf4b845724b50b44339c4fd"}, - {file = "jiter-0.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b082223f2e7e6f506d837df935f58f25cabf0a2b35902b4ec73fb561fbf2694a"}, - {file = "jiter-0.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13314287782782be8439dfafca50f13fcab18046227068a3a8e8d8ac888f092b"}, - {file = "jiter-0.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3da1346375605926f1ca4604d154ff41f5e3b933c6e01005e534bca2197d919f"}, - {file = "jiter-0.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9b67a97fbce3ec35ee97439c8b786393f71ecbe7458d5e9279d4c172772eac36"}, - {file = "jiter-0.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7b0f34544923bff0f3393aa3d60087686d86089c9361f6530bb5d19ebfb3db47"}, - {file = "jiter-0.4.1-cp39-none-win32.whl", hash = "sha256:b0c93ef95b896a4ce5edff23071e4dcad77c9e9262fcb6ca2b050f781e8335a9"}, - {file = "jiter-0.4.1-cp39-none-win_amd64.whl", hash = "sha256:3db5c83c8655ce031943b6f08434dac1a91e1477b0df452de0c44f3390a9b22c"}, - {file = "jiter-0.4.1.tar.gz", hash = "sha256:741851cf5f37cf3583f2a56829d734c9fd17334770c9a326e6d25291603d4278"}, + {file = "jiter-0.4.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c2b003ff58d14f5e182b875acd5177b2367245c19a03be9a2230535d296f7550"}, + {file = "jiter-0.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b48c77c25f094707731cd5bad6b776046846b60a27ee20efc8fadfb10a89415f"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f50ad6b172bde4d45f4d4ea10c49282a337b8bb735afc99763dfa55ea84a743"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:95f6001e86f525fbbc9706db2078dc22be078b0950de55b92d37041930f5f940"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16646ef23b62b007de80460d303ebb2d81e355dac9389c787cec87cdd7ffef2f"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b4e847c13b0bf1255c711a92330e7a8cb8b5cdd1e37d7db309627bcdd3367ff"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c536589be60e4c5f2b20fadc4db7e9f55d4c9df3551f29ddf1c4a18dcc9dd54"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b3b2763996167830889a854b4ded30bb90897f9b76be78069c50c3ec4540950e"}, + {file = "jiter-0.4.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:675e8ab98c99495091af6b6e9bf2b6353bcf81f25ab6ce27d36127e315b4505d"}, + {file = "jiter-0.4.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e48e43d9d999aaf55f53406b8846ff8cbe3e47ee4b9dc37e5a10a65ce760809f"}, + {file = "jiter-0.4.2-cp310-none-win32.whl", hash = "sha256:881b6e67c50bc36acb3570eda693763c8cd77d590940e06fa6d325d0da52ec1b"}, + {file = "jiter-0.4.2-cp310-none-win_amd64.whl", hash = "sha256:bb8f7b43259efc6add0d721ade2953e064b24e2026d26d979bc09ec080844cef"}, + {file = "jiter-0.4.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:24ad336ac47f274fa83f6fbedcabff9d3387c80f67c66b992688e6a8ba2c47e9"}, + {file = "jiter-0.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fc392a220095730afe365ce1516f2f88bb085a2fd29ea191be9c6e3c71713d9a"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1fdc408de36c81460896de0176f2f7b9f3574dcd35693a0b2c00f4ca34c98e4"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c10ad76722ee6a8c820b0db06a793c08b7d679e5201b9563015bd1e06c959a09"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dbb46d1e9c82bba87f0cbda38413e49448a7df35b1e55917124bff9f38974a23"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:194e28ef4b5f3b61408cb2ee6b6dcbcdb0c9063d01b92b01345b7605692849f5"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f0a447533eccd62748a727e058efa10a8d7cf1de8ffe1a4d705ecb41dad9090"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5f7704d7260bbb88cca3453951af739589132b26e896a3144fa2dae2263716d7"}, + {file = "jiter-0.4.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:01427458bc9550f2eda09d425755330e7d0eb09adce099577433bebf05d28d59"}, + {file = "jiter-0.4.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:159b8416879c0053b17c352f70b67b749ef5b2924c6154318ecf71918aab0905"}, + {file = "jiter-0.4.2-cp311-none-win32.whl", hash = "sha256:f2445234acfb79048ce1a0d5d0e181abb9afd9e4a29d8d9988fe26cc5773a81a"}, + {file = "jiter-0.4.2-cp311-none-win_amd64.whl", hash = "sha256:e15a65f233b6b0e5ac10ddf3b97ceb18aa9ffba096259961641d78b4ee321bd5"}, + {file = "jiter-0.4.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:d61d59521aea9745447ce50f74d39a16ef74ec9d6477d9350d77e75a3d774ad2"}, + {file = "jiter-0.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eef607dc0acc251923427808dbd017f1998ae3c1a0430a261527aa5cbb3a942"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af6bf39954646e374fc47429c656372ac731a6a26b644158a5a84bcdbed33a47"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8f509d23606e476852ee46a2b65b5c4ad3905f17424d9cc19c1dffa1c94ba3c6"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59672774daa44ee140aada0c781c82bee4d9ac5e522966186cfb6b3c217d8a51"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:24a0458efac5afeca254cf557b8a654e17013075a69905c78f88d557f129d871"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8860766d1c293e75c1bb4e25b74fa987e3adf199cac3f5f9e6e49c2bebf092f"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a109f3281b72bbf4921fe43db1005c004a38559ca0b6c4985add81777dfe0a44"}, + {file = "jiter-0.4.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:faa7e667454b77ad2f0ef87db39f4944de759617aadf210ea2b73f26bb24755f"}, + {file = "jiter-0.4.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3512f8b00cafb6780b427cb6282800d2bf8277161d9c917830661bd4ed1d3528"}, + {file = "jiter-0.4.2-cp312-none-win32.whl", hash = "sha256:853b35d508ee5b66d06630473c1c0b7bb5e29bf4785c9d2202437116c94f7e21"}, + {file = "jiter-0.4.2-cp312-none-win_amd64.whl", hash = "sha256:4a3a8197784278eb8b24cb02c45e1cad67c2ce5b5b758adfb19b87f74bbdff9c"}, + {file = "jiter-0.4.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:ca2a4d750aed3154b89f2efb148609fc985fad8db739460797aaf9b478acedda"}, + {file = "jiter-0.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0e6c304b3cc6896256727e1fb8991c7179a345eca8224e201795e9cacf4683b0"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7cc34ac708ae1750d077e490321761ec4b9a055b994cbdd1d6fbd37099e4aa7b"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8c93383875ab8d2e4f760aaff335b4a12ff32d4f9cf49c4498d657734f611466"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce197ee044add576afca0955b42142dd0312639adb6ebadbdbe4277f2855614f"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a427716813ff65480ca5b5117cfa099f49b49cd38051f8609bd0d5493013ca0"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:479990218353356234669e70fac53e5eb6f739a10db25316171aede2c97d9364"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d35a91ec5ac74cf33234c431505299fa91c0a197c2dbafd47400aca7c69489d4"}, + {file = "jiter-0.4.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b27189847193708c94ad10ca0d891309342ae882725d2187cf5d2db02bde8d1b"}, + {file = "jiter-0.4.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:76c255308cd1093fb411a03756b7bb220e48d4a98c30cbc79ed448bf3978e27d"}, + {file = "jiter-0.4.2-cp38-none-win32.whl", hash = "sha256:bb77438060bad49cc251941e6701b31138365c8a0ddaf10cdded2fcc6dd30701"}, + {file = "jiter-0.4.2-cp38-none-win_amd64.whl", hash = "sha256:ce858af19f7ce0d4b51c9f6c0c9d08f1e9dcef1986c5875efd0674a7054292ca"}, + {file = "jiter-0.4.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:6128838a2f357b3921b2a3242d5dc002ae4255ecc8f9f05c20d56d7d2d79c5ad"}, + {file = "jiter-0.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f2420cebb9ba856cb57dcab1d2d8def949b464b0db09c22a4e4dbd52fff7b200"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5d13d8128e853b320e00bb18bd4bb8b136cc0936091dc87633648fc688eb705"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eba5d6e54f149c508ba88677f97d3dc7dd75e9980d234bbac8027ac6db0763a3"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0fad5d64af0bc0545237419bf4150d8de56f0bd217434bdd1a59730327252bef"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d179e7bca89cf5719bd761dd37a341ff0f98199ecaa9c14af09792e47e977cc"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36353caee9f103d8ee7bda077f6400505b0f370e27eabcab33a33d21de12a2a6"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dd146c25bce576ca5db64fc7eccb8862af00f1f0e30108796953f12a53660e4c"}, + {file = "jiter-0.4.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:14b7c08cadbcd703041c66dc30e24e17de2f340281cac0e69374223ecf153aa4"}, + {file = "jiter-0.4.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a90f1a8b3d29aea198f8ea2b01148276ced8056e5103f32525266b3d880e65c9"}, + {file = "jiter-0.4.2-cp39-none-win32.whl", hash = "sha256:25b174997c780337b61ae57b1723455eecae9a17a9659044fd3c3b369190063f"}, + {file = "jiter-0.4.2-cp39-none-win_amd64.whl", hash = "sha256:bef62cea18521c5b99368147040c7e560c55098a35c93456f110678a2d34189a"}, + {file = "jiter-0.4.2.tar.gz", hash = "sha256:29b9d44f23f0c05f46d482f4ebf03213ee290d77999525d0975a17f875bf1eea"}, ] [[package]] name = "joblib" version = "1.4.2" description = "Lightweight pipelining with Python functions" -optional = true +optional = false python-versions = ">=3.8" files = [ {file = "joblib-1.4.2-py3-none-any.whl", hash = "sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6"}, @@ -1629,13 +1528,13 @@ jsonpointer = ">=1.9" [[package]] name = "jsonpointer" -version = "2.4" +version = "3.0.0" description = "Identify specific nodes in a JSON document (RFC 6901)" optional = true -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +python-versions = ">=3.7" files = [ - {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, - {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, + {file = "jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942"}, + {file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"}, ] [[package]] @@ -1675,13 +1574,13 @@ referencing = ">=0.31.0" [[package]] name = "langchain" -version = "0.2.2" +version = "0.2.3" description = "Building applications with LLMs through composability" optional = true python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain-0.2.2-py3-none-any.whl", hash = "sha256:58ca0c47bcdd156da66f50a0a4fcedc49bf6950827f4a6b06c8c4842d55805f3"}, - {file = "langchain-0.2.2.tar.gz", hash = "sha256:9d61e50e9cdc2bea659bc5e6c03650ba048fda63a307490ae368e539f61a0d3a"}, + {file = "langchain-0.2.3-py3-none-any.whl", hash = "sha256:5dc33cd9c8008693d328b7cb698df69073acecc89ad9c2a95f243b3314f8d834"}, + {file = "langchain-0.2.3.tar.gz", hash = "sha256:81962cc72cce6515f7bd71e01542727870789bf8b666c6913d85559080c1a201"}, ] [package.dependencies] @@ -1697,29 +1596,15 @@ requests = ">=2,<3" SQLAlchemy = ">=1.4,<3" tenacity = ">=8.1.0,<9.0.0" -[package.extras] -azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-textanalytics (>=5.3.0,<6.0.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b8)", "openai (<2)"] -clarifai = ["clarifai (>=9.1.0)"] -cli = ["typer (>=0.9.0,<0.10.0)"] -cohere = ["cohere (>=4,<6)"] -docarray = ["docarray[hnswlib] (>=0.32.0,<0.33.0)"] -embeddings = ["sentence-transformers (>=2,<3)"] -extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<6)", "couchbase (>=4.1.9,<5.0.0)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "langchain-openai (>=0.1,<0.2)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] -javascript = ["esprima (>=4.0.1,<5.0.0)"] -llms = ["clarifai (>=9.1.0)", "cohere (>=4,<6)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (<2)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] -openai = ["openai (<2)", "tiktoken (>=0.7,<1.0)"] -qdrant = ["qdrant-client (>=1.3.1,<2.0.0)"] -text-helpers = ["chardet (>=5.1.0,<6.0.0)"] - [[package]] name = "langchain-community" -version = "0.2.2" +version = "0.2.4" description = "Community contributed LangChain integrations." optional = true python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_community-0.2.2-py3-none-any.whl", hash = "sha256:470ee16e05f1acacb91a656b6d3c2cbf6fb6a8dcb00a13901cd1353cd29c2bb3"}, - {file = "langchain_community-0.2.2.tar.gz", hash = "sha256:fb09faf4640726a929932056dc55ff120e490aaf2e424fae8ddbb15605195447"}, + {file = "langchain_community-0.2.4-py3-none-any.whl", hash = "sha256:8582e9800f4837660dc297cccd2ee1ddc1d8c440d0fe8b64edb07620f0373b0e"}, + {file = "langchain_community-0.2.4.tar.gz", hash = "sha256:2bb6a1a36b8500a564d25d76469c02457b1a7c3afea6d4a609a47c06b993e3e4"}, ] [package.dependencies] @@ -1734,19 +1619,15 @@ requests = ">=2,<3" SQLAlchemy = ">=1.4,<3" tenacity = ">=8.1.0,<9.0.0" -[package.extras] -cli = ["typer (>=0.9.0,<0.10.0)"] -extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "azure-identity (>=1.15.0,<2.0.0)", "azure-search-documents (==11.4.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.6,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cloudpathlib (>=0.18,<0.19)", "cloudpickle (>=2.0.0)", "cohere (>=4,<5)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "friendli-client (>=1.2.4,<2.0.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "httpx (>=0.24.1,<0.25.0)", "httpx-sse (>=0.4.0,<0.5.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "nvidia-riva-client (>=2.14.0,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "oracledb (>=2.2.0,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "premai (>=0.3.25,<0.4.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pyjwt (>=2.8.0,<3.0.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "simsimd (>=4.3.1,<5.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "tidb-vector (>=0.0.3,<1.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "tree-sitter (>=0.20.2,<0.21.0)", "tree-sitter-languages (>=1.8.0,<2.0.0)", "upstash-redis (>=0.15.0,<0.16.0)", "vdms (>=0.0.20,<0.0.21)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] - [[package]] name = "langchain-core" -version = "0.2.4" +version = "0.2.5" description = "Building applications with LLMs through composability" optional = true python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain_core-0.2.4-py3-none-any.whl", hash = "sha256:5212f7ec78a525e88a178ed3aefe2fd7134b03fb92573dfbab9914f1d92d6ec5"}, - {file = "langchain_core-0.2.4.tar.gz", hash = "sha256:82bdcc546eb0341cefcf1f4ecb3e49836fff003903afddda2d1312bb8491ef81"}, + {file = "langchain_core-0.2.5-py3-none-any.whl", hash = "sha256:abe5138f22acff23a079ec538be5268bbf97cf023d51987a0dd474d2a16cae3e"}, + {file = "langchain_core-0.2.5.tar.gz", hash = "sha256:4a5c2f56b22396a63ef4790043660e393adbfa6832b978f023ca996a04b8e752"}, ] [package.dependencies] @@ -1757,9 +1638,6 @@ pydantic = ">=1,<3" PyYAML = ">=5.3" tenacity = ">=8.1.0,<9.0.0" -[package.extras] -extended-testing = ["jinja2 (>=3,<4)"] - [[package]] name = "langchain-text-splitters" version = "0.2.1" @@ -1779,13 +1657,13 @@ extended-testing = ["beautifulsoup4 (>=4.12.3,<5.0.0)", "lxml (>=4.9.3,<6.0)"] [[package]] name = "langsmith" -version = "0.1.72" +version = "0.1.77" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = true python-versions = "<4.0,>=3.8.1" files = [ - {file = "langsmith-0.1.72-py3-none-any.whl", hash = "sha256:a4456707669521bd75b7431b9205a6b99579fb9ff01bd338f52d29df11a7662d"}, - {file = "langsmith-0.1.72.tar.gz", hash = "sha256:262ae9e8aceaba50f3a0f5b6eb559d6110886f0afc6b0ed5270e7d3d3f1fd8d6"}, + {file = "langsmith-0.1.77-py3-none-any.whl", hash = "sha256:2202cc21b1ed7e7b9e5d2af2694be28898afa048c09fdf09f620cbd9301755ae"}, + {file = "langsmith-0.1.77.tar.gz", hash = "sha256:4ace09077a9a4e412afeb4b517ca68e7de7b07f36e4792dc8236ac5207c0c0c7"}, ] [package.dependencies] @@ -1906,13 +1784,13 @@ files = [ [[package]] name = "marshmallow" -version = "3.21.2" +version = "3.21.3" description = "A lightweight library for converting complex datatypes to and from native Python datatypes." optional = true python-versions = ">=3.8" files = [ - {file = "marshmallow-3.21.2-py3-none-any.whl", hash = "sha256:70b54a6282f4704d12c0a41599682c5c5450e843b9ec406308653b47c59648a1"}, - {file = "marshmallow-3.21.2.tar.gz", hash = "sha256:82408deadd8b33d56338d2182d455db632c6313aa2af61916672146bb32edc56"}, + {file = "marshmallow-3.21.3-py3-none-any.whl", hash = "sha256:86ce7fb914aa865001a4b2092c4c2872d13bc347f3d42673272cabfdbad386f1"}, + {file = "marshmallow-3.21.3.tar.gz", hash = "sha256:4f57c5e050a54d66361e826f94fba213eb10b67b2fdb02c3e0343ce207ba1662"}, ] [package.dependencies] @@ -1923,20 +1801,6 @@ dev = ["marshmallow[tests]", "pre-commit (>=3.5,<4.0)", "tox"] docs = ["alabaster (==0.7.16)", "autodocsumm (==0.2.12)", "sphinx (==7.3.7)", "sphinx-issues (==4.1.0)", "sphinx-version-warning (==1.1.2)"] tests = ["pytest", "pytz", "simplejson"] -[[package]] -name = "matplotlib-inline" -version = "0.1.7" -description = "Inline Matplotlib backend for Jupyter" -optional = false -python-versions = ">=3.8" -files = [ - {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"}, - {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"}, -] - -[package.dependencies] -traitlets = "*" - [[package]] name = "mdurl" version = "0.1.2" @@ -2173,7 +2037,7 @@ files = [ name = "nltk" version = "3.8.1" description = "Natural Language Toolkit" -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "nltk-3.8.1-py3-none-any.whl", hash = "sha256:fd5c9109f976fa86bcadba8f91e47f5e9293bd034474752e92a520f81c93dda5"}, @@ -2241,13 +2105,13 @@ files = [ [[package]] name = "openai" -version = "1.31.0" +version = "1.34.0" description = "The official Python library for the openai API" optional = false python-versions = ">=3.7.1" files = [ - {file = "openai-1.31.0-py3-none-any.whl", hash = "sha256:82044ee3122113f2a468a1f308a8882324d09556ba5348687c535d3655ee331c"}, - {file = "openai-1.31.0.tar.gz", hash = "sha256:54ae0625b005d6a3b895db2b8438dae1059cffff0cd262a26e9015c13a29ab06"}, + {file = "openai-1.34.0-py3-none-any.whl", hash = "sha256:018623c2f795424044675c6230fa3bfbf98d9e0aab45d8fd116f2efb2cfb6b7e"}, + {file = "openai-1.34.0.tar.gz", hash = "sha256:95c8e2da4acd6958e626186957d656597613587195abd0fb2527566a93e76770"}, ] [package.dependencies] @@ -2309,57 +2173,57 @@ opentelemetry-api = "1.25.0" [[package]] name = "orjson" -version = "3.10.3" +version = "3.10.4" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" optional = false python-versions = ">=3.8" files = [ - {file = "orjson-3.10.3-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9fb6c3f9f5490a3eb4ddd46fc1b6eadb0d6fc16fb3f07320149c3286a1409dd8"}, - {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:252124b198662eee80428f1af8c63f7ff077c88723fe206a25df8dc57a57b1fa"}, - {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f3e87733823089a338ef9bbf363ef4de45e5c599a9bf50a7a9b82e86d0228da"}, - {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8334c0d87103bb9fbbe59b78129f1f40d1d1e8355bbed2ca71853af15fa4ed3"}, - {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1952c03439e4dce23482ac846e7961f9d4ec62086eb98ae76d97bd41d72644d7"}, - {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c0403ed9c706dcd2809f1600ed18f4aae50be263bd7112e54b50e2c2bc3ebd6d"}, - {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:382e52aa4270a037d41f325e7d1dfa395b7de0c367800b6f337d8157367bf3a7"}, - {file = "orjson-3.10.3-cp310-none-win32.whl", hash = "sha256:be2aab54313752c04f2cbaab4515291ef5af8c2256ce22abc007f89f42f49109"}, - {file = "orjson-3.10.3-cp310-none-win_amd64.whl", hash = "sha256:416b195f78ae461601893f482287cee1e3059ec49b4f99479aedf22a20b1098b"}, - {file = "orjson-3.10.3-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:73100d9abbbe730331f2242c1fc0bcb46a3ea3b4ae3348847e5a141265479700"}, - {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a12eee96e3ab828dbfcb4d5a0023aa971b27143a1d35dc214c176fdfb29b3"}, - {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520de5e2ef0b4ae546bea25129d6c7c74edb43fc6cf5213f511a927f2b28148b"}, - {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccaa0a401fc02e8828a5bedfd80f8cd389d24f65e5ca3954d72c6582495b4bcf"}, - {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7bc9e8bc11bac40f905640acd41cbeaa87209e7e1f57ade386da658092dc16"}, - {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3582b34b70543a1ed6944aca75e219e1192661a63da4d039d088a09c67543b08"}, - {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c23dfa91481de880890d17aa7b91d586a4746a4c2aa9a145bebdbaf233768d5"}, - {file = "orjson-3.10.3-cp311-none-win32.whl", hash = "sha256:1770e2a0eae728b050705206d84eda8b074b65ee835e7f85c919f5705b006c9b"}, - {file = "orjson-3.10.3-cp311-none-win_amd64.whl", hash = "sha256:93433b3c1f852660eb5abdc1f4dd0ced2be031ba30900433223b28ee0140cde5"}, - {file = "orjson-3.10.3-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a39aa73e53bec8d410875683bfa3a8edf61e5a1c7bb4014f65f81d36467ea098"}, - {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0943a96b3fa09bee1afdfccc2cb236c9c64715afa375b2af296c73d91c23eab2"}, - {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e852baafceff8da3c9defae29414cc8513a1586ad93e45f27b89a639c68e8176"}, - {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18566beb5acd76f3769c1d1a7ec06cdb81edc4d55d2765fb677e3eaa10fa99e0"}, - {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd2218d5a3aa43060efe649ec564ebedec8ce6ae0a43654b81376216d5ebd42"}, - {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cf20465e74c6e17a104ecf01bf8cd3b7b252565b4ccee4548f18b012ff2f8069"}, - {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba7f67aa7f983c4345eeda16054a4677289011a478ca947cd69c0a86ea45e534"}, - {file = "orjson-3.10.3-cp312-none-win32.whl", hash = "sha256:17e0713fc159abc261eea0f4feda611d32eabc35708b74bef6ad44f6c78d5ea0"}, - {file = "orjson-3.10.3-cp312-none-win_amd64.whl", hash = "sha256:4c895383b1ec42b017dd2c75ae8a5b862fc489006afde06f14afbdd0309b2af0"}, - {file = "orjson-3.10.3-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:be2719e5041e9fb76c8c2c06b9600fe8e8584e6980061ff88dcbc2691a16d20d"}, - {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0175a5798bdc878956099f5c54b9837cb62cfbf5d0b86ba6d77e43861bcec2"}, - {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:978be58a68ade24f1af7758626806e13cff7748a677faf95fbb298359aa1e20d"}, - {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16bda83b5c61586f6f788333d3cf3ed19015e3b9019188c56983b5a299210eb5"}, - {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ad1f26bea425041e0a1adad34630c4825a9e3adec49079b1fb6ac8d36f8b754"}, - {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9e253498bee561fe85d6325ba55ff2ff08fb5e7184cd6a4d7754133bd19c9195"}, - {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0a62f9968bab8a676a164263e485f30a0b748255ee2f4ae49a0224be95f4532b"}, - {file = "orjson-3.10.3-cp38-none-win32.whl", hash = "sha256:8d0b84403d287d4bfa9bf7d1dc298d5c1c5d9f444f3737929a66f2fe4fb8f134"}, - {file = "orjson-3.10.3-cp38-none-win_amd64.whl", hash = "sha256:8bc7a4df90da5d535e18157220d7915780d07198b54f4de0110eca6b6c11e290"}, - {file = "orjson-3.10.3-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9059d15c30e675a58fdcd6f95465c1522b8426e092de9fff20edebfdc15e1cb0"}, - {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d40c7f7938c9c2b934b297412c067936d0b54e4b8ab916fd1a9eb8f54c02294"}, - {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4a654ec1de8fdaae1d80d55cee65893cb06494e124681ab335218be6a0691e7"}, - {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:831c6ef73f9aa53c5f40ae8f949ff7681b38eaddb6904aab89dca4d85099cb78"}, - {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99b880d7e34542db89f48d14ddecbd26f06838b12427d5a25d71baceb5ba119d"}, - {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e5e176c994ce4bd434d7aafb9ecc893c15f347d3d2bbd8e7ce0b63071c52e25"}, - {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b69a58a37dab856491bf2d3bbf259775fdce262b727f96aafbda359cb1d114d8"}, - {file = "orjson-3.10.3-cp39-none-win32.whl", hash = "sha256:b8d4d1a6868cde356f1402c8faeb50d62cee765a1f7ffcfd6de732ab0581e063"}, - {file = "orjson-3.10.3-cp39-none-win_amd64.whl", hash = "sha256:5102f50c5fc46d94f2033fe00d392588564378260d64377aec702f21a7a22912"}, - {file = "orjson-3.10.3.tar.gz", hash = "sha256:2b166507acae7ba2f7c315dcf185a9111ad5e992ac81f2d507aac39193c2c818"}, + {file = "orjson-3.10.4-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:afca963f19ca60c7aedadea9979f769139127288dd58ccf3f7c5e8e6dc62cabf"}, + {file = "orjson-3.10.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42b112eff36ba7ccc7a9d6b87e17b9d6bde4312d05e3ddf66bf5662481dee846"}, + {file = "orjson-3.10.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02b192eaba048b1039eca9a0cef67863bd5623042f5c441889a9957121d97e14"}, + {file = "orjson-3.10.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:827c3d0e4fc44242c82bfdb1a773235b8c0575afee99a9fa9a8ce920c14e440f"}, + {file = "orjson-3.10.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca8ec09724f10ec209244caeb1f9f428b6bb03f2eda9ed5e2c4dd7f2b7fabd44"}, + {file = "orjson-3.10.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8eaa5d531a8fde11993cbcb27e9acf7d9c457ba301adccb7fa3a021bfecab46c"}, + {file = "orjson-3.10.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e112aa7fc4ea67367ec5e86c39a6bb6c5719eddc8f999087b1759e765ddaf2d4"}, + {file = "orjson-3.10.4-cp310-none-win32.whl", hash = "sha256:1538844fb88446c42da3889f8c4ecce95a630b5a5ba18ecdfe5aea596f4dff21"}, + {file = "orjson-3.10.4-cp310-none-win_amd64.whl", hash = "sha256:de02811903a2e434127fba5389c3cc90f689542339a6e52e691ab7f693407b5a"}, + {file = "orjson-3.10.4-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:358afaec75de7237dfea08e6b1b25d226e33a1e3b6dc154fc99eb697f24a1ffa"}, + {file = "orjson-3.10.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb4e292c3198ab3d93e5f877301d2746be4ca0ba2d9c513da5e10eb90e19ff52"}, + {file = "orjson-3.10.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c39e57cf6323a39238490092985d5d198a7da4a3be013cc891a33fef13a536e"}, + {file = "orjson-3.10.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f86df433fc01361ff9270ad27455ce1ad43cd05e46de7152ca6adb405a16b2f6"}, + {file = "orjson-3.10.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c9966276a2c97e93e6cbe8286537f88b2a071827514f0d9d47a0aefa77db458"}, + {file = "orjson-3.10.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c499a14155a1f5a1e16e0cd31f6cf6f93965ac60a0822bc8340e7e2d3dac1108"}, + {file = "orjson-3.10.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3087023ce904a327c29487eb7e1f2c060070e8dbb9a3991b8e7952a9c6e62f38"}, + {file = "orjson-3.10.4-cp311-none-win32.whl", hash = "sha256:f965893244fe348b59e5ce560693e6dd03368d577ce26849b5d261ce31c70101"}, + {file = "orjson-3.10.4-cp311-none-win_amd64.whl", hash = "sha256:c212f06fad6aa6ce85d5665e91a83b866579f29441a47d3865c57329c0857357"}, + {file = "orjson-3.10.4-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:d0965a8b0131959833ca8a65af60285995d57ced0de2fd8f16fc03235975d238"}, + {file = "orjson-3.10.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27b64695d9f2aef3ae15a0522e370ec95c946aaea7f2c97a1582a62b3bdd9169"}, + {file = "orjson-3.10.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:867d882ddee6a20be4c8b03ae3d2b0333894d53ad632d32bd9b8123649577171"}, + {file = "orjson-3.10.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a0667458f8a8ceb6dee5c08fec0b46195f92c474cbbec71dca2a6b7fd5b67b8d"}, + {file = "orjson-3.10.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3eac9befc4eaec1d1ff3bba6210576be4945332dde194525601c5ddb5c060d3"}, + {file = "orjson-3.10.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4343245443552eae240a33047a6d1bcac7a754ad4b1c57318173c54d7efb9aea"}, + {file = "orjson-3.10.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:30153e269eea43e98918d4d462a36a7065031d9246407dfff2579a4e457515c1"}, + {file = "orjson-3.10.4-cp312-none-win32.whl", hash = "sha256:1a7d092ee043abf3db19c2183115e80676495c9911843fdb3ebd48ca7b73079e"}, + {file = "orjson-3.10.4-cp312-none-win_amd64.whl", hash = "sha256:07a2adbeb8b9efe6d68fc557685954a1f19d9e33f5cc018ae1a89e96647c1b65"}, + {file = "orjson-3.10.4-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:f5a746f3d908bce1a1e347b9ca89864047533bdfab5a450066a0315f6566527b"}, + {file = "orjson-3.10.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:465b4a8a3e459f8d304c19071b4badaa9b267c59207a005a7dd9dfe13d3a423f"}, + {file = "orjson-3.10.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:35858d260728c434a3d91b60685ab32418318567e8902039837e1c2af2719e0b"}, + {file = "orjson-3.10.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8a5ba090d40c4460312dd69c232b38c2ff67a823185cfe667e841c9dd5c06841"}, + {file = "orjson-3.10.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5dde86755d064664e62e3612a166c28298aa8dfd35a991553faa58855ae739cc"}, + {file = "orjson-3.10.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:020a9e9001cfec85c156ef3b185ff758b62ef986cefdb8384c4579facd5ce126"}, + {file = "orjson-3.10.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3bf8e6e3388a2e83a86466c912387e0f0a765494c65caa7e865f99969b76ba0d"}, + {file = "orjson-3.10.4-cp38-none-win32.whl", hash = "sha256:c5a1cca6a4a3129db3da68a25dc0a459a62ae58e284e363b35ab304202d9ba9e"}, + {file = "orjson-3.10.4-cp38-none-win_amd64.whl", hash = "sha256:ecd97d98d7bee3e3d51d0b51c92c457f05db4993329eea7c69764f9820e27eb3"}, + {file = "orjson-3.10.4-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:71362daa330a2fc85553a1469185ac448547392a8f83d34e67779f8df3a52743"}, + {file = "orjson-3.10.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d24b59d1fecb0fd080c177306118a143f7322335309640c55ed9580d2044e363"}, + {file = "orjson-3.10.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e906670aea5a605b083ebb58d575c35e88cf880fa372f7cedaac3d51e98ff164"}, + {file = "orjson-3.10.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ce32ed4bc4d632268e4978e595fe5ea07e026b751482b4a0feec48f66a90abc"}, + {file = "orjson-3.10.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1dcd34286246e0c5edd0e230d1da2daab2c1b465fcb6bac85b8d44057229d40a"}, + {file = "orjson-3.10.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c45d4b8c403e50beedb1d006a8916d9910ed56bceaf2035dc253618b44d0a161"}, + {file = "orjson-3.10.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:aaed3253041b5002a4f5bfdf6f7b5cce657d974472b0699a469d439beba40381"}, + {file = "orjson-3.10.4-cp39-none-win32.whl", hash = "sha256:9a4f41b7dbf7896f8dbf559b9b43dcd99e31e0d49ac1b59d74f52ce51ab10eb9"}, + {file = "orjson-3.10.4-cp39-none-win_amd64.whl", hash = "sha256:6c4eb7d867ed91cb61e6514cb4f457aa01d7b0fd663089df60a69f3d38b69d4c"}, + {file = "orjson-3.10.4.tar.gz", hash = "sha256:c912ed25b787c73fe994a5decd81c3f3b256599b8a87d410d799d5d52013af2a"}, ] [[package]] @@ -2373,21 +2237,6 @@ files = [ {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] -[[package]] -name = "parso" -version = "0.8.4" -description = "A Python Parser" -optional = false -python-versions = ">=3.6" -files = [ - {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, - {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"}, -] - -[package.extras] -qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] -testing = ["docopt", "pytest"] - [[package]] name = "pathspec" version = "0.12.1" @@ -2399,20 +2248,6 @@ files = [ {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] -[[package]] -name = "pexpect" -version = "4.9.0" -description = "Pexpect allows easy control of interactive console applications." -optional = false -python-versions = "*" -files = [ - {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, - {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, -] - -[package.dependencies] -ptyprocess = ">=0.5" - [[package]] name = "phonenumbers" version = "8.13.38" @@ -2455,20 +2290,6 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] -[[package]] -name = "prompt-toolkit" -version = "3.0.46" -description = "Library for building powerful interactive command lines in Python" -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "prompt_toolkit-3.0.46-py3-none-any.whl", hash = "sha256:45abe60a8300f3c618b23c16c4bb98c6fc80af8ce8b17c7ae92db48db3ee63c1"}, - {file = "prompt_toolkit-3.0.46.tar.gz", hash = "sha256:869c50d682152336e23c4db7f74667639b5047494202ffe7670817053fd57795"}, -] - -[package.dependencies] -wcwidth = "*" - [[package]] name = "proto-plus" version = "1.23.0" @@ -2506,31 +2327,6 @@ files = [ {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, ] -[[package]] -name = "ptyprocess" -version = "0.7.0" -description = "Run a subprocess in a pseudo terminal" -optional = false -python-versions = "*" -files = [ - {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, - {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, -] - -[[package]] -name = "pure-eval" -version = "0.2.2" -description = "Safely evaluate AST nodes without side effects" -optional = false -python-versions = "*" -files = [ - {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, - {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, -] - -[package.extras] -tests = ["pytest"] - [[package]] name = "pvkoala" version = "2.0.1" @@ -2580,13 +2376,13 @@ files = [ [[package]] name = "pydantic" -version = "2.7.3" +version = "2.7.4" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.7.3-py3-none-any.whl", hash = "sha256:ea91b002777bf643bb20dd717c028ec43216b24a6001a280f83877fd2655d0b4"}, - {file = "pydantic-2.7.3.tar.gz", hash = "sha256:c46c76a40bb1296728d7a8b99aa73dd70a48c3510111ff290034f860c99c419e"}, + {file = "pydantic-2.7.4-py3-none-any.whl", hash = "sha256:ee8538d41ccb9c0a9ad3e0e5f07bf15ed8015b481ced539a1759d8cc89ae90d0"}, + {file = "pydantic-2.7.4.tar.gz", hash = "sha256:0c84efd9548d545f63ac0060c1e4d39bb9b14db8b3c0652338aecc07b5adec52"}, ] [package.dependencies] @@ -2690,13 +2486,13 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pydantic-settings" -version = "2.3.0" +version = "2.3.3" description = "Settings management using Pydantic" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_settings-2.3.0-py3-none-any.whl", hash = "sha256:26eeed27370a9c5e3f64e4a7d6602573cbedf05ed940f1d5b11c3f178427af7a"}, - {file = "pydantic_settings-2.3.0.tar.gz", hash = "sha256:78db28855a71503cfe47f39500a1dece523c640afd5280edb5c5c9c9cfa534c9"}, + {file = "pydantic_settings-2.3.3-py3-none-any.whl", hash = "sha256:e4ed62ad851670975ec11285141db888fd24947f9440bd4380d7d8788d4965de"}, + {file = "pydantic_settings-2.3.3.tar.gz", hash = "sha256:87fda838b64b5039b970cd47c3e8a1ee460ce136278ff672980af21516f6e6ce"}, ] [package.dependencies] @@ -2945,7 +2741,6 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -2953,16 +2748,8 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -2979,7 +2766,6 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -2987,7 +2773,6 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -2995,13 +2780,13 @@ files = [ [[package]] name = "redis" -version = "5.0.4" +version = "5.0.6" description = "Python client for Redis database and key-value store" optional = false python-versions = ">=3.7" files = [ - {file = "redis-5.0.4-py3-none-any.whl", hash = "sha256:7adc2835c7a9b5033b7ad8f8918d09b7344188228809c98df07af226d39dec91"}, - {file = "redis-5.0.4.tar.gz", hash = "sha256:ec31f2ed9675cc54c21ba854cfe0462e6faf1d83c8ce5944709db8a4700b9c61"}, + {file = "redis-5.0.6-py3-none-any.whl", hash = "sha256:c0d6d990850c627bbf7be01c5c4cbaadf67b48593e913bb71c9819c30df37eee"}, + {file = "redis-5.0.6.tar.gz", hash = "sha256:38473cd7c6389ad3e44a91f4c3eaf6bcb8a9f746007f29bf4fb20824ff0b2197"}, ] [package.dependencies] @@ -3277,13 +3062,13 @@ pyasn1 = ">=0.1.3" [[package]] name = "sentry-sdk" -version = "2.4.0" +version = "2.5.1" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = ">=3.6" files = [ - {file = "sentry_sdk-2.4.0-py2.py3-none-any.whl", hash = "sha256:a42b70981cd4ed7da3c85d0360502d2ac932a15a4a420b360e1ebded2fc19a92"}, - {file = "sentry_sdk-2.4.0.tar.gz", hash = "sha256:62b9bb0489e731ecbce008f9647899b51d220067a75c3adfd46f8187660c0029"}, + {file = "sentry_sdk-2.5.1-py2.py3-none-any.whl", hash = "sha256:1f87acdce4a43a523ae5aa21a3fc37522d73ebd9ec04b1dbf01aa3d173852def"}, + {file = "sentry_sdk-2.5.1.tar.gz", hash = "sha256:fbc40a78a8a9c6675133031116144f0d0940376fa6e4e1acd5624c90b0aaf58b"}, ] [package.dependencies] @@ -3337,17 +3122,6 @@ files = [ {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, ] -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] - [[package]] name = "sniffio" version = "1.3.1" @@ -3477,25 +3251,6 @@ postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] pymysql = ["pymysql"] sqlcipher = ["sqlcipher3_binary"] -[[package]] -name = "stack-data" -version = "0.6.3" -description = "Extract data from python stack frames and tracebacks for informative displays" -optional = false -python-versions = "*" -files = [ - {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, - {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, -] - -[package.dependencies] -asttokens = ">=2.1.0" -executing = ">=1.2.0" -pure-eval = "*" - -[package.extras] -tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] - [[package]] name = "starlette" version = "0.37.2" @@ -3728,30 +3483,15 @@ notebook = ["ipywidgets (>=6)"] slack = ["slack-sdk"] telegram = ["requests"] -[[package]] -name = "traitlets" -version = "5.14.3" -description = "Traitlets Python configuration system" -optional = false -python-versions = ">=3.8" -files = [ - {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}, - {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"}, -] - -[package.extras] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"] - [[package]] name = "twilio" -version = "9.1.0" +version = "9.1.1" description = "Twilio API client and TwiML generator" optional = true python-versions = ">=3.7.0" files = [ - {file = "twilio-9.1.0-py2.py3-none-any.whl", hash = "sha256:eb4687a9f81dc3118e8981c5a46d9f8184baee135c79afed47c714c759c31bbc"}, - {file = "twilio-9.1.0.tar.gz", hash = "sha256:ab2eb19c779855bf02cdca8a7e02ebaa64feee47da7b591ac9088ec07a6962e2"}, + {file = "twilio-9.1.1-py2.py3-none-any.whl", hash = "sha256:cc3e090c3884db7d70e7c647358b9cf1f4d30fd3fbe0412adcae0df8459d29b0"}, + {file = "twilio-9.1.1.tar.gz", hash = "sha256:cfe72b12cabac2f0997f1060d53cea14bd1196e2cbda14789e53c7dd762c4349"}, ] [package.dependencies] @@ -3859,13 +3599,13 @@ files = [ [[package]] name = "typing-extensions" -version = "4.12.1" +version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.12.1-py3-none-any.whl", hash = "sha256:6024b58b69089e5a89c347397254e35f1bf02a907728ec7fee9bf0fe837d203a"}, - {file = "typing_extensions-4.12.1.tar.gz", hash = "sha256:915f5e35ff76f56588223f15fdd5938f9a1cf9195c0de25130c627e4d597f6d1"}, + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] [[package]] @@ -4059,13 +3799,13 @@ test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)" [[package]] name = "vonage" -version = "3.15.0" +version = "3.16.0" description = "Vonage Server SDK for Python" optional = true python-versions = ">=3.8" files = [ - {file = "vonage-3.15.0-py2.py3-none-any.whl", hash = "sha256:2843345a744444ab5a7ba24ffed8ea2b5493edbc2e47292b1a3e924b2df55cac"}, - {file = "vonage-3.15.0.tar.gz", hash = "sha256:4ce60ad0d52c43fb05e860050598576b97a4397aa426f19c3326c76978b4ffc8"}, + {file = "vonage-3.16.0-py2.py3-none-any.whl", hash = "sha256:ce14eb29f0942c55899c48254d39cb6624cdc1ff5e9b1ca6d520afea85abc352"}, + {file = "vonage-3.16.0.tar.gz", hash = "sha256:63ea60a70b358ddfc7b5491b1b39d3699d25fa41a6e9246ac4c8f3c5aeeff830"}, ] [package.dependencies] @@ -4192,17 +3932,6 @@ files = [ [package.dependencies] anyio = ">=3.0.0" -[[package]] -name = "wcwidth" -version = "0.2.13" -description = "Measures the displayed width of unicode strings in a terminal" -optional = false -python-versions = "*" -files = [ - {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, - {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, -] - [[package]] name = "websockets" version = "12.0" @@ -4498,11 +4227,11 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", [extras] all = ["cartesia", "google-cloud-speech", "google-cloud-texttospeech", "langchain", "langchain-community", "miniaudio", "nltk", "pvkoala", "pydub", "twilio", "vonage"] misc = ["langchain", "langchain-community"] -synthesizers = ["cartesia", "google-cloud-texttospeech", "miniaudio", "nltk", "pvkoala", "pydub"] +synthesizers = ["cartesia", "google-cloud-texttospeech", "miniaudio", "pvkoala", "pydub"] telephony = ["twilio", "vonage"] transcribers = ["google-cloud-speech"] [metadata] lock-version = "2.0" python-versions = ">=3.10,<4.0" -content-hash = "0153515588beee9a13a33a4fb32d26dad863de37b6c55f903148f9c88904dc82" +content-hash = "6a94ac4f14452e6e73f6d5984455bf7935a15f6812dfe6214a38ebd1be30adb9"