From 04b0a9462205dba37214d38f936786b5cf79ce00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C4=83zvan=20Purdel?= <104128753+rpurdel@users.noreply.github.com> Date: Thu, 18 Jan 2024 18:14:01 +0200 Subject: [PATCH] Docs initial commit (#43) * Docs initial commit * docs: remove incomplete sentence * streaming_whisper: add websocket dependency * streaming_whisper: add websocket dependency * streaming_whisper: update websockets * streaming_whisper: dependencies * misc: cleanup * streaming_whisper: fix disable auth * streaming_whisper: fix vad model path * build: add libgomp1 to runtime, remove unnecessary stuff * docs: exmaple path fix --- .gitignore | 1 + Dockerfile | 4 +- LICENSE | 176 ++++++++++ README.md | 63 ++-- docs/README.md | 8 + docs/auth.md | 122 +++++++ docs/env_vars.md | 46 +++ docs/monitoring.md | 139 ++++++++ docs/streaming_whisper_module.md | 149 ++++++++ docs/summaries_module.md | 62 ++++ poetry.lock | 329 +++++++++++++++--- pyproject.toml | 2 +- requirements.txt | 19 +- .../streaming_whisper/ConnectionManager.py | 17 +- skynet/modules/stt/streaming_whisper/cfg.py | 2 +- skynet/sample.txt | 1 - skynet/sample_long.txt | 1 - 17 files changed, 1047 insertions(+), 94 deletions(-) create mode 100644 LICENSE create mode 100644 docs/README.md create mode 100644 docs/auth.md create mode 100644 docs/env_vars.md create mode 100644 docs/monitoring.md create mode 100644 docs/streaming_whisper_module.md create mode 100644 docs/summaries_module.md delete mode 100644 skynet/sample.txt delete mode 100644 skynet/sample_long.txt diff --git a/.gitignore b/.gitignore index 405d654..9da8798 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ __pycache__ llm .DS_Store .env +.idea diff --git a/Dockerfile b/Dockerfile index 44e4512..02c1c05 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,7 +46,7 @@ COPY --chown=jitsi:jitsi docker/run-skynet.sh /opt/ RUN \ apt-dpkg-wrap apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F23C5A6CF475977595C89F51BA6932366A755776 && \ apt-dpkg-wrap apt-get update && \ - apt-dpkg-wrap apt-get install -y python3.11 python3.11-venv tini && \ + apt-dpkg-wrap apt-get install -y python3.11 python3.11-venv tini libgomp1 && \ apt-cleanup # Principle of least privilege: create a new user for running the application @@ -76,7 +76,7 @@ RUN chown jitsi:jitsi ${PYTHONPATH} # Document the exposed port EXPOSE 8000 -# Use the unpriveledged user to run the application +# Use the unpriviledged user to run the application USER 1001 # Use tini as our PID 1 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2bb9ad2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/README.md b/README.md index 4c26aa4..0361133 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,52 @@ # Skynet -Skynet is an API server for AI services wrapping several APIs and models. +Skynet is an API server for AI services wrapping several apps and models. -## Usage -All requests to this service will require a standard HTTP Authorization header with a Bearer JWT -You can generate a valid JWT in two ways: +It is comprised of specialized modules which can be enabled or disabled as needed. -1. Have a JaaS account (https://jaas-pilot.8x8.vc or https://jaas.8x8.vc if using production) and use one of the JaaS public - private key pairs to generate the JWT as specified [here](https://developer.8x8.com/jaas/docs/api-keys-jwt). Currently, the tokens will be considered valid as long as they have the header in the specified format (alg, kid and typ), and an audience set to the value "jitsi". -2. Have a private - public key pair for generating JWTs as specified above. -3. Use the helper script to generate a token: +- **Summary and Action Items** with llama.cpp (enabled by default) +- **Live Transcriptions** with Faster Whisper via websockets +- _more to follow_ -```bash -./docs/jaas-jwt.sh PrivateKey.pk API-Key -# The generated token has a validity of 7200 seconds -``` +## Requirements -### Code samples +- Poetry +- Redis -JavaScript: https://github.com/jitsi/skynet/blob/master/docs/sample.js +## Quickstart +```bash +# Download the preferred GGUF llama model (e.g. https://huggingface.co/TheBloke/Llama-2-7b-Chat-GGUF) and point LLAMA_PATH to it +mkdir skynet/models -### [Flowchart](https://github.com/jitsi/skynet/blob/master/docs/flowchart.jpg) +wget -q --show-progress "https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/main/llama-2-7b-chat.Q4_K_M.gguf?download=true" -O skynet/models/llama-2-7b-chat.Q4_K_M.gguf -### Running +export LLAMA_PATH="$(pwd)/skynet/models/llama-2-7b-chat.Q4_K_M.gguf" -Download GGUF llama model (e.g. https://huggingface.co/TheBloke/Llama-2-7b-Chat-GGUF) and point LLAMA_PATH to it +# start Redis +docker run -d --rm -p 6379:6379 redis + +# disable authorization +export BYPASS_AUTHORIZATION="true" -```bash poetry install -./run.sh -``` +poetry run python skynet/main.py -Visit -http://127.0.0.1:8000 -http://127.0.0.1:8001/metrics +# open http://localhost:8000/summaries/docs in a browser +``` -### Some benchmarks +## Documentation -Summary: +Detailed documentation on how to configure, run, build, monitor and deploy Skynet and can be found in the [docs](docs/README.md) folder. -| Model | Input size | Time to summarize (M1 CPU) | Time to summarize (GPU) | -| :---- | :--------: |:---------------------------:|:-----------------------:| -| [llama-2-7b-chat.Q4_K_M.gguf][1] | 16000 chars | ~87 sec | ~44 sec | -| [llama-2-7b-chat.Q4_K_M.gguf][1] | 8000 chars | ~51 sec | ~28 sec | +## Development -[1]: https://huggingface.co/TheBloke/Llama-2-7b-Chat-GGUF/blob/main/llama-2-7b-chat.Q4_K_M.gguf +If you want to contribute, make sure to install the pre-commit hook for linting. -### Development +```bash +poetry run githooks setup +``` -Install pre-commit hook that we use for linting +## License -```poetry run githooks setup``` +Skynet is distributed under the Apache 2.0 License. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..9c34ef4 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,8 @@ +# Skynet Documentation + +1. [Modules - Summaries](summaries_module.md) +2. [Modules - Streaming Whisper Live Transcription](streaming_whisper_module.md) +3. [Config - Environment Variables](env_vars.md) +4. [Authentication](auth.md) +5. [Monitoring](monitoring.md) +6. [Demos](../demos/) diff --git a/docs/auth.md b/docs/auth.md new file mode 100644 index 0000000..e612e61 --- /dev/null +++ b/docs/auth.md @@ -0,0 +1,122 @@ +# Skynet Authorization + +Skynet uses a JWT signed with an asymmetric key, just like [**Jitsi as a Service**](https://jaas.8x8.vc) does. + +The authorization is performed by downloading the public key advertised in the JWT's `kid` header from a well-known location and checking if the JWT signature and the audiences match. + +> Authorization can be disabled all together by setting the `BYPASS_AUTHORIZATION` env var to `true`. + + +## Creating a keypair + +Generate an `RS256` keypair with the command below and upload the public key to a web server. + +```bash +ssh-keygen -m PKCS8 -b 2048 -t rsa +``` + +Pick a key id (`kid`), e.g. `my-awesome-service`, and rename the public key to its `SHA256` sum. + +```bash +echo -n "my-awesome-service" | shasum -a 256 +# cf83fb2ffe64d959f93c3ade60a1c45421f016be3dcbbeda9ea7f1b78afdb698 - +``` + +So you would rename `id_rsa.pub`, or whatever your public key's name is, to `cf83fb2ffe64d959f93c3ade60a1c45421f016be3dcbbeda9ea7f1b78afdb698.pub` and upload +it to a http server of your liking. + +> **N.B.** The web service url and root path should be specified as environment variables, check `ASAP_PUB_KEYS_REPO_URL` and `ASAP_PUB_KEYS_FOLDER` in [Environment Variables](./env_vars.md). + +## Creating JWTs + +The JWT unencrypted header should look like this, note the mandatory `kid` with the name we picked earlier. + +```json +{ + "alg": "RS256", + "kid": "my-awesome-service", + "typ": "JWT" +} +``` + +The only mandatory field in the body is the `aud` claim, which must match at least one of the audiences defined in the `ASAP_PUB_KEYS_AUDS` environment variable, check [Environment Variables](./env_vars.md). + +Once you have your JWT, sign it with the private key and use it to access any of the services provided by Skynet. + +## Authorization Flow + +1. Skynet receives the JWT and reads the unencrypted header +2. It extracts the `kid` and performs a `SHA256` sum on the string +3. It then attempts to download the public key from `ASAP_PUB_KEYS_REPO_URL/ASAP_PUB_KEYS_FOLDER/{sha-sum-of-kid}.pem` if it cannot find it in the local cache +4. It checks if the signature and the audience match + +## Helper script + +Use this [bash script](jaas-jwt.sh) to quickly generate JWTs. Please note that you will still need to upload the public key somewhere and generate the key pair. + +```bash +./docs/jaas-jwt.sh PrivateKey.pk API-Key +# The generated token has a validity of 7200 seconds +``` + +## Examples + +### Issue a JWT in Java + +```java +private String getJWT() throws NoSuchAlgorithmException, InvalidKeySpecException + { + long nowMillis = System.currentTimeMillis(); + Date now = new Date(nowMillis); + KeyFactory kf = KeyFactory.getInstance("RSA"); + PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)); + PrivateKey finalPrivateKey = kf.generatePrivate(keySpecPKCS8); + JwtBuilder builder = Jwts.builder() + .setHeaderParam("kid", "my-awesome-service") + .setIssuedAt(now) + .setIssuer("myCoolApp") + .setAudience("my-audience") + .signWith(SignatureAlgorithm.RS256, finalPrivateKey); + long expires = nowMillis + (60 * 60 * 1000); + Date expiry = new Date(expires); + builder.setExpiration(expiry); + return builder.compact(); + } +``` + +### Issue a JWT in Python + +```python +import time +import os +import sys +import jwt + +parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.append(parent_dir) + +dir_path = os.path.dirname(os.path.realpath(__file__)) + +header = { + 'alg': 'RS256', + 'kid': 'my-awesome-service', + 'typ': 'JWT' +} + +claims = { + 'iss': 'myAwesomeApp', + 'exp': time.time() + 300, + 'user': 'me', + 'aud': 'my-audience' +} + +def create_jwt(claims: dict, headers: dict, secret_key: str) -> str: + return jwt.encode(claims, secret_key, headers=headers) + +with open(f'{dir_path}/keys/private.key', 'r') as f: + private_key = f.read() + +jwt = create_jwt(claims, header, private_key) + +print(jwt) +``` diff --git a/docs/env_vars.md b/docs/env_vars.md new file mode 100644 index 0000000..ef89d0d --- /dev/null +++ b/docs/env_vars.md @@ -0,0 +1,46 @@ +# Skynet Environment Variables + +Skynet is configurable via environment variables. Some are shared by all modules, while others are specific to each one of them. You can skip setting the env variables for the disabled modules. + +## Shared Environment Variables + +| **Name** | **Description** | **Default** | **Available values** | +|------------------------|-------------------------------------------------------------|-------------------------------------------|---------------------------------------------------------------------------------| +| `ENABLED_MODULES` | Which modules should be enabled, separated by commas | `summaries:dispatcher,summaries:executor` | `summaries:dispatcher`, `summaries:executor`, `openai-api`, `streaming_whisper` | +| `BYPASS_AUTHORIZATION` | If signed JWT authorization should be enabled | `false` | `true`, `false` | +| `ENABLE_MONITORING` | If the Prometheus metrics endpoint should be enabled or not | `true` | `true`, `false` | +| `ASAP_PUB_KEYS_REPO_URL` | Public key repository URL | `NULL` | N/A | +| `ASAP_PUB_KEYS_FOLDER` | Public key repository root path | `NULL` | N/A | +| `ASAP_PUB_KEYS_AUDS` | Allowed JWT audiences, separated by commas | `NULL` | N/A | +| `ASAP_PUB_KEYS_MAX_CACHE_SIZE` | Public key maximum cache size in bytes | `512` | N/A | + + +## Summaries Module Environment Variables + +| Name | **Description** | **Default** | **Available values** | +|----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------|------------------| +| `LLAMA_PATH` | The path where the llama GGUF model is located. | `NULL` | N/A | +| `LLAMA_N_GPU_LAYERS` | The number of layers to offload to the GPU. Depends on the hardware. The more layers are offloaded to the GPU, the faster it churns out responses. | `1` if running on Mac, `40` if not. | N/A | +| `LLAMA_N_BATCH` | The batch size used when parsing long texts. | `512` | N/A | +| `JOB_TIMEOUT` | Timeout in seconds after which an inference job will be considered stuck and the app killed. | `600` | N/A | +| `REDIS_EXP_SECONDS` | After how many seconds will a completed job expire/be deleted from Redis | `1800` | N/A | +| `REDIS_HOST` | Redis host | `localhost` | N/A | +| `REDIS_PORT` | Redis port | `6379` | N/A | +| `REDIS_USE_TLS` | Use TLS when connecting to Redis | `false` | N/A | +| `REDIS_DB_NO` | Redis database number | `0` | N/A | +| `REDIS_USR` | Redis user if using user/pass auth | `NULL` | N/A | +| `REDIS_PWD` | Redis pass if using user/pass auth | `NULL` | N/A | +| `REDIS_AWS_SECRET_ID` | The ID of the secret to retrieve from AWS Secrets Manager | `NULL` | N/A | +| `REDIS_USE_SECRETS_MANAGER` | Use AWS Secrets Manager to retrieve credentials | `false` | N/A | +| `REDIS_NAMESPACE` | Prefix for each Redis key | `skynet` | N/A | +| `REDIS_AWS_REGION` | The AWS region. Needed when using AWS Secrets Manager to retrieve credentials. | `us-west-2` | N/A | + +## Streaming Whisper Module Environment Variables + +| Name | **Description** | **Default** | **Available values** | +|----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------|------------------| +| `BEAM_SIZE` | Whisper beam size | `5` | N/A | +| `WHISPER_COMPUTE_TYPE` | Quantization https://opennmt.net/CTranslate2/quantization.html | `int8` | `int8`, `int8_float32`, `int8_float16`, `int8_bfloat16`, `int16`, `float16`, `bfloat16`, `float32` | +| `WHISPER_GPU_INDICES` | Use multiple GPUs if available by specifying the indices separated by commas, e.g. `0,1` for two GPUs | `0` | N/A | +| `WHISPER_DEVICE`| Which device to use for inference. The default `auto` will automatically detect if a GPU is present and fall back to `cpu` if not. | `auto` | `auto`, `cpu`, `gpu` | +| `WHISPER_MODEL_PATH` | The path to the model folder | `f'{os.getcwd()}/models/streaming_whisper'` | N/A | diff --git a/docs/monitoring.md b/docs/monitoring.md new file mode 100644 index 0000000..cbd074c --- /dev/null +++ b/docs/monitoring.md @@ -0,0 +1,139 @@ +# Monitoring + +Skynet exposes a Prometheus `/metrics` endpoint on port `8001`. + +The metrics endpoint can be disabled by setting the `ENABLE_MONITORING` env var to `false`. + +## Exposed metrics + +``` +# HELP python_gc_objects_collected_total Objects collected during gc +# TYPE python_gc_objects_collected_total counter +python_gc_objects_collected_total{generation="0"} 0.0 +python_gc_objects_collected_total{generation="1"} 0.0 +python_gc_objects_collected_total{generation="2"} 0.0 +# HELP python_gc_objects_uncollectable_total Uncollectable objects found during GC +# TYPE python_gc_objects_uncollectable_total counter +python_gc_objects_uncollectable_total{generation="0"} 0.0 +python_gc_objects_uncollectable_total{generation="1"} 0.0 +python_gc_objects_uncollectable_total{generation="2"} 0.0 +# HELP python_gc_collections_total Number of times this generation was collected +# TYPE python_gc_collections_total counter +python_gc_collections_total{generation="0"} 0.0 +python_gc_collections_total{generation="1"} 0.0 +python_gc_collections_total{generation="2"} 0.0 +# HELP python_info Python platform information +# TYPE python_info gauge +python_info{implementation="CPython",major="3",minor="11",patchlevel="7",version="3.11.7"} 1.0 +# HELP process_virtual_memory_bytes Virtual memory size in bytes. +# TYPE process_virtual_memory_bytes gauge +process_virtual_memory_bytes 0.0 +# HELP process_resident_memory_bytes Resident memory size in bytes. +# TYPE process_resident_memory_bytes gauge +process_resident_memory_bytes 0.0 +# HELP process_start_time_seconds Start time of the process since unix epoch in seconds. +# TYPE process_start_time_seconds gauge +process_start_time_seconds 0.0 +# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds. +# TYPE process_cpu_seconds_total counter +process_cpu_seconds_total 0.0 +# HELP process_open_fds Number of open file descriptors. +# TYPE process_open_fds gauge +process_open_fds 0.0 +# HELP process_max_fds Maximum number of open file descriptors. +# TYPE process_max_fds gauge +process_max_fds 0.0 +# HELP Skynet_Summaries_summary_input_length Measures the length of the input text +# TYPE Skynet_Summaries_summary_input_length histogram +Skynet_Summaries_summary_input_length_bucket{le="50.0"} 0.0 +Skynet_Summaries_summary_input_length_bucket{le="100.0"} 0.0 +Skynet_Summaries_summary_input_length_bucket{le="500.0"} 0.0 +Skynet_Summaries_summary_input_length_bucket{le="1000.0"} 0.0 +Skynet_Summaries_summary_input_length_bucket{le="2000.0"} 0.0 +Skynet_Summaries_summary_input_length_bucket{le="5000.0"} 0.0 +Skynet_Summaries_summary_input_length_bucket{le="10000.0"} 0.0 +Skynet_Summaries_summary_input_length_bucket{le="+Inf"} 0.0 +Skynet_Summaries_summary_input_length_count 0.0 +Skynet_Summaries_summary_input_length_sum 0.0 +# HELP Skynet_Summaries_summary_input_length_created Measures the length of the input text +# TYPE Skynet_Summaries_summary_input_length_created gauge +Skynet_Summaries_summary_input_length_created 0.0 +# HELP Skynet_Summaries_summary_duration_seconds Measures the duration of the summary / action items inference in seconds +# TYPE Skynet_Summaries_summary_duration_seconds histogram +Skynet_Summaries_summary_duration_seconds_bucket{le="1.0"} 0.0 +Skynet_Summaries_summary_duration_seconds_bucket{le="5.0"} 0.0 +Skynet_Summaries_summary_duration_seconds_bucket{le="25.0"} 0.0 +Skynet_Summaries_summary_duration_seconds_bucket{le="125.0"} 0.0 +Skynet_Summaries_summary_duration_seconds_bucket{le="+Inf"} 0.0 +Skynet_Summaries_summary_duration_seconds_count 0.0 +Skynet_Summaries_summary_duration_seconds_sum 0.0 +# HELP Skynet_Summaries_summary_duration_seconds_created Measures the duration of the summary / action items inference in seconds +# TYPE Skynet_Summaries_summary_duration_seconds_created gauge +Skynet_Summaries_summary_duration_seconds_created 0.0 +# HELP Skynet_Summaries_summary_queue_time_seconds Measures the time spent in the queue in seconds +# TYPE Skynet_Summaries_summary_queue_time_seconds histogram +Skynet_Summaries_summary_queue_time_seconds_bucket{le="1.0"} 0.0 +Skynet_Summaries_summary_queue_time_seconds_bucket{le="5.0"} 0.0 +Skynet_Summaries_summary_queue_time_seconds_bucket{le="25.0"} 0.0 +Skynet_Summaries_summary_queue_time_seconds_bucket{le="125.0"} 0.0 +Skynet_Summaries_summary_queue_time_seconds_bucket{le="+Inf"} 0.0 +Skynet_Summaries_summary_queue_time_seconds_count 0.0 +Skynet_Summaries_summary_queue_time_seconds_sum 0.0 +# HELP Skynet_Summaries_summary_queue_time_seconds_created Measures the time spent in the queue in seconds +# TYPE Skynet_Summaries_summary_queue_time_seconds_created gauge +Skynet_Summaries_summary_queue_time_seconds_created 0.0 +# HELP Skynet_Summaries_summary_queue_size Number of jobs in the queue +# TYPE Skynet_Summaries_summary_queue_size gauge +Skynet_Summaries_summary_queue_size 0.0 +# HELP Skynet_Streaming_Whisper_LiveWsConnections Number of active WS connections +# TYPE Skynet_Streaming_Whisper_LiveWsConnections gauge +Skynet_Streaming_Whisper_LiveWsConnections 0.0 +# HELP Skynet_Streaming_Whisper_WhisperTranscriptionDuration Measures the duration of the transcription process in seconds +# TYPE Skynet_Streaming_Whisper_WhisperTranscriptionDuration histogram +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="0.1"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="0.2"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="0.3"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="0.4"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="0.5"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="0.6"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="0.7"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="0.8"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="0.9"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="1.0"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="1.1"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="1.2"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="1.3"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="1.4"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="1.5"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="1.6"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="1.7"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="1.8"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="1.9"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="2.0"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="2.1"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="2.2"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="2.3"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="2.4"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="2.5"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="2.6"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="2.7"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="2.8"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="2.9"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="3.0"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_bucket{le="+Inf"} 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_count 0.0 +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_sum 0.0 +# HELP Skynet_Streaming_Whisper_WhisperTranscriptionDuration_created Measures the duration of the transcription process in seconds +# TYPE Skynet_Streaming_Whisper_WhisperTranscriptionDuration_created gauge +Skynet_Streaming_Whisper_WhisperTranscriptionDuration_created 0.0 +# HELP Skynet_Summaries_forced_exit_total Number of forced exits +# TYPE Skynet_Summaries_forced_exit_total counter +Skynet_Summaries_forced_exit_total 0.0 +# HELP Skynet_Summaries_forced_exit_created Number of forced exits +# TYPE Skynet_Summaries_forced_exit_created gauge +Skynet_Summaries_forced_exit_created 0.0 +# HELP http_request_duration_seconds Duration of HTTP requests in seconds +# TYPE http_request_duration_seconds histogram +# HELP Skynet_Summaries_http_requests_total Total number of requests by method, status and handler. +# TYPE Skynet_Summaries_http_requests_total counter +``` diff --git a/docs/streaming_whisper_module.md b/docs/streaming_whisper_module.md new file mode 100644 index 0000000..22788a2 --- /dev/null +++ b/docs/streaming_whisper_module.md @@ -0,0 +1,149 @@ +# Streaming Whisper Module + +Performs live transcriptions using [Faster Whisper](https://github.com/SYSTRAN/faster-whisper) via a websocket connection. + +Enable the module by setting the `ENABLED_MODULES` env var to `streaming_whisper`. + +> Here the JWT (see [Authorization](auth.md)) needs to be provided as a GET parameter. Please make sure to make it _very_ short-lived. + +## Requirements + +- Poetry + +## Quickstart + +```bash +# git lfs install +git clone git@hf.co:guillaumekln/faster-whisper-base.en "$HOME/my-models-folder/streaming-whisper" + +export BYPASS_AUTHORIZATION="true" +export ENABLED_MODULES="streaming_whisper" +export WHISPER_MODEL_PATH="$HOME/my-models-folder/streaming-whisper" + +poetry install +./run.sh +``` + +Go to [demos/streaming-whisper/](../demos/streaming-whisper/) and start a Python http server + +```bash +python3 -m http.server 8080 +``` + +Open http://127.0.0.1:8080. + +## Websocket connection string + +``` +wss|ws://{DOMAIN}:8000/streaming-whisper/ws/{UNIQUE_MEETING_ID}?auth_token={short-lived JWT} +``` + +Omit the `auth_token` parameter if authorization is disabled. + +## Authorization + +We pass the JWT as part of the connection string, so please make it as short lived as possible. Refer to [Authorization](auth.md) for more details regarding the generation of JWTs. + +## Data format + +The payload sent by the client should be a binary blob. Where the first 60 bytes must be a header composed by a unique speaker id plus the language in short ISO format separated by a pipe `|`. + +> E.G. `some_unique_speaker_id|en` + +If the header is not fully filled, it must be padded with nulls. The rest of the payload must be a raw, single-channel, 16khz, WAV array of bytes. **The audio chunk must not contain a WAV header**. Each audio chunk should be at least 1 second long. + +## Building the payload + +### Javascript client implementation + +```js +ws = new WebSocket('wss://' + host + '/streaming-whisper/ws/' + MEETINGID + '?auth_token=' + jwt.value) +ws.binaryType = 'blob' + + +function preparePayload(data) { + let lang = "ro" + let str = CLIENTID + "|" + lang + if (str.length < 60) { + str = str.padEnd(60, " ") + } + let utf8Encode = new TextEncoder() + let buffer = utf8Encode.encode(str) + + let headerArr = new Uint16Array(buffer.buffer) + + const payload = [] + + headerArr.forEach(i => payload.push(i)) + data.forEach(i => payload.push(i)) + + return Uint16Array.from(payload) +} + +recorder.port.onmessage = (e) => { + const audio = convertFloat32To16BitPCM(e.data) + const payload = preparePayload(audio) + ws.send(payload) +} +``` + +### Java client implementation + +```java +private ByteBuffer buildPayload(Participant participant, ByteBuffer audio) { + ByteBuffer header = ByteBuffer.allocate(60); + int lenAudio = audio.remaining(); + ByteBuffer fullPayload = ByteBuffer.allocate(lenAudio + 60); + String headerStr = participant.getDebugName() + "|" + this.getLanguage(participant); + header.put(headerStr.getBytes()).rewind(); + fullPayload.put(header).put(audio).rewind(); + return fullPayload; +} + +public void sendAudio(Participant participant, ByteBuffer audio) { + String participantId = participant.getDebugName(); + try + { + logger.debug("Sending audio for " + participantId); + session.getRemote().sendBytes(buildPayload(participant, audio)); + } + catch (NullPointerException e) + { + logger.error("Failed sending audio for " + participantId + ". " + e); + if (!session.isOpen()) + { + try + { + connect(); + } + catch (Exception ex) + { + logger.error(ex.toString()); + } + } + } + catch (IOException e) + { + logger.error("Failed sending audio for " + participantId + ". " + e); + } +} +``` + +## Build image + +You need to change the build and runtime images to `cuda:11.8.0-cudnn8-devel-ubuntu20.04` and `nvidia/cuda:11.8.0-cudnn8-runtime-ubuntu20.04` respectively. + +```bash +docker buildx build --build-arg="BASE_IMAGE_BUILD=nvidia/cuda:11.8.0-cudnn8-devel-ubuntu20.04" --build-arg="BASE_IMAGE_RUN=nvidia/cuda:11.8.0-cudnn8-runtime-ubuntu20.04" --push --progress plain --platform linux/amd64 -t your-registry/skynet:your-tag . +``` + +When running the resulting image, make sure to mount a faster-whisper model under `/models` on the container fs and reference it in the `WHISPER_MODEL_PATH` environment variable. + +```bash +git clone git@hf.co:guillaumekln/faster-whisper-base.en "$HOME/my-models-folder/streaming-whisper" +docker run -p 8000:8000 -e "BEAM_SIZE=1" -e "WHISPER_MODEL_PATH=/models/streaming-whisper" -e "ENABLED_MODULES=streaming_whisper" -e "BYPASS_AUTHORIZATION=true" -v "$HOME/my-models-folder":"/models" skynet:test-whisper +``` + +## Demo + +Check [/demos/streaming-whisper](../demos/streaming-whisper/) for a client implementation in Javascript. **Only works in Chrome-based browsers.** diff --git a/docs/summaries_module.md b/docs/summaries_module.md new file mode 100644 index 0000000..e091083 --- /dev/null +++ b/docs/summaries_module.md @@ -0,0 +1,62 @@ +# Skynet Summaries Module + +Extracts summaries and action items from a given text. The API wraps the wonderful [ggerganov/llama.cpp](https://github.com/ggerganov/llama.cpp). It is split into two sub-modules, `summaries:dispatcher` and `summaries:executor`. + +`summaries:dispatcher` will push jobs and retrieve job results from a Redis queue while `summaries:executor` performs the actual inference. They can both be enabled at the same time or deployed separately. + +> All requests to this service will require a standard HTTP Authorization header with a Bearer JWT. Check the [**Authorization page**](auth.md) for detailed information on how to generate JWTs or disable authorization. + +## Requirements + +- Redis +- Poetry + +## Flowchart + +Skynet Summaries Module Flowchart + +## Configuration + +All of the configuration is done via env vars. Check the [Skynet Environment Variables](env_vars.md) page for a list of values. + +## Running + +```bash +# Download the preferred GGUF llama model (e.g. https://huggingface.co/TheBloke/Llama-2-7b-Chat-GGUF) and point LLAMA_PATH to it +mkdir skynet/models + +wget -q --show-progress "https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/main/llama-2-7b-chat.Q4_K_M.gguf?download=true" -O skynet/models/llama-2-7b-chat.Q4_K_M.gguf + +export LLAMA_PATH="$(pwd)/skynet/models/llama-2-7b-chat.Q4_K_M.gguf" + +# start Redis +docker run -d --rm -p 6379:6379 redis + +poetry install +./run.sh +``` + +Visit http://127.0.0.1:8000 + +## Build Image + +```bash +docker buildx build --push --progress plain --platform linux/amd64 -t your-registry/skynet:your-tag . +``` + +When running the resulting image, make sure to mount a model under `/models` on the container fs. + +### Code samples + +JavaScript: https://github.com/jitsi/skynet/blob/master/docs/sample.js + +## Some benchmarks + +Summary: + +| Model | Input size | Time to summarize (M1 CPU) | Time to summarize (GPU) | +| :---- | :--------: |:---------------------------:|:-----------------------:| +| [llama-2-7b-chat.Q4_K_M.gguf][1] | 16000 chars | ~87 sec | ~44 sec | +| [llama-2-7b-chat.Q4_K_M.gguf][1] | 8000 chars | ~51 sec | ~28 sec | + +[1]: https://huggingface.co/TheBloke/Llama-2-7b-Chat-GGUF/blob/main/llama-2-7b-chat.Q4_K_M.gguf diff --git a/poetry.lock b/poetry.lock index 6abb120..e258005 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.0 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" @@ -280,17 +280,17 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "boto3" -version = "1.34.19" +version = "1.34.21" description = "The AWS SDK for Python" optional = false python-versions = ">= 3.8" files = [ - {file = "boto3-1.34.19-py3-none-any.whl", hash = "sha256:4c76ef92af7dbdcea21b196a2699671e82e8814d4cfe570c48eda477dd1aeb19"}, - {file = "boto3-1.34.19.tar.gz", hash = "sha256:95d2c2bde86a0934d4c461020c50fc1344b444f167654e215f1de549bc77fc0f"}, + {file = "boto3-1.34.21-py3-none-any.whl", hash = "sha256:88e3baeb53ae421aabd44bb49ebdd7122b74b53b0f437b0f3e17141f6744574a"}, + {file = "boto3-1.34.21.tar.gz", hash = "sha256:206e61ba1f8c830e5df0355606d178ad5bc970df12c4c318b021c71da410eb0c"}, ] [package.dependencies] -botocore = ">=1.34.19,<1.35.0" +botocore = ">=1.34.21,<1.35.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.10.0,<0.11.0" @@ -299,13 +299,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.34.19" +version = "1.34.21" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">= 3.8" files = [ - {file = "botocore-1.34.19-py3-none-any.whl", hash = "sha256:a4a39c7092960f5da2439efc5f6220730dab634aaff4c1444bbd1dfa43bc28cc"}, - {file = "botocore-1.34.19.tar.gz", hash = "sha256:64352b2f05de5c6ab025c1d5232880c22775356dcc5a53d798a6f65db847e826"}, + {file = "botocore-1.34.21-py3-none-any.whl", hash = "sha256:43274fd3f8e02573790ee76313607c60e3c15a7a0d89d24dfe4042f882f1f8c9"}, + {file = "botocore-1.34.21.tar.gz", hash = "sha256:21983bb0473a19130192c50ec6974d55f0c4aa48a7094bcf40f7882c8b69b8f1"}, ] [package.dependencies] @@ -1108,6 +1108,54 @@ files = [ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, ] +[[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 = "huggingface-hub" version = "0.20.2" @@ -1356,13 +1404,13 @@ text-helpers = ["chardet (>=5.1.0,<6.0.0)"] [[package]] name = "langchain-community" -version = "0.0.12" +version = "0.0.13" description = "Community contributed LangChain integrations." optional = false python-versions = ">=3.8.1,<4.0" files = [ - {file = "langchain_community-0.0.12-py3-none-any.whl", hash = "sha256:13b988afaa24e570d2b9992aecccb2fe36d9c33feafd9804f3066dc2ff042d4d"}, - {file = "langchain_community-0.0.12.tar.gz", hash = "sha256:7cfe36c52b1fb86c1095d4dec0cf466a1c752a7446104e8b39cf0f70512a4851"}, + {file = "langchain_community-0.0.13-py3-none-any.whl", hash = "sha256:655196e446e7f37f4882221b6f3f791d6add28ea596d521ccf6f4507386b9a13"}, + {file = "langchain_community-0.0.13.tar.gz", hash = "sha256:cf66c6ff7fcbeb582f5e88ee00decea7fdeca5ccddda725046f28efc697c41a7"}, ] [package.dependencies] @@ -1382,13 +1430,13 @@ extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15. [[package]] name = "langchain-core" -version = "0.1.10" +version = "0.1.12" description = "Building applications with LLMs through composability" optional = false python-versions = ">=3.8.1,<4.0" files = [ - {file = "langchain_core-0.1.10-py3-none-any.whl", hash = "sha256:d89952f6d0766cfc88d9f1e25b84d56f8d7bd63a45ad8ec1a9a038c9b49df16d"}, - {file = "langchain_core-0.1.10.tar.gz", hash = "sha256:3c9e1383264c102fcc6f865700dbb9416c4931a25d0ac2195f6311c6b867aa17"}, + {file = "langchain_core-0.1.12-py3-none-any.whl", hash = "sha256:d11c6262f7a9deff7de8fdf14498b8a951020dfed3a80f2358ab731ad04abef0"}, + {file = "langchain_core-0.1.12.tar.gz", hash = "sha256:f18e9300e9a07589b3e280e51befbc5a4513f535949406e55eb7a2dc40c3ce66"}, ] [package.dependencies] @@ -1406,13 +1454,13 @@ extended-testing = ["jinja2 (>=3,<4)"] [[package]] name = "langsmith" -version = "0.0.80" +version = "0.0.82" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = false python-versions = ">=3.8.1,<4.0" files = [ - {file = "langsmith-0.0.80-py3-none-any.whl", hash = "sha256:dee1c6ef9e8241b82a8851926624269954d0ff8e22d82e32e73455f387f4e245"}, - {file = "langsmith-0.0.80.tar.gz", hash = "sha256:6d22ee07eb41c65b3f5166b20041a026714952497d9e80d5be6879d3a5c14d84"}, + {file = "langsmith-0.0.82-py3-none-any.whl", hash = "sha256:b17eed8351bcb375e46ce6d47e1b9bdd41826d0cc167eb96cbe0989ca966ce57"}, + {file = "langsmith-0.0.82.tar.gz", hash = "sha256:0645e0315e836f36a7b5de34efb765fcf3abda1ac79bcaf7a66d40c40e942ae4"}, ] [package.dependencies] @@ -1520,16 +1568,6 @@ files = [ {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-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {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"}, @@ -2428,7 +2466,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"}, @@ -2436,15 +2473,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_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"}, @@ -2461,7 +2491,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"}, @@ -2469,7 +2498,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"}, @@ -3161,22 +3189,73 @@ files = [ [[package]] name = "uvicorn" -version = "0.25.0" +version = "0.26.0" description = "The lightning-fast ASGI server." optional = false python-versions = ">=3.8" files = [ - {file = "uvicorn-0.25.0-py3-none-any.whl", hash = "sha256:ce107f5d9bd02b4636001a77a4e74aab5e1e2b146868ebbad565237145af444c"}, - {file = "uvicorn-0.25.0.tar.gz", hash = "sha256:6dddbad1d7ee0f5140aba5ec138ddc9612c5109399903828b4874c9937f009c2"}, + {file = "uvicorn-0.26.0-py3-none-any.whl", hash = "sha256:cdb58ef6b8188c6c174994b2b1ba2150a9a8ae7ea5fb2f1b856b94a815d6071d"}, + {file = "uvicorn-0.26.0.tar.gz", hash = "sha256:48bfd350fce3c5c57af5fb4995fded8fb50da3b4feb543eb18ad7e0d54589602"}, ] [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 = "virtualenv" version = "20.25.0" @@ -3197,6 +3276,174 @@ platformdirs = ">=3.9.1,<5" docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "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)"] +[[package]] +name = "watchfiles" +version = "0.21.0" +description = "Simple, modern and high performance file watching and code reload in python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "watchfiles-0.21.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:27b4035013f1ea49c6c0b42d983133b136637a527e48c132d368eb19bf1ac6aa"}, + {file = "watchfiles-0.21.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c81818595eff6e92535ff32825f31c116f867f64ff8cdf6562cd1d6b2e1e8f3e"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6c107ea3cf2bd07199d66f156e3ea756d1b84dfd43b542b2d870b77868c98c03"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d9ac347653ebd95839a7c607608703b20bc07e577e870d824fa4801bc1cb124"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5eb86c6acb498208e7663ca22dbe68ca2cf42ab5bf1c776670a50919a56e64ab"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f564bf68404144ea6b87a78a3f910cc8de216c6b12a4cf0b27718bf4ec38d303"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d0f32ebfaa9c6011f8454994f86108c2eb9c79b8b7de00b36d558cadcedaa3d"}, + {file = "watchfiles-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6d45d9b699ecbac6c7bd8e0a2609767491540403610962968d258fd6405c17c"}, + {file = "watchfiles-0.21.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:aff06b2cac3ef4616e26ba17a9c250c1fe9dd8a5d907d0193f84c499b1b6e6a9"}, + {file = "watchfiles-0.21.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d9792dff410f266051025ecfaa927078b94cc7478954b06796a9756ccc7e14a9"}, + {file = "watchfiles-0.21.0-cp310-none-win32.whl", hash = "sha256:214cee7f9e09150d4fb42e24919a1e74d8c9b8a9306ed1474ecaddcd5479c293"}, + {file = "watchfiles-0.21.0-cp310-none-win_amd64.whl", hash = "sha256:1ad7247d79f9f55bb25ab1778fd47f32d70cf36053941f07de0b7c4e96b5d235"}, + {file = "watchfiles-0.21.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:668c265d90de8ae914f860d3eeb164534ba2e836811f91fecc7050416ee70aa7"}, + {file = "watchfiles-0.21.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a23092a992e61c3a6a70f350a56db7197242f3490da9c87b500f389b2d01eef"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e7941bbcfdded9c26b0bf720cb7e6fd803d95a55d2c14b4bd1f6a2772230c586"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11cd0c3100e2233e9c53106265da31d574355c288e15259c0d40a4405cbae317"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78f30cbe8b2ce770160d3c08cff01b2ae9306fe66ce899b73f0409dc1846c1b"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6674b00b9756b0af620aa2a3346b01f8e2a3dc729d25617e1b89cf6af4a54eb1"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd7ac678b92b29ba630d8c842d8ad6c555abda1b9ef044d6cc092dacbfc9719d"}, + {file = "watchfiles-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c873345680c1b87f1e09e0eaf8cf6c891b9851d8b4d3645e7efe2ec20a20cc7"}, + {file = "watchfiles-0.21.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:49f56e6ecc2503e7dbe233fa328b2be1a7797d31548e7a193237dcdf1ad0eee0"}, + {file = "watchfiles-0.21.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:02d91cbac553a3ad141db016e3350b03184deaafeba09b9d6439826ee594b365"}, + {file = "watchfiles-0.21.0-cp311-none-win32.whl", hash = "sha256:ebe684d7d26239e23d102a2bad2a358dedf18e462e8808778703427d1f584400"}, + {file = "watchfiles-0.21.0-cp311-none-win_amd64.whl", hash = "sha256:4566006aa44cb0d21b8ab53baf4b9c667a0ed23efe4aaad8c227bfba0bf15cbe"}, + {file = "watchfiles-0.21.0-cp311-none-win_arm64.whl", hash = "sha256:c550a56bf209a3d987d5a975cdf2063b3389a5d16caf29db4bdddeae49f22078"}, + {file = "watchfiles-0.21.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:51ddac60b96a42c15d24fbdc7a4bfcd02b5a29c047b7f8bf63d3f6f5a860949a"}, + {file = "watchfiles-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:511f0b034120cd1989932bf1e9081aa9fb00f1f949fbd2d9cab6264916ae89b1"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cfb92d49dbb95ec7a07511bc9efb0faff8fe24ef3805662b8d6808ba8409a71a"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f92944efc564867bbf841c823c8b71bb0be75e06b8ce45c084b46411475a915"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:642d66b75eda909fd1112d35c53816d59789a4b38c141a96d62f50a3ef9b3360"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d23bcd6c8eaa6324fe109d8cac01b41fe9a54b8c498af9ce464c1aeeb99903d6"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18d5b4da8cf3e41895b34e8c37d13c9ed294954907929aacd95153508d5d89d7"}, + {file = "watchfiles-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b8d1eae0f65441963d805f766c7e9cd092f91e0c600c820c764a4ff71a0764c"}, + {file = "watchfiles-0.21.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1fd9a5205139f3c6bb60d11f6072e0552f0a20b712c85f43d42342d162be1235"}, + {file = "watchfiles-0.21.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a1e3014a625bcf107fbf38eece0e47fa0190e52e45dc6eee5a8265ddc6dc5ea7"}, + {file = "watchfiles-0.21.0-cp312-none-win32.whl", hash = "sha256:9d09869f2c5a6f2d9df50ce3064b3391d3ecb6dced708ad64467b9e4f2c9bef3"}, + {file = "watchfiles-0.21.0-cp312-none-win_amd64.whl", hash = "sha256:18722b50783b5e30a18a8a5db3006bab146d2b705c92eb9a94f78c72beb94094"}, + {file = "watchfiles-0.21.0-cp312-none-win_arm64.whl", hash = "sha256:a3b9bec9579a15fb3ca2d9878deae789df72f2b0fdaf90ad49ee389cad5edab6"}, + {file = "watchfiles-0.21.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:4ea10a29aa5de67de02256a28d1bf53d21322295cb00bd2d57fcd19b850ebd99"}, + {file = "watchfiles-0.21.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:40bca549fdc929b470dd1dbfcb47b3295cb46a6d2c90e50588b0a1b3bd98f429"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9b37a7ba223b2f26122c148bb8d09a9ff312afca998c48c725ff5a0a632145f7"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec8c8900dc5c83650a63dd48c4d1d245343f904c4b64b48798c67a3767d7e165"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8ad3fe0a3567c2f0f629d800409cd528cb6251da12e81a1f765e5c5345fd0137"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d353c4cfda586db2a176ce42c88f2fc31ec25e50212650c89fdd0f560ee507b"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:83a696da8922314ff2aec02987eefb03784f473281d740bf9170181829133765"}, + {file = "watchfiles-0.21.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a03651352fc20975ee2a707cd2d74a386cd303cc688f407296064ad1e6d1562"}, + {file = "watchfiles-0.21.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3ad692bc7792be8c32918c699638b660c0de078a6cbe464c46e1340dadb94c19"}, + {file = "watchfiles-0.21.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06247538e8253975bdb328e7683f8515ff5ff041f43be6c40bff62d989b7d0b0"}, + {file = "watchfiles-0.21.0-cp38-none-win32.whl", hash = "sha256:9a0aa47f94ea9a0b39dd30850b0adf2e1cd32a8b4f9c7aa443d852aacf9ca214"}, + {file = "watchfiles-0.21.0-cp38-none-win_amd64.whl", hash = "sha256:8d5f400326840934e3507701f9f7269247f7c026d1b6cfd49477d2be0933cfca"}, + {file = "watchfiles-0.21.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:7f762a1a85a12cc3484f77eee7be87b10f8c50b0b787bb02f4e357403cad0c0e"}, + {file = "watchfiles-0.21.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6e9be3ef84e2bb9710f3f777accce25556f4a71e15d2b73223788d528fcc2052"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4c48a10d17571d1275701e14a601e36959ffada3add8cdbc9e5061a6e3579a5d"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c889025f59884423428c261f212e04d438de865beda0b1e1babab85ef4c0f01"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:66fac0c238ab9a2e72d026b5fb91cb902c146202bbd29a9a1a44e8db7b710b6f"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4a21f71885aa2744719459951819e7bf5a906a6448a6b2bbce8e9cc9f2c8128"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c9198c989f47898b2c22201756f73249de3748e0fc9de44adaf54a8b259cc0c"}, + {file = "watchfiles-0.21.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f57c4461cd24fda22493109c45b3980863c58a25b8bec885ca8bea6b8d4b28"}, + {file = "watchfiles-0.21.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:853853cbf7bf9408b404754b92512ebe3e3a83587503d766d23e6bf83d092ee6"}, + {file = "watchfiles-0.21.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d5b1dc0e708fad9f92c296ab2f948af403bf201db8fb2eb4c8179db143732e49"}, + {file = "watchfiles-0.21.0-cp39-none-win32.whl", hash = "sha256:59137c0c6826bd56c710d1d2bda81553b5e6b7c84d5a676747d80caf0409ad94"}, + {file = "watchfiles-0.21.0-cp39-none-win_amd64.whl", hash = "sha256:6cb8fdc044909e2078c248986f2fc76f911f72b51ea4a4fbbf472e01d14faa58"}, + {file = "watchfiles-0.21.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ab03a90b305d2588e8352168e8c5a1520b721d2d367f31e9332c4235b30b8994"}, + {file = "watchfiles-0.21.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:927c589500f9f41e370b0125c12ac9e7d3a2fd166b89e9ee2828b3dda20bfe6f"}, + {file = "watchfiles-0.21.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd467213195e76f838caf2c28cd65e58302d0254e636e7c0fca81efa4a2e62c"}, + {file = "watchfiles-0.21.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02b73130687bc3f6bb79d8a170959042eb56eb3a42df3671c79b428cd73f17cc"}, + {file = "watchfiles-0.21.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:08dca260e85ffae975448e344834d765983237ad6dc308231aa16e7933db763e"}, + {file = "watchfiles-0.21.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:3ccceb50c611c433145502735e0370877cced72a6c70fd2410238bcbc7fe51d8"}, + {file = "watchfiles-0.21.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57d430f5fb63fea141ab71ca9c064e80de3a20b427ca2febcbfcef70ff0ce895"}, + {file = "watchfiles-0.21.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dd5fad9b9c0dd89904bbdea978ce89a2b692a7ee8a0ce19b940e538c88a809c"}, + {file = "watchfiles-0.21.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:be6dd5d52b73018b21adc1c5d28ac0c68184a64769052dfeb0c5d9998e7f56a2"}, + {file = "watchfiles-0.21.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b3cab0e06143768499384a8a5efb9c4dc53e19382952859e4802f294214f36ec"}, + {file = "watchfiles-0.21.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c6ed10c2497e5fedadf61e465b3ca12a19f96004c15dcffe4bd442ebadc2d85"}, + {file = "watchfiles-0.21.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43babacef21c519bc6631c5fce2a61eccdfc011b4bcb9047255e9620732c8097"}, + {file = "watchfiles-0.21.0.tar.gz", hash = "sha256:c76c635fabf542bb78524905718c39f736a98e5ab25b23ec6d4abede1a85a6a3"}, +] + +[package.dependencies] +anyio = ">=3.0.0" + +[[package]] +name = "websockets" +version = "12.0" +description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" +optional = false +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 = "xattr" version = "0.10.1" @@ -3402,4 +3649,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "~3.11" -content-hash = "380ae356b760ae6cfaa6eec0176ceafe95f249b352c8fbe5cea58da456f74ca2" +content-hash = "2932b16fc9c97fc8cfff3cc16901a39cb60ca28f8436ff1cae789abfa4e44d10" diff --git a/pyproject.toml b/pyproject.toml index eef3d77..c9872c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ redis = "5.0.1" torch = ">=2.0.0,<2.1.0" torchaudio = ">=2.0.1,<2.1.0" uuid6 = ">=2023.5.2" -uvicorn = "0.25.0" +uvicorn = {extras = ["standard"], version = "^0.26.0"} [build-system] build-backend = "poetry.core.masonry.api" diff --git a/requirements.txt b/requirements.txt index 3a67747..637d5be 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,13 +6,13 @@ async-lru==2.0.4 ; python_version >= "3.11" and python_version < "3.12" async-timeout==4.0.3 ; python_version >= "3.11" and python_full_version <= "3.11.2" attrs==23.2.0 ; python_version >= "3.11" and python_version < "3.12" av==10.0.0 ; python_version >= "3.11" and python_version < "3.12" -boto3==1.34.19 ; python_version >= "3.11" and python_version < "3.12" -botocore==1.34.19 ; python_version >= "3.11" and python_version < "3.12" +boto3==1.34.21 ; python_version >= "3.11" and python_version < "3.12" +botocore==1.34.21 ; python_version >= "3.11" and python_version < "3.12" certifi==2023.11.17 ; python_version >= "3.11" and python_version < "3.12" cffi==1.16.0 ; python_version >= "3.11" and python_version < "3.12" charset-normalizer==3.3.2 ; python_version >= "3.11" and python_version < "3.12" click==8.1.7 ; python_version >= "3.11" and python_version < "3.12" -colorama==0.4.6 ; python_version >= "3.11" and python_version < "3.12" and platform_system == "Windows" +colorama==0.4.6 ; python_version >= "3.11" and python_version < "3.12" and (sys_platform == "win32" or platform_system == "Windows") coloredlogs==15.0.1 ; python_version >= "3.11" and python_version < "3.12" cryptography==41.0.7 ; python_version >= "3.11" and python_version < "3.12" ctranslate2==3.24.0 ; python_version >= "3.11" and python_version < "3.12" @@ -27,6 +27,7 @@ frozenlist==1.4.1 ; python_version >= "3.11" and python_version < "3.12" fsspec==2023.12.2 ; python_version >= "3.11" and python_version < "3.12" greenlet==3.0.3 ; python_version >= "3.11" and python_version < "3.12" and (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") h11==0.14.0 ; python_version >= "3.11" and python_version < "3.12" +httptools==0.6.1 ; python_version >= "3.11" and python_version < "3.12" huggingface-hub==0.20.2 ; python_version >= "3.11" and python_version < "3.12" humanfriendly==10.0 ; python_version >= "3.11" and python_version < "3.12" idna==3.6 ; python_version >= "3.11" and python_version < "3.12" @@ -34,10 +35,10 @@ jinja2==3.1.3 ; python_version >= "3.11" and python_version < "3.12" jmespath==1.0.1 ; python_version >= "3.11" and python_version < "3.12" jsonpatch==1.33 ; python_version >= "3.11" and python_version < "3.12" jsonpointer==2.4 ; python_version >= "3.11" and python_version < "3.12" -langchain-community==0.0.12 ; python_version >= "3.11" and python_version < "3.12" -langchain-core==0.1.10 ; python_version >= "3.11" and python_version < "3.12" +langchain-community==0.0.13 ; python_version >= "3.11" and python_version < "3.12" +langchain-core==0.1.12 ; python_version >= "3.11" and python_version < "3.12" langchain==0.0.354 ; python_version >= "3.11" and python_version < "3.12" -langsmith==0.0.80 ; python_version >= "3.11" and python_version < "3.12" +langsmith==0.0.82 ; python_version >= "3.11" and python_version < "3.12" llama-cpp-python[server]==0.2.18 ; python_version >= "3.11" and python_version < "3.12" markupsafe==2.1.3 ; python_version >= "3.11" and python_version < "3.12" marshmallow==3.20.2 ; python_version >= "3.11" and python_version < "3.12" @@ -81,5 +82,9 @@ typing-extensions==4.9.0 ; python_version >= "3.11" and python_version < "3.12" typing-inspect==0.9.0 ; python_version >= "3.11" and python_version < "3.12" urllib3==2.0.7 ; python_version >= "3.11" and python_version < "3.12" uuid6==2024.1.12 ; python_version >= "3.11" and python_version < "3.12" -uvicorn==0.25.0 ; python_version >= "3.11" and python_version < "3.12" +uvicorn==0.26.0 ; python_version >= "3.11" and python_version < "3.12" +uvicorn[standard]==0.26.0 ; python_version >= "3.11" and python_version < "3.12" +uvloop==0.19.0 ; (sys_platform != "win32" and sys_platform != "cygwin") and platform_python_implementation != "PyPy" and python_version >= "3.11" and python_version < "3.12" +watchfiles==0.21.0 ; python_version >= "3.11" and python_version < "3.12" +websockets==12.0 ; python_version >= "3.11" and python_version < "3.12" yarl==1.9.4 ; python_version >= "3.11" and python_version < "3.12" diff --git a/skynet/modules/stt/streaming_whisper/ConnectionManager.py b/skynet/modules/stt/streaming_whisper/ConnectionManager.py index 7b5ce8e..3e7f729 100644 --- a/skynet/modules/stt/streaming_whisper/ConnectionManager.py +++ b/skynet/modules/stt/streaming_whisper/ConnectionManager.py @@ -18,14 +18,15 @@ def __init__(self): self.connections: dict[str, MeetingConnection] = {} async def connect(self, websocket: WebSocket, meeting_id: str, auth_token: str | None): - authorized = await authorize(auth_token) - if bypass_auth or authorized: - await websocket.accept() - self.connections[meeting_id] = MeetingConnection(websocket) - CONNECTIONS_METRIC.set(len(self.connections)) - log.info(f'Client {meeting_id} connected. Connection count {len(self.connections)}') - else: - await websocket.close(401, 'Bad JWT token') + if not bypass_auth: + authorized = await authorize(auth_token) + if not authorized: + await websocket.close(401, 'Bad JWT token') + return + await websocket.accept() + self.connections[meeting_id] = MeetingConnection(websocket) + CONNECTIONS_METRIC.set(len(self.connections)) + log.info(f'Client {meeting_id} connected. Connection count {len(self.connections)}') async def process(self, meeting_id: str, chunk: bytes): if meeting_id not in self.connections: diff --git a/skynet/modules/stt/streaming_whisper/cfg.py b/skynet/modules/stt/streaming_whisper/cfg.py index 85b77eb..f0d73fe 100644 --- a/skynet/modules/stt/streaming_whisper/cfg.py +++ b/skynet/modules/stt/streaming_whisper/cfg.py @@ -18,7 +18,7 @@ def get_device() -> str: return 'cpu' -vad_model = vad.init_jit_model(f'{os.getcwd()}/modules/stt/streaming_whisper/models/vad/silero_vad.jit') +vad_model = vad.init_jit_model(f'{os.getcwd()}/skynet/modules/stt/streaming_whisper/models/vad/silero_vad.jit') device = whisper_device if whisper_device != 'auto' else get_device() log.info(f'Using {device}') diff --git a/skynet/sample.txt b/skynet/sample.txt deleted file mode 100644 index bf3eaec..0000000 --- a/skynet/sample.txt +++ /dev/null @@ -1 +0,0 @@ -"Andrew: Hello. Beatrix: Honey? It’s me . . . Andrew: Where are you? Beatrix: At the station. I missed my train so I’m going to be late. Andrew: Oh, that’s too bad. Will you get back in time to pick up the kids? Beatrix: I don’t think so. Can you get them? Andrew: No problem. Beatrix: Make sure they start their homework. Andrew: Don’t worry. What time do you think you’ll be home? Beatrix: Probably in about an hour. How was your day? Andrew: Well, I worked for a few hours at the computer, and then I got sleepy, so I took a nap. Beatrix: You took a nap! You’re so lucky you work at home. I can’t take a nap in the office, you know. Andrew: But I also did the laundry and the dishes. You can’t do those things at the office. Beatrix: Well, that’s true. Hey, what’s for dinner? Andrew: Chicken. It’ll be ready when you get home. Beatrix: I can’t wait. I love your chicken. Andrew: And I love you. See you around 6:30? Beatrix: I hope so. See ya." \ No newline at end of file diff --git a/skynet/sample_long.txt b/skynet/sample_long.txt deleted file mode 100644 index b1278f0..0000000 --- a/skynet/sample_long.txt +++ /dev/null @@ -1 +0,0 @@ -"Yana: hello;Yana: don't many people signed today;Yana: we want any secrets to go home;Yana: Friday everyone;Andrei Gavrilescu: happy Friday to you too;Yana: go home now means moving from the desk of the couch;Andrei Gavrilescu: YouTube close the laptop;Andrei Gavrilescu: leave the office room go to your actual home;Yana: let me think;Yana: while waiting for marijuana can I ask you;Yana: The Thing theme;Oana: yes so Mario's tested and she submitted a bag I asked him let me see;Oana: Michael Myers pasta;Yana: she was able to reproduce;Oana: he wanted with three people in one case not for if he was the agility case but what I say when I ask for the ticket;Yana: thank you and I'm always now here so we can start;Emil Ivov: I saw you were committed an example so who sent it to me was hoping whoever that we could have a from what I saw it was just that there was just a consular;Emil Ivov: come get your JWT from here;Tudor: okay;Emil Ivov: we have one like the men for jazz or how you generate the That Dope;Tudor: I'm saying I don't think we have;Emil Ivov: how much you can generate within Jazz you can generate a key;Tudor: users can generate ingredients using the sample igit;Emil Ivov: you mean the token you can get it and download it right but from a public-private keep are there's nothing that tells you;Tudor: I mean you can go to jw.org on yourself but you also have to ask The Gabbie Hanna;Tudor: flashlight;Tudor: Brookings rich;Tudor: this might also change so we also have to keep up updating it tonight;Tudor: Beallsville also have to update assembled that.;Tudor: panda;Tudor: I'm in jw.org spine because the private key never leaves the browser and I'm not sure how would we do that;Tudor: I have to expose the Social Web interface;Emil Ivov: how do you generate your key;Tudor: public and private keys there;Tudor: I think Heather has a script;Tudor: yeah you need to stop me to eat;Emil Ivov: that one he did share that one with me and icky and it's;Tudor: devious designs;Emil Ivov: because;Emil Ivov: uses;Emil Ivov: not the one that you get from pip and you have to have Audrey to get better dependency management I'm thinking he's so complicated so;Emil Ivov: complicated then we can have one line that says here that's how we do it;Emil Ivov: quite understand is is it complicated to describing weekend definitely should do it or is it to simple in which others and why are we not doing it I'm kind of lost;Tudor: okay;Tudor: I guess we can try and see how that works and if it's not too much of a pain from the dependencies;Emil Ivov: Mike might look my point is I want to send this to Johnny so it should pass it to whoever in her immunization coming over to work on this and I want them to know what to do with this thing when they get it I want him to know here's how you tested and here's why we agree to working and can we start from;Tudor: wait so the first problem here is that way.;Tudor: I have to have a publicly shared with us;Emil Ivov: and that I can easily explain and tell them just get yourself a jazz account and make sure you have a key registered that and use that key to generate your token like soap and it's the likes o that I'm missing;Tudor: is the description that iPad is not sufficient or is it too cumbersome;Emil Ivov: maybe I'm looking at something I so I so so who sent me a script that does a bunch of things yes a JavaScript;Tudor: JavaScript;Tudor: text;Tudor: link to the literate me order apple and that one also contains the two ways you can generate cheetah booties that are valid;Tudor: sides do a link to the actual sample implementation documentation on how to generate a TT;Emil Ivov: okay I haven't seen I'm looking at it now okay;Emil Ivov: Animoto said the page;Tudor: yeah it's past its should have a section called;Tudor: how's it going CenturyLink;Emil Ivov: generate the jwtf specified here and then I'm going to specify here;Emil Ivov: okay and that it has an Indica so everything everything there is the way it is said to be right it's you have to use that kid you have to use your magic;Emil Ivov: thank you for;Emil Ivov: I'll try.;Emil Ivov: thank you;Emil Ivov: can you stand up;Tudor: I guess so mostly work around two condition or stain it also created some flow chart for how Skynet works and also a bit of how it's supposed to be used and also have some concerns I had some;Tudor: the fact that's currency on deployment state is lost because we're not assisting jobs around progress so if we're going to;Tudor: how many customers we would get with a. At one point we probably have to think about this and insertion cuz right now every time we did apply to service the jobs are lost;Tudor: summer;Tudor: or maybe;Oana: today so I had to put some more things back for about and then you where I clicked it;Oana: how to stop ice ice pick The Mists of the invoices;Emil Ivov: who is ready to move to strike;Emil Ivov: so so they all confirmed that they will do that what does it what does it mean ready to move to strike as opposed to just move to;Oana: they still have invoices and paid on the old system they were building, they're just trying to clarify all the invoices with with them and have everything clean;Emil Ivov: I wonder whether Visa we can probably stop can probably stop doing the splitting if we just tell them;Emil Ivov: a researcher to Giovanni and then so can you enable back payments for be soft as well so that they see the bank information and then I'll tell Giovanni that they can start using it when I;Oana: yes yes I'll forward this to work we have to remove all their credit cards and they have like turkeys;Emil Ivov: why do we have to;Oana: otherwise until at the due date;Emil Ivov: why is that I'm pretty sure I vote;Oana: I know I said you date was still show as of today when I was tired of being second not interview days;Emil Ivov: okay well let's just add the bank details without changing anything else so that the thing is there and then I'll have Giovani cuz I wanted to see it;Emil Ivov: got bank account.;Emil Ivov: music;Emil Ivov: do you want;Emil Ivov: doing;Oana: I also told to Jovani a message because they did five invoices;Oana: Friday Warriors Plaza 3 that I generated 2 days;Oana: I got home and in the morning;Oana: in the morning we tried to see what was the movie Brave;Oana: we would need the making rings;Yana: I have a question I have a question;Yana: accordingly;Yana: in a slash in a stream;Yana: but it is.;Yana: the meeting and if it's not I don't we make some muffins so that we don't go out;Yana: many people may be so so basically the problem is;Yana: affordable recording they give us the recording you around they say they're not able to download this recording;Yana: and then I'll table 2002 meeting this was then we're not able to search through this gyro;Oana: in this case is the recording URL yes so we don't keep the history for the week past users;Yana: but how would they also get that you're out of the meeting because they see a different URL when they integrate jazz;Yana: we have to go and join this meeting again and going like the elements and go there and get that you're out and it smells;Yana: we should think of something about those things.;Oana: okay I will explain;Yana: Steele's explained that Rollie by said they now though so I explained it to her yesterday;Yana: they are staying at and it's not only about recordings so we may have to think about that;Emil Ivov: should we have a discussion about this at the end;Oana: okay;Oana: now I'm looking;Oana: if it's on there and I want to see we're back;Mihaela: thanks call in the morning I did some tests for debacle that are making some changes to our back form in the way tickets get to sembawang the changes we're fine others to something else;Mihaela: live Disco;Mihaela: gold. Whatever Taco a small bag but went on a full tangent and started by trying to fix a fix bag that was missing somewhere but then I noticed some irregularities around display the important this training and eventually I;Mihaela: I agree with someone;Mihaela: and I also have the same with him;Horas: today's support guilty not so many things that are like three or four tickets all related;Horas: the quality of the meeting they are complaining the;Horas: love you do a snot out of sync with audio sometimes and sometimes it's blurry;Horas: isn't that at least for some hot Asana for work some meetings a meeting with Anna and one of the situation and they helped us;Horas: half the image the screenshot taken in the in the event election thing say it being saved on the CSS;Horas: MPG;Andrei Gavrilescu: yellow plated some training and investigated the issue with green where they are tracking for wasn't showing the problem fixed;Andrei Gavrilescu: extended;robert oanta: oh I continent without factoring history so some discussions that they had me to go to your house yesterday I found out that the tasks were generating some reason action items;robert oanta: and I have expected so it did end up beating our internal Bay County Library;robert oanta: actually hung music.;robert oanta: the Port Saint Lucie, basically optimizing;Emil Ivov: what do we want to discuss;Mihaela: but she's going to drain it;Yana: so before so John can write is there a way to improve the email do you understand that you should expressing so we yes so we have a very often reports from like let's play the recording;Emil Ivov: do you want to say;Yana: horse about missing recorded and mostly from Brave but other people as well and we can discuss why;Yana: there's anything like more major there that's we can fix but what I wanted to discuss now is that they always give us the recording me and everytime I have to go back and ask them can I give us the URL of the meeting they most of the time;Yana: I was thinking is there a way to;Yana: we have that you're out right away when we have a recording you were out to find the recording;Oana: I came up with an idea ID;Oana: dogs and we have them you found watch now we would find a recording session ID and envelopes will find the meeting URL but this is not the only case we have;Oana: in the feedback like just missing recording or something without fathers;Yana: if we don't have any other information that's fine but you should have the recording link we should be able to like find it without asking back customer what was the actual;Yana: that's my only said that we go back and ask them if they'll;Emil Ivov: so I didn't want to get you the meeting out of the recording or no;Oana: technically yes but I tried to search getting the locks in the Jeep by the fish by the Jeep by the recording session ID and there I can't find them;Yana: so but why is it called silly because they rotate and we might have lost it already;Oana: Nikki MacCallum for today I think this happened recent;Yana: biscuit from yesterday;Yana: finding things like if we received five requests for days and then we'll be probably worried about that;Emil Ivov: an automated if that would have made the way;Oana: we should fix Nation;Yana: that's for sure yes but yeah can we all tomato;Emil Ivov: fix the issue anyway;Yana: find out what's going on there okay so can you try to look up those to request that they sent I sent you another one;Yana: play any differently in the one where it ended up on the different regions also an interesting one can you look up those and when you're looking for that;Yana: we make it easier for us to the search for those in the future;Oana: turn off.;Emil Ivov: okay what do we eat and we talked a little bit about what is causing this why do we have lost recording;Emil Ivov: anyone know;Oana: not sure yet I can explain how this happened and maybe you know more if you want me to;Oana: if you're on the deployment;Oana: you're going.;Oana: doxey Family theme song;Oana: I want release;Yana: a shart;Oana: and weeks back. According to be started by a Gymboree in this week so;Oana: in a bucket in the same region has permission to go in history;Oana: newscenter1;Oana: do we have a case where two different user the region will show as accepted for me it was in Rihanna;Yana: if we're looking at The Shard region now we're on the same shot shot.;Yana: but yes;Oana: because we send them the the link of the recording When recording;Oana: happy news;Oana: don't know why this was not the case why was like why we selected the US instead do this is how it should work;Emil Ivov: so you know that in this case we know that in this case the recording was in US.;Oana: Jimmy will be for me;Oana: what no I don't know yet;Yana: it could be a conference moves so we do see the same region I'm in the US and I see you Central one because we're on the show;Yana: drawing to someone from you guys and they ended up being a franchise charge;Yana: so;Yana: the only reason is we can move sharks in the middle of the meeting this can happen sometime so I'll discuss with that we can but then people cheer reload;Yana: is that something that there was another anomaly in the movie;Emil Ivov: well that doesn't mean that they'll say it necessary but okay we have to investigate this and then once we know;Emil Ivov: I was going on to be able to do to decide what;Yana: but independently there is a missing recording thing or am I mistaken the one that I sent you another one this morning;Emil Ivov: should we continue to discuss this with everyone else;Yana: yes I just wanted to say this is a different one that I sent this morning okay;saghul: what time;Emil Ivov: is that Rico and mindful that we kind of overstayed;Emil Ivov: topics that require everyone that don't require that would be beneficial;saghul: I think that we could discuss this like I don't think it's the kind of it's somewhat be so maybe we can;Emil Ivov: discuss it now but we can also let people go and then I'll just stay and wherever else you need;saghul: remember;saghul: going to things I have in my life yeah one is supposed to be sharing thing I told me about yesterday for the one is an election security;Emil Ivov: so this sounds like something we can start to discuss between the two of us;Emil Ivov: well everyone asks you for you to feel free to go and so you can share with me already whoever is interested;saghul: translate by the way;saghul: so the first one is the let me start from the election security;saghul: thought I had passed all of the holes but in the past before the whole shake-up happens Bogdan has worked on a full mitigation for this bike which would close it completely involves changing the way Wayne both.;saghul: a hole between the electron renderer process and the iPhone and that's why basically everybody ends up becoming remote code execution bug the way to avoid that is to use the information;saghul: they just need to be switched over to finish but because of all the shenanigans that have happened;saghul: no security shenanigansen happened now this has happened;saghul: the question is;Emil Ivov: what what are you asking for exactly do you need someone to help;saghul: is the kind of thing where we need to still support the old way or we would break is going to share it with everybody and then the Kaiser updated we can rotate the feature out that we could make a change;saghul: call Morgan;saghul: submerged tests and there I don't think there is space;Emil Ivov: where's the urgency that we have in Salt Lake;Emil Ivov: well let's see once we get someone;saghul: what's right in the form of security;Emil Ivov: Okay so;Emil Ivov: let me think a little bit about this the very worst once we get up for yourselves a little bit with with the whole LM stuff and contacts Center Stuff Etc and and then the authentication stuff try to put some time into this also lets you and I catch a buzz when I think about;saghul: DC stats and its relationship with with watch IDC so like looks like the most likely scenario anywhere that they would want to go with watch are teasing so if the spear like whatever it's called right now in Seattle;saghul: problem with either which is because both of them both and latex projects rely on monkey patching the peer connection they cannot be used at the same time;saghul: Youfit;saghul: unfortunate side effect here is that what your PC does not seem to support;saghul: they wired it out they don't have to login they kind of wire application looks so I guess we could we have two choices we can reach out to see if that is something on the pipeline and put make sense or what;saghul: at a certain way of operations what is he stands where it doesn't gather study the other slugs do we can have both;Andrei Gavrilescu: I wanted to say that this could technically be included in the logs part shipping box;Emil Ivov: I'd suggest;Andrei Gavrilescu: I don't think it's too much work to add the mode where logs are sent separately so I can probably fit this in the logs thing as well;Andrei Gavrilescu: that's reasonable but one thing I'd like to ask is if we do any Pilates she starts and whatnot that the guys have a problem with their meetings are they going to say are they going to send us watch Odyssey links for us to analyze work or whatever;saghul: yes;Emil Ivov: that's that's yes that's what I'm going to do;Emil Ivov: that's the right thing to do exactly for that reason we cannot tell people hey you know the lyrics to;Emil Ivov: but you we have Partners you can go use the partners and they go okay cuz of your insufficiency we're going to go and spend more money using someone else and the next thing we tell them;Emil Ivov: you anymore haha it's it's not that you don't see how this look if we can fix it they both work together I should be a preferred option so I suggest;Emil Ivov: we added support for which our DC breaks for RTC stats support and and we can't wait;Emil Ivov: please you know let's work together on on on on a on a solution;saghul: and breaking up with somebody else or just sorry I mean;Yana: I lost you;Andrei Gavrilescu: it broke up;Emil Ivov: we can ask them to;Emil Ivov: I was saying let's reach out to Taki and let's tell him;Emil Ivov: itzhaki your washer to see brakes are stats right now and that was probably already but we can just bring it up again and we need you we need you to come up with a fix;saghul: we know because we only allowed one one of them too;saghul: is that so;saghul: we say that way it sounds like what we want is to have a mechanism by which both work at the same time force that sounds like a very unlikely scenario we will have two libraries that they have both monkey patched save your connection. Get stats to hijack it and do something beforehand;Emil Ivov: everything's possible rain;saghul: yes;saghul: what I'm saying is is where is our interests are we interested in getting full art to see starts functionality or are we interested in being able to gather location logs but every other analytics date;Emil Ivov: we want the full warranty since that's what you think about it this way what will happen in the nature is customers of ours like attend anywhere dumb and say your logs and stand suck you want something more evolved;Emil Ivov: we have Partners you can use that we want to avoid if we don't want the usage of a partner to compromise our way to support so;Emil Ivov: nothing but any solution that stops already C-SPAN compromises our way to support them even if it's because we don't automatically;Emil Ivov: people who are all our own Analytics;Emil Ivov: way to do this is our PC stats is not compromised in any way by the usage of water which means I don't know we got some multiplexing Lair when you munch packs with your connection or something but from a perspective that's the right way to do it so unless this ends up being;Emil Ivov: expenses should go in that direction and in order to fix the prohibitive the expensive side of things we can push sake to help is this is his thing we can ask;saghul: okay;saghul: I think one thing we could do I know it we can talk about it because I think we have at least I know we have to;saghul: we could both have to guess there's a nonzero chance that things just worked one monkey purchase first and the other one monkey patches after they both get there;Andrei Gavrilescu: minutes should;Andrei Gavrilescu: yep it should work technically;saghul: maybe that's one way to go about it and it's easier than with us;saghul: what waiting for investigation is sports Ahi to let us use the service;saghul: Beast;saghul: remote control screen share stuff so;saghul: to the wireless to screenshot it and the way it works is computer that access a remote in that case because sharing your screen wirelessly use you first connect us a little remote that you would make that a peer-to-peer connection first has the remote with the TV and then there will be a connection established between the remote and meeting the actual meeting and has been joined by assistant called proxy your connection;saghul: is establishing one-way pure connection where;saghul: scream and then it uses this as it's local a bill for the way this was built was by reusing GT connection the muck the GT the jingle search all of those except that connection the conference everything except the actually most of everything is smoke though it's just fake objects don't do anything it's just so we could reuse the logic in General Session;saghul: historically every six months or so very peculiar ways and it cuz of how this is where proxy thing is something that needs to be used for from both ends so that is one time is in in Legion she needs baked into the deployment and then the other house isn't delicious she needs that spot needs to use this you can easily spot the problem;saghul: thanks and also very very subtle API changes to severe breakage;saghul: he's finally fixed but I'm not happy about it because we will inevitably run into this;saghul: broken now anymore pilot so I was playing on Creighton and Architects to the place to Prague and when they buy ABC gets updated it will work;saghul: and the way would be to use the iPhone API as a transport for negotiating this expert Care Connection I'm instead of all of that stuff and we would not have those tiny and subtle dependencies;saghul: resources from the deployment if Starbucks will fix them all in one generally speaking and;saghul: Camille dad's waiting to spend time with this so I thought of;saghul: cool feature so I thought that actually is there could be at your skates around and I thinking sternal streams D is the page that is using the iframe video source that once GT2 you just eat local video. It's impossible;saghul: implementing a connection transport across the ice cream boundary we can so we can send that stream to mainside meeting and then a meeting;saghul: local ice cream in general there is no reason why this to you you you're drawing something in a canvas and you wanted that to be your local feed;saghul: I Love Your Way;Yana: not at all;Emil Ivov: I thought your question was for everyone else;saghul: just want to make sure that everybody;Emil Ivov: where did I would look at this is;Emil Ivov: intuitively I like the idea of being able to plug in external get used to it it's it's it's something that's worth spending some time with you;Emil Ivov: probably as an experiment warrants less time than the fool spot rear axle so I would say;Emil Ivov: and maybe that's something that if you and we can discuss on the next Friday we can have I don't know if it's worth chordify how much time at any point are we spending in experiments but we can we can make sure that at any point it needs what we ate so is being the case that some of us are working on something that we don't really know how popular that will be but we want to try it;Emil Ivov: we're implementing;Emil Ivov: wait;Emil Ivov: Colonel video services in the air we push it on a blog post maybe we do a bit of a video about it and we see if it picks up if we get one or two people who and do something with it;Emil Ivov: then we can coordinate and it becomes part of the APA and that has reduced by that much the effort necessary;Emil Ivov: to actually switch Spa;Emil Ivov: and even if it doesn't get picked up by people it stood there so when we get a little bit more time to continue pushing in Sparta Sparta squat;Emil Ivov: okay but let's started as a jazz project I truly mean it right with the idea of this is what we're doing here's the blog post I was just yesterday;Emil Ivov: I don't know some window;Emil Ivov: I do not think about something something else that you could use is a generating an avatar;saghul: we could use Gabby's talking robot web-dl;Emil Ivov: yeah that might actually be an alternative way of achieving some of the things that we wanted to cheat with boss I like that but we can use;saghul: yes I I like I like I thought if it's due to do it in that order it was also with wasn't my mind I said we can build and then sort of migrate to it and I'm comes maybe the next time you brace;saghul: it will not be necessarily a walk in the park on this but side there is number like the things that we need to untangle so I think building upon the external API sign will be a simpler thing than to unplug it from the other end but the look I took sounds like;saghul: looking at the future;saghul: thank you;Yana: thanks or thank everyone have a great Friday" \ No newline at end of file