diff --git a/examples/04_bigquery_integration.ipynb b/examples/04_bigquery_integration.ipynb new file mode 100644 index 00000000..7544d393 --- /dev/null +++ b/examples/04_bigquery_integration.ipynb @@ -0,0 +1,294 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# BigQuery Integration\n", + "\n", + "This notebook demonstrates how to set up and use the LLMstudio tracking functionalities integrated to BigQuery. \n", + "\n", + "You'll learn:\n", + "1. Authenticate BigQuery\n", + "2. Start a local Tracker server\n", + "3. See the saved logs\n", + "\n", + "First things first:\n", + "* run `pip install llmstudio[tracker]`\n", + "* update your .env file with `GOOGLE_API_KEY` or `OPENAI_API_KEY` \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### BigQuery setup\n", + "\n", + "To use BigQuery, follow these steps:\n", + "\n", + "1. Select or create a Cloud Platform project.\n", + "2. [Create a BigQuery Dataset](https://cloud.google.com/bigquery/docs/datasets)\n", + "2. [Enable the BigQuery Storage API](https://console.cloud.google.com/apis/library/bigquery.googleapis.com).\n", + "3. [Setup Authentication:](https://googleapis.dev/python/google-api-core/latest/auth.html)\n", + " - If you’re running in a Google Virtual Machine Environment (Compute Engine, App Engine, Cloud Run, Cloud Functions), authentication should “just work”.\n", + " - If you’re developing locally, the easiest way to authenticate is using the Google Cloud SDK:\n", + " ```$ gcloud auth application-default login```\n", + " - If you’re running your application elsewhere, you should download a service account JSON keyfile and point to it using an environment variable: \n", + " ```$ export GOOGLE_APPLICATION_CREDENTIALS=\"/path/to/keyfile.json\"```\n", + "\n", + " \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## LLMstudio Tracker setup\n", + "\n", + "For LLMstudio to store your logs in BigQuery you need to set the 'LLMSTUDIO_TRACKING_URI' environment variable with the corresponding uri, which will be in this format: `bigquery:///`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "os.environ[\"LLMSTUDIO_TRACKING_URI\"] = \"bigquery:///\"" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from llmstudio.providers import LLM\n", + "from pprint import pprint" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running LLMstudio Tracking on http://0.0.0.0:8002 \n" + ] + } + ], + "source": [ + "from llmstudio.server import start_servers\n", + "start_servers(proxy=False, tracker=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from llmstudio_tracker.tracker import TrackingConfig\n", + "# default port is 50002. set the environment varible to specify which host and port; LLMSTUDIO_TRACKING_HOST, LLMSTUDIO_TRACKING_PORT\n", + "tracker_config = TrackingConfig(host=\"0.0.0.0\", port=\"50002\")\n", + "# You can set OPENAI_API_KEY and ANTHROPIC_API_KEY on .env file\n", + "openai = LLM(\"openai\", tracking_config = tracker_config)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Analyse logs" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "from llmstudio_tracker.tracker import Tracker\n", + "\n", + "tracker = Tracker(tracking_config=tracker_config)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'chat_input': \"Write a paragraph explaining why you're not a cat\",\n", + " 'chat_output': \"I’m not a cat because I lack the physical form and instincts that characterize feline creatures. Unlike a cat, I don’t have a furry coat, retractable claws, or the ability to pounce playfully on a sunbeam. I don’t experience the world through senses like smell, sight, or sound, nor do I possess the whimsical personality traits that make cats so captivating, such as their curiosity and independence. Instead, I am a collection of algorithms and data, designed to process information and generate responses, which allows me to assist you in ways that a cat simply can't—like answering questions, providing explanations, or engaging in conversation.\",\n", + " 'session_id': '20241024-110303-e8b361d9-d5f6-4b73-80f1-6d77a4be3793',\n", + " 'context': [{'role': 'user',\n", + " 'content': \"Write a paragraph explaining why you're not a cat\"}],\n", + " 'provider': 'openai',\n", + " 'model': 'gpt-4o-mini',\n", + " 'deployment': 'gpt-4o-mini-2024-07-18',\n", + " 'parameters': {},\n", + " 'metrics': {'input_tokens': 10,\n", + " 'output_tokens': 132,\n", + " 'total_tokens': 142,\n", + " 'cost_usd': 8.07e-05,\n", + " 'latency_s': 1.7590069770812988,\n", + " 'time_to_first_token_s': 0.450714111328125,\n", + " 'inter_token_latency_s': 0.010057984865628755,\n", + " 'tokens_per_second': 74.47383762932361},\n", + " 'log_id': 56,\n", + " 'created_at': '2024-10-24T11:03:26'}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "logs = tracker.get_logs()\n", + "logs.json()[-1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Add a session id to tracking logs\n", + "\n", + "* this is especially benefitial if running an app, chatbot agent, etc in production and you need to correlate user feedback, costs etc with user sessions, agent runs, etc" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# default port is 50002. set the environment varible to specify which host and port; LLMSTUDIO_TRACKING_HOST, LLMSTUDIO_TRACKING_PORT\n", + "# You can set OPENAI_API_KEY on .env file\n", + "openai = LLM(\"openai\", tracking_config = tracker_config, session_id=\"openai-session-1\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "Tracking AI agents' usage metrics and costs, alongside correlating them with user feedback, is crucial\n", + "\n", + " for optimizing performance and user satisfaction. Usage metrics provide insights into how often and in what ways AI agents\n", + "\n", + " are being utilized, helping to identify patterns, peak usage times, and potential bottlenecks that could\n", + "\n", + " affect service quality. Monitoring costs is equally important to ensure that resources are allocated efficiently, preventing financial waste\n", + "\n", + " while maximizing return on investment. By correlating these metrics with user feedback, developers and stakeholders can gain\n", + "\n", + " a holistic understanding of how the AI agent is performing in real-world settings. This integrated approach enables the\n", + "\n", + " identification of areas for improvement, the fine-tuning of algorithms, and the enhancement of user experience,\n", + "\n", + " ultimately leading to more effective, scalable, and user-friendly AI solutions. Additionally, it allows for the\n", + "\n", + " alignment of AI functionalities with user demands and business objectives, fostering continuous innovation and value creation.\n", + "\n", + "## Metrics:\n", + "{'cost_usd': 0.0027600000000000003,\n", + " 'input_tokens': 21,\n", + " 'inter_token_latency_s': 0.015782629505971844,\n", + " 'latency_s': 3.4153928756713867,\n", + " 'output_tokens': 177,\n", + " 'time_to_first_token_s': 0.6054329872131348,\n", + " 'tokens_per_second': 52.40978315410135,\n", + " 'total_tokens': 198}\n" + ] + } + ], + "source": [ + "response = openai.chat(\"Write a paragraph explaining why it's important to track AI agents usage metrics and costs and correlate with user feedback\", model=\"gpt-4o\", is_stream=True)\n", + "for i, chunk in enumerate(response):\n", + " if i%20==0:\n", + " print(\"\\n\")\n", + " if not chunk.metrics:\n", + " print(chunk.chat_output_stream, end=\"\", flush=True)\n", + " else:\n", + " print(\"\\n\\n## Metrics:\")\n", + " pprint(chunk.metrics)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'chat_input': \"Write a paragraph explaining why it's important to track AI agents usage metrics and costs and correlate with user feedback\",\n", + " 'chat_output': \"Tracking AI agents' usage metrics and costs, alongside correlating them with user feedback, is crucial for optimizing performance and user satisfaction. Usage metrics provide insights into how often and in what ways AI agents are being utilized, helping to identify patterns, peak usage times, and potential bottlenecks that could affect service quality. Monitoring costs is equally important to ensure that resources are allocated efficiently, preventing financial waste while maximizing return on investment. By correlating these metrics with user feedback, developers and stakeholders can gain a holistic understanding of how the AI agent is performing in real-world settings. This integrated approach enables the identification of areas for improvement, the fine-tuning of algorithms, and the enhancement of user experience, ultimately leading to more effective, scalable, and user-friendly AI solutions. Additionally, it allows for the alignment of AI functionalities with user demands and business objectives, fostering continuous innovation and value creation.\",\n", + " 'session_id': 'openai-session-1',\n", + " 'context': [{'role': 'user',\n", + " 'content': \"Write a paragraph explaining why it's important to track AI agents usage metrics and costs and correlate with user feedback\"}],\n", + " 'provider': 'openai',\n", + " 'model': 'gpt-4o',\n", + " 'deployment': 'gpt-4o-2024-08-06',\n", + " 'parameters': {},\n", + " 'metrics': {'input_tokens': 21,\n", + " 'output_tokens': 177,\n", + " 'total_tokens': 198,\n", + " 'cost_usd': 0.0027600000000000003,\n", + " 'latency_s': 3.4153928756713867,\n", + " 'time_to_first_token_s': 0.6054329872131348,\n", + " 'inter_token_latency_s': 0.015782629505971844,\n", + " 'tokens_per_second': 52.40978315410135},\n", + " 'log_id': 57,\n", + " 'created_at': '2024-10-24T11:04:21'}" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "logs = tracker.get_session_logs(session_id=\"openai-session-1\")\n", + "logs.json()[-1]" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/libs/tracker/README.md b/libs/tracker/README.md index 97b731f9..3c11f4ce 100644 --- a/libs/tracker/README.md +++ b/libs/tracker/README.md @@ -1,62 +1,100 @@ -# LLMstudio by [TensorOps](http://tensorops.ai "TensorOps") +# LLMstudio Tracker -Prompt Engineering at your fingertips - -![LLMstudio logo](https://imgur.com/Xqsj6V2.gif) +LLMstudio Tracker is the module of LLMstudio that allows monitoring and logging your LLM calls. +It supports seamless integration with the LLMstudio environment through configurable tracking servers, allowing for detailed insights into synchronous and asynchronous chat interactions. By leveraging LLMstudio Tracker, users can gain insights on model performance and streamline development workflows with actionable analytics. ## 🌟 Features -![LLMstudio UI](https://imgur.com/wrwiIUs.png) - -- **LLM Proxy Access**: Seamless access to all the latest LLMs by OpenAI, Anthropic, Google. -- **Custom and Local LLM Support**: Use custom or local open-source LLMs through Ollama. -- **Prompt Playground UI**: A user-friendly interface for engineering and fine-tuning your prompts. -- **Python SDK**: Easily integrate LLMstudio into your existing workflows. - **Monitoring and Logging**: Keep track of your usage and performance for all requests. -- **LangChain Integration**: LLMstudio integrates with your already existing LangChain projects. -- **Batch Calling**: Send multiple requests at once for improved efficiency. -- **Smart Routing and Fallback**: Ensure 24/7 availability by routing your requests to trusted LLMs. -- **Type Casting (soon)**: Convert data types as needed for your specific use case. +- **Logs Persistence with SQLAlquemy**: You can configure the tracker to use a database of your choice (SQLlite, Postgres, Bigquery, etc...) -## 🚀 Quickstart - -Don't forget to check out [https://docs.llmstudio.ai](docs) page. ## Installation -Install the latest version of **LLMstudio** using `pip`. We suggest that you create and activate a new environment using `conda` +Install the latest version of **LLMstudio** using `pip`. We suggest that you create and activate a new virtual environment. ```bash pip install 'llmstudio[tracker]' ``` -Create a `.env` file at the same path you'll run **LLMstudio** +## How to run + +To configure the tracker host, port, and database URI, create a `.env` file at the same path you'll run **LLMstudio** and set values for: +- LLMSTUDIO_TRACKING_HOST (default is 0.0.0.0) +- LLMSTUDIO_TRACKING_PORT (default is 50002) +- LLMSTUDIO_TRACKING_URI (the default is sqlite:///./llmstudio_mgmt.db) + +If you skip this step, LLMstudio will just use the default values. + ```bash -OPENAI_API_KEY="sk-api_key" +LLMSTUDIO_TRACKING_HOST=0.0.0.0 +LLMSTUDIO_TRACKING_PORT=8002 +LLMSTUDIO_TRACKIN_URI="your_db_uri" + ``` -Now you should be able to run **LLMstudio Tracker** using the following command. +### Launching from a terminal + +Now you should be able to run **LLMstudio Tracker** using the following command: ```bash llmstudio server --tracker ``` +### Launching directly in your code + +Alternatively, you can start the server in your code: +```python +from llmstudio.server import start_servers +start_servers(proxy=False, tracker=True) +``` + When the `--tracker` flag is set, you'll be able to access the [Swagger at http://0.0.0.0:50002/docs (default port)](http://0.0.0.0:50002/docs) +If you didn't provide the URI to your database, LLMstudio will create an SQLite database at the root of your project and write the logs there. + +## Usage + +Now, you can initialize an LLM to make calls and link it to your tracking configuration so that the tracker will log the calls. + +```python +from llmstudio_tracker.tracker import TrackingConfig + +tracker_config = TrackingConfig(host="0.0.0.0", port="50002") # needs to match what was set in your .env file + +# You can set OPENAI_API_KEY in your .env file +openai = LLM("openai", tracking_config = tracker_config) + +openai.chat("Hey!", model="gpt-4o") +``` + +### Analysing the logs + +```python +from llmstudio_tracker.tracker import Tracker + +tracker = Tracker(tracking_config=tracker_config) + +logs = tracker.get_logs() +logs.json() +``` + + + + ## 📖 Documentation -- [Visit our docs to learn how the SDK works](https://docs.LLMstudio.ai) (coming soon) -- Checkout our [notebook examples](https://github.com/TensorOpsAI/LLMstudio/tree/main/examples) to follow along with interactive tutorials +- [Visit our docs to learn how it works](https://docs.LLMstudio.ai) +- Checkout our [notebook examples](https://github.com/TensorOpsAI/LLMstudio/tree/main/examples) to follow along with interactive tutorials, especially: + - [Intro to LLMstudio Tracking](https://github.com/TensorOpsAI/LLMstudio/tree/main/examples/01_intro_to_llmstudio_with_tracking.ipynb) + - [BigQuery Integration](https://github.com/TensorOpsAI/LLMstudio/tree/main/examples/04_bigquery_integration.ipynb) ## 👨‍💻 Contributing - Head on to our [Contribution Guide](https://github.com/TensorOpsAI/LLMstudio/tree/main/CONTRIBUTING.md) to see how you can help LLMstudio. - Join our [Discord](https://discord.gg/GkAfPZR9wy) to talk with other LLMstudio enthusiasts. -## Training - -[![Banner](https://imgur.com/XTRFZ4m.png)](https://www.tensorops.ai/llm-studio-workshop) --- diff --git a/libs/tracker/llmstudio_tracker/config.py b/libs/tracker/llmstudio_tracker/config.py index 3cbb397f..a32614d1 100644 --- a/libs/tracker/llmstudio_tracker/config.py +++ b/libs/tracker/llmstudio_tracker/config.py @@ -32,3 +32,4 @@ def assign_port(default_port=None): TRACKING_HOST = os.environ["LLMSTUDIO_TRACKING_HOST"] TRACKING_PORT = os.environ["LLMSTUDIO_TRACKING_PORT"] TRACKING_URI = os.environ["LLMSTUDIO_TRACKING_URI"] +DB_TYPE = TRACKING_URI.split("://")[0] diff --git a/libs/tracker/llmstudio_tracker/database.py b/libs/tracker/llmstudio_tracker/database.py index ebedbd0f..53a73990 100644 --- a/libs/tracker/llmstudio_tracker/database.py +++ b/libs/tracker/llmstudio_tracker/database.py @@ -1,10 +1,10 @@ -from llmstudio_tracker.config import TRACKING_URI +from llmstudio_tracker.config import DB_TYPE, TRACKING_URI from sqlalchemy import create_engine from sqlalchemy.orm import declarative_base, sessionmaker def create_tracking_engine(uri: str): - if uri.split("://")[0] == "sqlite": + if DB_TYPE == "sqlite": return create_engine(uri, connect_args={"check_same_thread": False}) return create_engine(uri) diff --git a/libs/tracker/llmstudio_tracker/db_utils.py b/libs/tracker/llmstudio_tracker/db_utils.py new file mode 100644 index 00000000..8b3e5899 --- /dev/null +++ b/libs/tracker/llmstudio_tracker/db_utils.py @@ -0,0 +1,20 @@ +import json + +from sqlalchemy import Text +from sqlalchemy.types import TypeDecorator + + +class JSONEncodedDict(TypeDecorator): + """JSON-encoded dictionary for compatibility with BigQuery.""" + + impl = Text + + def process_bind_param(self, value, dialect): + if value is not None: + return json.dumps(value) + return None + + def process_result_value(self, value, dialect): + if value is not None: + return json.loads(value) + return None diff --git a/libs/tracker/llmstudio_tracker/logs/models.py b/libs/tracker/llmstudio_tracker/logs/models.py index 66403912..493c1669 100644 --- a/libs/tracker/llmstudio_tracker/logs/models.py +++ b/libs/tracker/llmstudio_tracker/logs/models.py @@ -1,21 +1,45 @@ +from datetime import datetime, timezone + +from llmstudio_tracker.config import DB_TYPE from llmstudio_tracker.database import Base +from llmstudio_tracker.db_utils import JSONEncodedDict from sqlalchemy import JSON, Column, DateTime, Integer, String -from sqlalchemy.sql import func class LogDefault(Base): __tablename__ = "logs_default" - log_id = Column(Integer, primary_key=True, index=True) - created_at = Column(DateTime(timezone=True), server_default=func.now()) - - session_id = Column(String) - - chat_input = Column(String) - chat_output = Column(String) - context = Column(JSON) - provider = Column(String) - model = Column(String) - deployment = Column(String) - parameters = Column(JSON) - metrics = Column(JSON) + if DB_TYPE == "bigquery": + log_id = Column( + Integer, + primary_key=True, + default=lambda: int( + datetime.now(timezone.utc).strftime("%Y%m%d%H%M%S%f")[:-1] + ), + ) + created_at = Column( + DateTime(timezone=True), default=lambda: datetime.now(timezone.utc) + ) + session_id = Column(String) + chat_input = Column(String) + chat_output = Column(String) + context = Column(JSONEncodedDict) + provider = Column(String) + model = Column(String) + deployment = Column(String) + parameters = Column(JSONEncodedDict) + metrics = Column(JSONEncodedDict) + else: + log_id = Column(Integer, primary_key=True, index=True) + created_at = Column( + DateTime(timezone=True), default=lambda: datetime.now(timezone.utc) + ) + session_id = Column(String) + chat_input = Column(String) + chat_output = Column(String) + context = Column(JSON) + provider = Column(String) + model = Column(String) + deployment = Column(String) + parameters = Column(JSON) + metrics = Column(JSON) diff --git a/libs/tracker/llmstudio_tracker/session/models.py b/libs/tracker/llmstudio_tracker/session/models.py index 2a4366bf..dfde6a10 100644 --- a/libs/tracker/llmstudio_tracker/session/models.py +++ b/libs/tracker/llmstudio_tracker/session/models.py @@ -1,15 +1,37 @@ +from datetime import datetime, timezone + +from llmstudio_tracker.config import DB_TYPE from llmstudio_tracker.database import Base +from llmstudio_tracker.db_utils import JSONEncodedDict from sqlalchemy import JSON, Column, DateTime, Integer, String -from sqlalchemy.sql import func class SessionDefault(Base): __tablename__ = "sessions" - message_id = Column(Integer, primary_key=True, index=True) - session_id = Column(String, index=True) - chat_history = Column(JSON) - extras = Column(JSON) + + if DB_TYPE == "bigquery": + message_id = Column( + Integer, + primary_key=True, + default=lambda: int( + datetime.now(timezone.utc).strftime("%Y%m%d%H%M%S%f")[:-1] + ), + ) + session_id = Column(String) + chat_history = Column(JSONEncodedDict) + extras = Column(JSONEncodedDict) + + else: + message_id = Column(Integer, primary_key=True, index=True) + session_id = Column(String, index=True) + chat_history = Column(JSON) + extras = Column(JSON) + updated_at = Column( - DateTime(timezone=True), onupdate=func.now(), server_default=func.now() + DateTime(timezone=True), + onupdate=lambda: datetime.now(timezone.utc), + default=lambda: datetime.now(timezone.utc), + ) + created_at = Column( + DateTime(timezone=True), default=lambda: datetime.now(timezone.utc) ) - created_at = Column(DateTime(timezone=True), server_default=func.now()) diff --git a/libs/tracker/poetry.lock b/libs/tracker/poetry.lock index e7231cfd..cad243d7 100644 --- a/libs/tracker/poetry.lock +++ b/libs/tracker/poetry.lock @@ -33,6 +33,17 @@ doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21.0b1)"] trio = ["trio (>=0.26.1)"] +[[package]] +name = "cachetools" +version = "5.5.0" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292"}, + {file = "cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a"}, +] + [[package]] name = "certifi" version = "2024.8.30" @@ -214,8 +225,210 @@ starlette = ">=0.40.0,<0.42.0" typing-extensions = ">=4.8.0" [package.extras] -all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] -standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=2.11.2)", "python-multipart (>=0.0.7)", "uvicorn[standard] (>=0.12.0)"] +all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] + +[[package]] +name = "google-api-core" +version = "2.23.0" +description = "Google API client core library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google_api_core-2.23.0-py3-none-any.whl", hash = "sha256:c20100d4c4c41070cf365f1d8ddf5365915291b5eb11b83829fbd1c999b5122f"}, + {file = "google_api_core-2.23.0.tar.gz", hash = "sha256:2ceb087315e6af43f256704b871d99326b1f12a9d6ce99beaedec99ba26a0ace"}, +] + +[package.dependencies] +google-auth = ">=2.14.1,<3.0.dev0" +googleapis-common-protos = ">=1.56.2,<2.0.dev0" +grpcio = [ + {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, + {version = ">=1.33.2,<2.0dev", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, +] +grpcio-status = [ + {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, + {version = ">=1.33.2,<2.0.dev0", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, +] +proto-plus = ">=1.22.3,<2.0.0dev" +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" +requests = ">=2.18.0,<3.0.0.dev0" + +[package.extras] +async-rest = ["google-auth[aiohttp] (>=2.35.0,<3.0.dev0)"] +grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "grpcio-status (>=1.33.2,<2.0.dev0)", "grpcio-status (>=1.49.1,<2.0.dev0)"] +grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] +grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] + +[[package]] +name = "google-auth" +version = "2.36.0" +description = "Google Authentication Library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google_auth-2.36.0-py2.py3-none-any.whl", hash = "sha256:51a15d47028b66fd36e5c64a82d2d57480075bccc7da37cde257fc94177a61fb"}, + {file = "google_auth-2.36.0.tar.gz", hash = "sha256:545e9618f2df0bcbb7dcbc45a546485b1212624716975a1ea5ae8149ce769ab1"}, +] + +[package.dependencies] +cachetools = ">=2.0.0,<6.0" +pyasn1-modules = ">=0.2.1" +rsa = ">=3.1.4,<5" + +[package.extras] +aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"] +enterprise-cert = ["cryptography", "pyopenssl"] +pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] +reauth = ["pyu2f (>=0.1.5)"] +requests = ["requests (>=2.20.0,<3.0.0.dev0)"] + +[[package]] +name = "google-cloud-bigquery" +version = "3.27.0" +description = "Google BigQuery API client library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google_cloud_bigquery-3.27.0-py2.py3-none-any.whl", hash = "sha256:b53b0431e5ba362976a4cd8acce72194b4116cdf8115030c7b339b884603fcc3"}, + {file = "google_cloud_bigquery-3.27.0.tar.gz", hash = "sha256:379c524054d7b090fa56d0c22662cc6e6458a6229b6754c0e7177e3a73421d2c"}, +] + +[package.dependencies] +google-api-core = {version = ">=2.11.1,<3.0.0dev", extras = ["grpc"]} +google-auth = ">=2.14.1,<3.0.0dev" +google-cloud-core = ">=2.4.1,<3.0.0dev" +google-resumable-media = ">=2.0.0,<3.0dev" +packaging = ">=20.0.0" +python-dateutil = ">=2.7.3,<3.0dev" +requests = ">=2.21.0,<3.0.0dev" + +[package.extras] +all = ["Shapely (>=1.8.4,<3.0.0dev)", "bigquery-magics (>=0.1.0)", "db-dtypes (>=0.3.0,<2.0.0dev)", "geopandas (>=0.9.0,<1.0dev)", "google-cloud-bigquery-storage (>=2.6.0,<3.0.0dev)", "grpcio (>=1.47.0,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "importlib-metadata (>=1.0.0)", "ipykernel (>=6.0.0)", "ipywidgets (>=7.7.0)", "opentelemetry-api (>=1.1.0)", "opentelemetry-instrumentation (>=0.20b0)", "opentelemetry-sdk (>=1.1.0)", "pandas (>=1.1.0)", "proto-plus (>=1.22.3,<2.0.0dev)", "protobuf (>=3.20.2,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0dev)", "pyarrow (>=3.0.0)", "tqdm (>=4.7.4,<5.0.0dev)"] +bigquery-v2 = ["proto-plus (>=1.22.3,<2.0.0dev)", "protobuf (>=3.20.2,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0dev)"] +bqstorage = ["google-cloud-bigquery-storage (>=2.6.0,<3.0.0dev)", "grpcio (>=1.47.0,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "pyarrow (>=3.0.0)"] +geopandas = ["Shapely (>=1.8.4,<3.0.0dev)", "geopandas (>=0.9.0,<1.0dev)"] +ipython = ["bigquery-magics (>=0.1.0)"] +ipywidgets = ["ipykernel (>=6.0.0)", "ipywidgets (>=7.7.0)"] +opentelemetry = ["opentelemetry-api (>=1.1.0)", "opentelemetry-instrumentation (>=0.20b0)", "opentelemetry-sdk (>=1.1.0)"] +pandas = ["db-dtypes (>=0.3.0,<2.0.0dev)", "importlib-metadata (>=1.0.0)", "pandas (>=1.1.0)", "pyarrow (>=3.0.0)"] +tqdm = ["tqdm (>=4.7.4,<5.0.0dev)"] + +[[package]] +name = "google-cloud-bigquery-storage" +version = "2.27.0" +description = "Google Cloud Bigquery Storage API client library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google_cloud_bigquery_storage-2.27.0-py2.py3-none-any.whl", hash = "sha256:3bfa8f74a61ceaffd3bfe90be5bbef440ad81c1c19ac9075188cccab34bffc2b"}, + {file = "google_cloud_bigquery_storage-2.27.0.tar.gz", hash = "sha256:522faba9a68bea7e9857071c33fafce5ee520b7b175da00489017242ade8ec27"}, +] + +[package.dependencies] +google-api-core = {version = ">=1.34.0,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} +google-auth = ">=2.14.1,<3.0.0dev" +proto-plus = [ + {version = ">=1.22.2,<2.0.0dev", markers = "python_version >= \"3.11\""}, + {version = ">=1.22.0,<2.0.0dev", markers = "python_version < \"3.11\""}, +] +protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0dev" + +[package.extras] +fastavro = ["fastavro (>=0.21.2)"] +pandas = ["importlib-metadata (>=1.0.0)", "pandas (>=0.21.1)"] +pyarrow = ["pyarrow (>=0.15.0)"] + +[[package]] +name = "google-cloud-core" +version = "2.4.1" +description = "Google Cloud API client core library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-cloud-core-2.4.1.tar.gz", hash = "sha256:9b7749272a812bde58fff28868d0c5e2f585b82f37e09a1f6ed2d4d10f134073"}, + {file = "google_cloud_core-2.4.1-py2.py3-none-any.whl", hash = "sha256:a9e6a4422b9ac5c29f79a0ede9485473338e2ce78d91f2370c01e730eab22e61"}, +] + +[package.dependencies] +google-api-core = ">=1.31.6,<2.0.dev0 || >2.3.0,<3.0.0dev" +google-auth = ">=1.25.0,<3.0dev" + +[package.extras] +grpc = ["grpcio (>=1.38.0,<2.0dev)", "grpcio-status (>=1.38.0,<2.0.dev0)"] + +[[package]] +name = "google-crc32c" +version = "1.6.0" +description = "A python wrapper of the C library 'Google CRC32C'" +optional = false +python-versions = ">=3.9" +files = [ + {file = "google_crc32c-1.6.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:5bcc90b34df28a4b38653c36bb5ada35671ad105c99cfe915fb5bed7ad6924aa"}, + {file = "google_crc32c-1.6.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:d9e9913f7bd69e093b81da4535ce27af842e7bf371cde42d1ae9e9bd382dc0e9"}, + {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a184243544811e4a50d345838a883733461e67578959ac59964e43cca2c791e7"}, + {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:236c87a46cdf06384f614e9092b82c05f81bd34b80248021f729396a78e55d7e"}, + {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebab974b1687509e5c973b5c4b8b146683e101e102e17a86bd196ecaa4d099fc"}, + {file = "google_crc32c-1.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:50cf2a96da226dcbff8671233ecf37bf6e95de98b2a2ebadbfdf455e6d05df42"}, + {file = "google_crc32c-1.6.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:f7a1fc29803712f80879b0806cb83ab24ce62fc8daf0569f2204a0cfd7f68ed4"}, + {file = "google_crc32c-1.6.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:40b05ab32a5067525670880eb5d169529089a26fe35dce8891127aeddc1950e8"}, + {file = "google_crc32c-1.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e4b426c3702f3cd23b933436487eb34e01e00327fac20c9aebb68ccf34117d"}, + {file = "google_crc32c-1.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51c4f54dd8c6dfeb58d1df5e4f7f97df8abf17a36626a217f169893d1d7f3e9f"}, + {file = "google_crc32c-1.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:bb8b3c75bd157010459b15222c3fd30577042a7060e29d42dabce449c087f2b3"}, + {file = "google_crc32c-1.6.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:ed767bf4ba90104c1216b68111613f0d5926fb3780660ea1198fc469af410e9d"}, + {file = "google_crc32c-1.6.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:62f6d4a29fea082ac4a3c9be5e415218255cf11684ac6ef5488eea0c9132689b"}, + {file = "google_crc32c-1.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c87d98c7c4a69066fd31701c4e10d178a648c2cac3452e62c6b24dc51f9fcc00"}, + {file = "google_crc32c-1.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd5e7d2445d1a958c266bfa5d04c39932dc54093fa391736dbfdb0f1929c1fb3"}, + {file = "google_crc32c-1.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:7aec8e88a3583515f9e0957fe4f5f6d8d4997e36d0f61624e70469771584c760"}, + {file = "google_crc32c-1.6.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:e2806553238cd076f0a55bddab37a532b53580e699ed8e5606d0de1f856b5205"}, + {file = "google_crc32c-1.6.0-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:bb0966e1c50d0ef5bc743312cc730b533491d60585a9a08f897274e57c3f70e0"}, + {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:386122eeaaa76951a8196310432c5b0ef3b53590ef4c317ec7588ec554fec5d2"}, + {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2952396dc604544ea7476b33fe87faedc24d666fb0c2d5ac971a2b9576ab871"}, + {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35834855408429cecf495cac67ccbab802de269e948e27478b1e47dfb6465e57"}, + {file = "google_crc32c-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:d8797406499f28b5ef791f339594b0b5fdedf54e203b5066675c406ba69d705c"}, + {file = "google_crc32c-1.6.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48abd62ca76a2cbe034542ed1b6aee851b6f28aaca4e6551b5599b6f3ef175cc"}, + {file = "google_crc32c-1.6.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18e311c64008f1f1379158158bb3f0c8d72635b9eb4f9545f8cf990c5668e59d"}, + {file = "google_crc32c-1.6.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05e2d8c9a2f853ff116db9706b4a27350587f341eda835f46db3c0a8c8ce2f24"}, + {file = "google_crc32c-1.6.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ca8145b060679ec9176e6de4f89b07363d6805bd4760631ef254905503598d"}, + {file = "google_crc32c-1.6.0.tar.gz", hash = "sha256:6eceb6ad197656a1ff49ebfbbfa870678c75be4344feb35ac1edf694309413dc"}, +] + +[package.extras] +testing = ["pytest"] + +[[package]] +name = "google-resumable-media" +version = "2.7.2" +description = "Utilities for Google Media Downloads and Resumable Uploads" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google_resumable_media-2.7.2-py2.py3-none-any.whl", hash = "sha256:3ce7551e9fe6d99e9a126101d2536612bb73486721951e9562fee0f90c6ababa"}, + {file = "google_resumable_media-2.7.2.tar.gz", hash = "sha256:5280aed4629f2b60b847b0d42f9857fd4935c11af266744df33d8074cae92fe0"}, +] + +[package.dependencies] +google-crc32c = ">=1.0,<2.0dev" + +[package.extras] +aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)", "google-auth (>=1.22.0,<2.0dev)"] +requests = ["requests (>=2.18.0,<3.0.0dev)"] + +[[package]] +name = "googleapis-common-protos" +version = "1.66.0" +description = "Common protobufs used in Google APIs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "googleapis_common_protos-1.66.0-py2.py3-none-any.whl", hash = "sha256:d7abcd75fabb2e0ec9f74466401f6c119a0b498e27370e9be4c94cb7e382b8ed"}, + {file = "googleapis_common_protos-1.66.0.tar.gz", hash = "sha256:c3e7b33d15fdca5374cc0a7346dd92ffa847425cc4ea941d970f13680052ec8c"}, +] + +[package.dependencies] +protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" + +[package.extras] +grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] [[package]] name = "greenlet" @@ -303,6 +516,89 @@ files = [ docs = ["Sphinx", "furo"] test = ["objgraph", "psutil"] +[[package]] +name = "grpcio" +version = "1.68.0" +description = "HTTP/2-based RPC framework" +optional = false +python-versions = ">=3.8" +files = [ + {file = "grpcio-1.68.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:619b5d0f29f4f5351440e9343224c3e19912c21aeda44e0c49d0d147a8d01544"}, + {file = "grpcio-1.68.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:a59f5822f9459bed098ffbceb2713abbf7c6fd13f2b9243461da5c338d0cd6c3"}, + {file = "grpcio-1.68.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:c03d89df516128febc5a7e760d675b478ba25802447624edf7aa13b1e7b11e2a"}, + {file = "grpcio-1.68.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44bcbebb24363d587472089b89e2ea0ab2e2b4df0e4856ba4c0b087c82412121"}, + {file = "grpcio-1.68.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79f81b7fbfb136247b70465bd836fa1733043fdee539cd6031cb499e9608a110"}, + {file = "grpcio-1.68.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:88fb2925789cfe6daa20900260ef0a1d0a61283dfb2d2fffe6194396a354c618"}, + {file = "grpcio-1.68.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:99f06232b5c9138593ae6f2e355054318717d32a9c09cdc5a2885540835067a1"}, + {file = "grpcio-1.68.0-cp310-cp310-win32.whl", hash = "sha256:a6213d2f7a22c3c30a479fb5e249b6b7e648e17f364598ff64d08a5136fe488b"}, + {file = "grpcio-1.68.0-cp310-cp310-win_amd64.whl", hash = "sha256:15327ab81131ef9b94cb9f45b5bd98803a179c7c61205c8c0ac9aff9d6c4e82a"}, + {file = "grpcio-1.68.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:3b2b559beb2d433129441783e5f42e3be40a9e1a89ec906efabf26591c5cd415"}, + {file = "grpcio-1.68.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e46541de8425a4d6829ac6c5d9b16c03c292105fe9ebf78cb1c31e8d242f9155"}, + {file = "grpcio-1.68.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:c1245651f3c9ea92a2db4f95d37b7597db6b246d5892bca6ee8c0e90d76fb73c"}, + {file = "grpcio-1.68.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f1931c7aa85be0fa6cea6af388e576f3bf6baee9e5d481c586980c774debcb4"}, + {file = "grpcio-1.68.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b0ff09c81e3aded7a183bc6473639b46b6caa9c1901d6f5e2cba24b95e59e30"}, + {file = "grpcio-1.68.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8c73f9fbbaee1a132487e31585aa83987ddf626426d703ebcb9a528cf231c9b1"}, + {file = "grpcio-1.68.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6b2f98165ea2790ea159393a2246b56f580d24d7da0d0342c18a085299c40a75"}, + {file = "grpcio-1.68.0-cp311-cp311-win32.whl", hash = "sha256:e1e7ed311afb351ff0d0e583a66fcb39675be112d61e7cfd6c8269884a98afbc"}, + {file = "grpcio-1.68.0-cp311-cp311-win_amd64.whl", hash = "sha256:e0d2f68eaa0a755edd9a47d40e50dba6df2bceda66960dee1218da81a2834d27"}, + {file = "grpcio-1.68.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:8af6137cc4ae8e421690d276e7627cfc726d4293f6607acf9ea7260bd8fc3d7d"}, + {file = "grpcio-1.68.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4028b8e9a3bff6f377698587d642e24bd221810c06579a18420a17688e421af7"}, + {file = "grpcio-1.68.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:f60fa2adf281fd73ae3a50677572521edca34ba373a45b457b5ebe87c2d01e1d"}, + {file = "grpcio-1.68.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e18589e747c1e70b60fab6767ff99b2d0c359ea1db8a2cb524477f93cdbedf5b"}, + {file = "grpcio-1.68.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0d30f3fee9372796f54d3100b31ee70972eaadcc87314be369360248a3dcffe"}, + {file = "grpcio-1.68.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7e0a3e72c0e9a1acab77bef14a73a416630b7fd2cbd893c0a873edc47c42c8cd"}, + {file = "grpcio-1.68.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a831dcc343440969aaa812004685ed322cdb526cd197112d0db303b0da1e8659"}, + {file = "grpcio-1.68.0-cp312-cp312-win32.whl", hash = "sha256:5a180328e92b9a0050958ced34dddcb86fec5a8b332f5a229e353dafc16cd332"}, + {file = "grpcio-1.68.0-cp312-cp312-win_amd64.whl", hash = "sha256:2bddd04a790b69f7a7385f6a112f46ea0b34c4746f361ebafe9ca0be567c78e9"}, + {file = "grpcio-1.68.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:fc05759ffbd7875e0ff2bd877be1438dfe97c9312bbc558c8284a9afa1d0f40e"}, + {file = "grpcio-1.68.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:15fa1fe25d365a13bc6d52fcac0e3ee1f9baebdde2c9b3b2425f8a4979fccea1"}, + {file = "grpcio-1.68.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:32a9cb4686eb2e89d97022ecb9e1606d132f85c444354c17a7dbde4a455e4a3b"}, + {file = "grpcio-1.68.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dba037ff8d284c8e7ea9a510c8ae0f5b016004f13c3648f72411c464b67ff2fb"}, + {file = "grpcio-1.68.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0efbbd849867e0e569af09e165363ade75cf84f5229b2698d53cf22c7a4f9e21"}, + {file = "grpcio-1.68.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:4e300e6978df0b65cc2d100c54e097c10dfc7018b9bd890bbbf08022d47f766d"}, + {file = "grpcio-1.68.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:6f9c7ad1a23e1047f827385f4713b5b8c6c7d325705be1dd3e31fb00dcb2f665"}, + {file = "grpcio-1.68.0-cp313-cp313-win32.whl", hash = "sha256:3ac7f10850fd0487fcce169c3c55509101c3bde2a3b454869639df2176b60a03"}, + {file = "grpcio-1.68.0-cp313-cp313-win_amd64.whl", hash = "sha256:afbf45a62ba85a720491bfe9b2642f8761ff348006f5ef67e4622621f116b04a"}, + {file = "grpcio-1.68.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:f8f695d9576ce836eab27ba7401c60acaf9ef6cf2f70dfe5462055ba3df02cc3"}, + {file = "grpcio-1.68.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9fe1b141cda52f2ca73e17d2d3c6a9f3f3a0c255c216b50ce616e9dca7e3441d"}, + {file = "grpcio-1.68.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:4df81d78fd1646bf94ced4fb4cd0a7fe2e91608089c522ef17bc7db26e64effd"}, + {file = "grpcio-1.68.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:46a2d74d4dd8993151c6cd585594c082abe74112c8e4175ddda4106f2ceb022f"}, + {file = "grpcio-1.68.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a17278d977746472698460c63abf333e1d806bd41f2224f90dbe9460101c9796"}, + {file = "grpcio-1.68.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:15377bce516b1c861c35e18eaa1c280692bf563264836cece693c0f169b48829"}, + {file = "grpcio-1.68.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cc5f0a4f5904b8c25729a0498886b797feb817d1fd3812554ffa39551112c161"}, + {file = "grpcio-1.68.0-cp38-cp38-win32.whl", hash = "sha256:def1a60a111d24376e4b753db39705adbe9483ef4ca4761f825639d884d5da78"}, + {file = "grpcio-1.68.0-cp38-cp38-win_amd64.whl", hash = "sha256:55d3b52fd41ec5772a953612db4e70ae741a6d6ed640c4c89a64f017a1ac02b5"}, + {file = "grpcio-1.68.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:0d230852ba97654453d290e98d6aa61cb48fa5fafb474fb4c4298d8721809354"}, + {file = "grpcio-1.68.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:50992f214264e207e07222703c17d9cfdcc2c46ed5a1ea86843d440148ebbe10"}, + {file = "grpcio-1.68.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:14331e5c27ed3545360464a139ed279aa09db088f6e9502e95ad4bfa852bb116"}, + {file = "grpcio-1.68.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f84890b205692ea813653ece4ac9afa2139eae136e419231b0eec7c39fdbe4c2"}, + {file = "grpcio-1.68.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0cf343c6f4f6aa44863e13ec9ddfe299e0be68f87d68e777328bff785897b05"}, + {file = "grpcio-1.68.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:fd2c2d47969daa0e27eadaf15c13b5e92605c5e5953d23c06d0b5239a2f176d3"}, + {file = "grpcio-1.68.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:18668e36e7f4045820f069997834e94e8275910b1f03e078a6020bd464cb2363"}, + {file = "grpcio-1.68.0-cp39-cp39-win32.whl", hash = "sha256:2af76ab7c427aaa26aa9187c3e3c42f38d3771f91a20f99657d992afada2294a"}, + {file = "grpcio-1.68.0-cp39-cp39-win_amd64.whl", hash = "sha256:e694b5928b7b33ca2d3b4d5f9bf8b5888906f181daff6b406f4938f3a997a490"}, + {file = "grpcio-1.68.0.tar.gz", hash = "sha256:7e7483d39b4a4fddb9906671e9ea21aaad4f031cdfc349fec76bdfa1e404543a"}, +] + +[package.extras] +protobuf = ["grpcio-tools (>=1.68.0)"] + +[[package]] +name = "grpcio-status" +version = "1.68.0" +description = "Status proto mapping for gRPC" +optional = false +python-versions = ">=3.8" +files = [ + {file = "grpcio_status-1.68.0-py3-none-any.whl", hash = "sha256:0a71b15d989f02df803b4ba85c5bf1f43aeaa58ac021e5f9974b8cadc41f784d"}, + {file = "grpcio_status-1.68.0.tar.gz", hash = "sha256:8369823de22ab6a2cddb3804669c149ae7a71819e127c2dca7c2322028d52bea"}, +] + +[package.dependencies] +googleapis-common-protos = ">=1.5.5" +grpcio = ">=1.68.0" +protobuf = ">=5.26.1,<6.0dev" + [[package]] name = "h11" version = "0.14.0" @@ -328,6 +624,79 @@ files = [ [package.extras] all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] +[[package]] +name = "packaging" +version = "24.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, + {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, +] + +[[package]] +name = "proto-plus" +version = "1.25.0" +description = "Beautiful, Pythonic protocol buffers." +optional = false +python-versions = ">=3.7" +files = [ + {file = "proto_plus-1.25.0-py3-none-any.whl", hash = "sha256:c91fc4a65074ade8e458e95ef8bac34d4008daa7cce4a12d6707066fca648961"}, + {file = "proto_plus-1.25.0.tar.gz", hash = "sha256:fbb17f57f7bd05a68b7707e745e26528b0b3c34e378db91eef93912c54982d91"}, +] + +[package.dependencies] +protobuf = ">=3.19.0,<6.0.0dev" + +[package.extras] +testing = ["google-api-core (>=1.31.5)"] + +[[package]] +name = "protobuf" +version = "5.28.3" +description = "" +optional = false +python-versions = ">=3.8" +files = [ + {file = "protobuf-5.28.3-cp310-abi3-win32.whl", hash = "sha256:0c4eec6f987338617072592b97943fdbe30d019c56126493111cf24344c1cc24"}, + {file = "protobuf-5.28.3-cp310-abi3-win_amd64.whl", hash = "sha256:91fba8f445723fcf400fdbe9ca796b19d3b1242cd873907979b9ed71e4afe868"}, + {file = "protobuf-5.28.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a3f6857551e53ce35e60b403b8a27b0295f7d6eb63d10484f12bc6879c715687"}, + {file = "protobuf-5.28.3-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:3fa2de6b8b29d12c61911505d893afe7320ce7ccba4df913e2971461fa36d584"}, + {file = "protobuf-5.28.3-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:712319fbdddb46f21abb66cd33cb9e491a5763b2febd8f228251add221981135"}, + {file = "protobuf-5.28.3-cp38-cp38-win32.whl", hash = "sha256:3e6101d095dfd119513cde7259aa703d16c6bbdfae2554dfe5cfdbe94e32d548"}, + {file = "protobuf-5.28.3-cp38-cp38-win_amd64.whl", hash = "sha256:27b246b3723692bf1068d5734ddaf2fccc2cdd6e0c9b47fe099244d80200593b"}, + {file = "protobuf-5.28.3-cp39-cp39-win32.whl", hash = "sha256:135658402f71bbd49500322c0f736145731b16fc79dc8f367ab544a17eab4535"}, + {file = "protobuf-5.28.3-cp39-cp39-win_amd64.whl", hash = "sha256:70585a70fc2dd4818c51287ceef5bdba6387f88a578c86d47bb34669b5552c36"}, + {file = "protobuf-5.28.3-py3-none-any.whl", hash = "sha256:cee1757663fa32a1ee673434fcf3bf24dd54763c79690201208bafec62f19eed"}, + {file = "protobuf-5.28.3.tar.gz", hash = "sha256:64badbc49180a5e401f373f9ce7ab1d18b63f7dd4a9cdc43c92b9f0b481cef7b"}, +] + +[[package]] +name = "pyasn1" +version = "0.6.1" +description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629"}, + {file = "pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"}, +] + +[[package]] +name = "pyasn1-modules" +version = "0.4.1" +description = "A collection of ASN.1-based protocols modules" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyasn1_modules-0.4.1-py3-none-any.whl", hash = "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd"}, + {file = "pyasn1_modules-0.4.1.tar.gz", hash = "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c"}, +] + +[package.dependencies] +pyasn1 = ">=0.4.6,<0.7.0" + [[package]] name = "pydantic" version = "2.10.0" @@ -460,6 +829,20 @@ files = [ [package.dependencies] typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + [[package]] name = "requests" version = "2.32.3" @@ -481,6 +864,31 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "rsa" +version = "4.9" +description = "Pure-Python RSA implementation" +optional = false +python-versions = ">=3.6,<4" +files = [ + {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, + {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, +] + +[package.dependencies] +pyasn1 = ">=0.1.3" + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + [[package]] name = "sniffio" version = "1.3.1" @@ -587,6 +995,31 @@ postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] pymysql = ["pymysql"] sqlcipher = ["sqlcipher3_binary"] +[[package]] +name = "sqlalchemy-bigquery" +version = "1.12.0" +description = "SQLAlchemy dialect for BigQuery" +optional = false +python-versions = "<3.13,>=3.8" +files = [ + {file = "sqlalchemy_bigquery-1.12.0-py2.py3-none-any.whl", hash = "sha256:5b2b77bdaefe9c0663db213d9475a5abbae88fa46108c352d19fa6fc51a47a1a"}, + {file = "sqlalchemy_bigquery-1.12.0.tar.gz", hash = "sha256:12783ad83ffad34e8e6e14046cb14bb2f1a3e7fb52676f5a24e940ff5cdeb864"}, +] + +[package.dependencies] +google-api-core = ">=1.31.5,<2.0.dev0 || >2.3.0,<3.0.0dev" +google-auth = ">=1.25.0,<3.0.0dev" +google-cloud-bigquery = ">=3.3.6,<4.0.0dev" +packaging = "*" +sqlalchemy = ">=1.4.16,<3.0.0dev" + +[package.extras] +alembic = ["alembic"] +all = ["GeoAlchemy2", "alembic", "google-cloud-bigquery-storage (>=2.0.0,<3.0.0dev)", "grpcio (>=1.47.0,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "packaging", "pyarrow (>=3.0.0)", "pytz", "shapely"] +bqstorage = ["google-cloud-bigquery-storage (>=2.0.0,<3.0.0dev)", "grpcio (>=1.47.0,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "pyarrow (>=3.0.0)"] +geography = ["GeoAlchemy2", "shapely"] +tests = ["packaging", "pytz"] + [[package]] name = "starlette" version = "0.41.3" @@ -665,5 +1098,5 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", [metadata] lock-version = "2.0" -python-versions = "^3.9" -content-hash = "25c452c9b1978950fcce4f3d87b666ebd5b5f36c9c2acb5c1e18f2cbe211518f" +python-versions = ">=3.9,<3.13" +content-hash = "755ec9f0e28533633b47e8fe9437a87d71b4b5993b77ad06462fd1341e0e22ea" diff --git a/libs/tracker/pyproject.toml b/libs/tracker/pyproject.toml index aba4fceb..949228bf 100644 --- a/libs/tracker/pyproject.toml +++ b/libs/tracker/pyproject.toml @@ -1,18 +1,20 @@ [tool.poetry] name = "llmstudio-tracker" -version = "1.0.2" -description = "" +version = "1.0.3" +description = "LLMstudio Tracker is the module of LLMstudio that allows monitoring and logging your LLM calls. It supports seamless integration with the LLMstudio environment through configurable tracking servers, allowing for detailed insights into synchronous and asynchronous chat interactions. By leveraging LLMstudio Tracker, users can gain insights on model performance and streamline development workflows with actionable analytics." authors = ["Diogo Goncalves "] readme = "README.md" [tool.poetry.dependencies] -python = "^3.9" +python = ">=3.9,<3.13" pydantic = "^2.5" sqlalchemy = "^2" toml = "^0.10" requests = "^2.31" fastapi = "^0.115.5" uvicorn = "^0.27" +sqlalchemy-bigquery = "^1.12.0" +google-cloud-bigquery-storage = "^2.27.0" [build-system] requires = ["poetry-core"]