From dd237906c4211584842b9bb3d00aae8d4bff60e2 Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Tue, 22 Aug 2023 22:32:16 -0700 Subject: [PATCH 01/15] .. --- Makefile | 2 +- parea/api_client.py | 2 +- parea/client.py | 24 + parea/client_two.py | 1212 +++++++++++++++++++ parea/cookbook/example2.py | 307 +++++ parea/cookbook/tracing_with_Parea_sdk.ipynb | 157 +-- parea/cookbook/tracing_with_parea_sdk.py | 2 +- parea/example.py | 114 +- parea/parea_logger.py | 25 + parea/schemas/models.py | 43 +- parea/trace_utils/__init__.py | 0 parea/trace_utils/log_tree.py | 52 + parea/trace_utils/run_helpers.py | 563 +++++++++ parea/trace_utils/run_trees.py | 423 +++++++ parea/trace_utils/trace.py | 201 +++ poetry.lock | 573 ++++++++- pyproject.toml | 3 + requirements.txt | 149 ++- 18 files changed, 3735 insertions(+), 117 deletions(-) create mode 100644 parea/client_two.py create mode 100644 parea/cookbook/example2.py create mode 100644 parea/parea_logger.py create mode 100644 parea/trace_utils/__init__.py create mode 100644 parea/trace_utils/log_tree.py create mode 100644 parea/trace_utils/run_helpers.py create mode 100644 parea/trace_utils/run_trees.py create mode 100644 parea/trace_utils/trace.py diff --git a/Makefile b/Makefile index d7518678..86f0d3b5 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ poetry-remove: install: poetry lock -n && poetry export --without-hashes > requirements.txt poetry install -n - -poetry run mypy --install-types --non-interactive ./ + -#poetry run mypy --install-types --non-interactive ./ .PHONY: pre-commit-install pre-commit-install: diff --git a/parea/api_client.py b/parea/api_client.py index 1546a5e2..2af1ac70 100644 --- a/parea/api_client.py +++ b/parea/api_client.py @@ -5,7 +5,7 @@ class HTTPClient: _instance = None - base_url = "https://optimus-prompt-backend.vercel.app/api/parea/v1" + base_url = "http://localhost:8000/api/parea/v1" # "https://optimus-prompt-backend.vercel.app/api/parea/v1" api_key = None def __new__(cls, *args, **kwargs): diff --git a/parea/client.py b/parea/client.py index 4f26263e..488a9892 100644 --- a/parea/client.py +++ b/parea/client.py @@ -3,7 +3,9 @@ from attrs import asdict, define, field from parea.api_client import HTTPClient +from parea.parea_logger import parea_logger from parea.schemas.models import Completion, CompletionResponse, FeedbackRequest, UseDeployedPrompt, UseDeployedPromptResponse +from parea.trace_utils.trace import trace_context COMPLETION_ENDPOINT = "/completion" DEPLOYED_PROMPT_ENDPOINT = "/deployed-prompt" @@ -17,8 +19,10 @@ class Parea: def __attrs_post_init__(self): self._client.set_api_key(self.api_key) + parea_logger.set_client(self._client) def completion(self, data: Completion) -> CompletionResponse: + data.inference_id = trace_context.get()[-1] r = self._client.request( "POST", COMPLETION_ENDPOINT, @@ -27,6 +31,8 @@ def completion(self, data: Completion) -> CompletionResponse: return CompletionResponse(**r.json()) async def acompletion(self, data: Completion) -> CompletionResponse: + trace_id = trace_context.get()[-1] + data.trace_id = trace_id r = await self._client.request_async( "POST", COMPLETION_ENDPOINT, @@ -64,6 +70,24 @@ async def arecord_feedback(self, data: FeedbackRequest) -> None: data=asdict(data), ) + # def record_log(self, data: LogRequest) -> None: + # print(f"Logging to database: {data}") + # db_entries.append(data) + # # self._client.request( + # # "POST", + # # LOG_ENDPOINT, + # # data=asdict(data), + # # ) + # + # async def arecord_log(self, data: LogRequest) -> None: + # print(f"Logging to database: {data}") + # db_entries.append(data) + # # await self._client.request_async( + # # "POST", + # # LOG_ENDPOINT, + # # data=asdict(data), + # # ) + def gen_trace_id() -> str: """Generate a unique trace id for each chain of requests""" diff --git a/parea/client_two.py b/parea/client_two.py new file mode 100644 index 00000000..14ad5ea2 --- /dev/null +++ b/parea/client_two.py @@ -0,0 +1,1212 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union, cast + +import json +import logging +import os +import platform +import socket +import subprocess +import weakref +from collections.abc import Iterator, Mapping +from datetime import datetime +from enum import Enum +from functools import lru_cache +from urllib.parse import urlsplit +from uuid import UUID + +from attrs import asdict +from dotenv import load_dotenv +from requests import ConnectionError, HTTPError, Response, Session +from requests.adapters import HTTPAdapter +from urllib3.util import Retry + +from parea.schemas.models import Completion, CompletionResponse + +if TYPE_CHECKING: + pass + + +load_dotenv() + +logger = logging.getLogger(__name__) + + +class PareaAPIError(Exception): + """An error occurred while communicating with the Parea API.""" + + +class PareaUserError(Exception): + """An error occurred while communicating with the Parea API.""" + + +class PareaError(Exception): + """An error occurred while communicating with the Parea API.""" + + +class PareaConnectionError(Exception): + """Couldn't connect to the Parea API.""" + + +def xor_args(*arg_groups: tuple[str, ...]) -> Callable: + """Validate specified keyword args are mutually exclusive.""" + + def decorator(func: Callable) -> Callable: + def wrapper(*args: Any, **kwargs: Any) -> Callable: + """Validate exactly one arg in each group is not None.""" + counts = [sum(1 for arg in arg_group if kwargs.get(arg) is not None) for arg_group in arg_groups] + invalid_groups = [i for i, count in enumerate(counts) if count != 1] + if invalid_groups: + invalid_group_names = [", ".join(arg_groups[i]) for i in invalid_groups] + raise ValueError("Exactly one argument in each of the following" " groups must be defined:" f" {', '.join(invalid_group_names)}") + return func(*args, **kwargs) + + return wrapper + + return decorator + + +def raise_for_status_with_text(response: Response) -> None: + """Raise an error with the response text.""" + try: + response.raise_for_status() + except HTTPError as e: + raise ValueError(response.text) from e + + +def get_enum_value(enum: Enum | str) -> str: + """Get the value of a string enum.""" + if isinstance(enum, Enum): + return enum.value + return enum + + +@lru_cache +def get_runtime_environment() -> dict: + """Get information about the environment.""" + # Lazy import to avoid circular imports + from parea import version + + return { + "sdk_version": version, + "library": "langsmith", + "platform": platform.platform(), + "runtime": "python", + "runtime_version": platform.python_version(), + "langchain_version": get_langchain_environment(), + } + + +def _get_message_type(message: Mapping[str, Any]) -> str: + if not message: + raise ValueError("Message is empty.") + if "lc" in message: + if "id" not in message: + raise ValueError(f"Unexpected format for serialized message: {message}" " Message does not have an id.") + return message["id"][-1].replace("Message", "").lower() + else: + if "type" not in message: + raise ValueError(f"Unexpected format for stored message: {message}" " Message does not have a type.") + return message["type"] + + +def _get_message_fields(message: Mapping[str, Any]) -> Mapping[str, Any]: + if not message: + raise ValueError("Message is empty.") + if "lc" in message: + if "kwargs" not in message: + raise ValueError(f"Unexpected format for serialized message: {message}" " Message does not have kwargs.") + return message["kwargs"] + else: + if "data" not in message: + raise ValueError(f"Unexpected format for stored message: {message}" " Message does not have data.") + return message["data"] + + +def _convert_message(message: Mapping[str, Any]) -> dict[str, Any]: + """Extract message from a message object.""" + message_type = _get_message_type(message) + message_data = _get_message_fields(message) + return {"type": message_type, "data": message_data} + + +def get_messages_from_inputs(inputs: Mapping[str, Any]) -> list[dict[str, Any]]: + if "messages" in inputs: + return [_convert_message(message) for message in inputs["messages"]] + if "message" in inputs: + return [_convert_message(inputs["message"])] + raise ValueError(f"Could not find message(s) in run with inputs {inputs}.") + + +def get_message_generation_from_outputs(outputs: Mapping[str, Any]) -> dict[str, Any]: + if "generations" not in outputs: + raise ValueError(f"No generations found in in run with output: {outputs}.") + generations = outputs["generations"] + if len(generations) != 1: + raise ValueError("Chat examples expect exactly one generation." f" Found {len(generations)} generations: {generations}.") + first_generation = generations[0] + if "message" not in first_generation: + raise ValueError(f"Unexpected format for generation: {first_generation}." " Generation does not have a message.") + return _convert_message(first_generation["message"]) + + +def get_prompt_from_inputs(inputs: Mapping[str, Any]) -> str: + if "prompt" in inputs: + return inputs["prompt"] + if "prompts" in inputs: + prompts = inputs["prompts"] + if len(prompts) == 1: + return prompts[0] + raise ValueError(f"Multiple prompts in run with inputs {inputs}." " Please create example manually.") + raise ValueError(f"Could not find prompt in run with inputs {inputs}.") + + +def get_llm_generation_from_outputs(outputs: Mapping[str, Any]) -> str: + if "generations" not in outputs: + raise ValueError(f"No generations found in in run with output: {outputs}.") + generations = outputs["generations"] + if len(generations) != 1: + raise ValueError(f"Multiple generations in run: {generations}") + first_generation = generations[0] + if "text" not in first_generation: + raise ValueError(f"No text in generation: {first_generation}") + return first_generation["text"] + + +@lru_cache +def get_docker_compose_command() -> list[str]: + """Get the correct docker compose command for this system.""" + try: + subprocess.check_call( + ["docker", "compose", "--version"], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) + return ["docker", "compose"] + except (subprocess.CalledProcessError, FileNotFoundError): + try: + subprocess.check_call( + ["docker-compose", "--version"], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) + return ["docker-compose"] + except (subprocess.CalledProcessError, FileNotFoundError): + raise ValueError( + "Neither 'docker compose' nor 'docker-compose'" + " commands are available. Please install the Docker" + " server following the instructions for your operating" + " system at https://docs.docker.com/engine/install/" + ) + + +@lru_cache +def get_langchain_environment() -> str | None: + try: + import parea # type: ignore + + return parea.version + except: # noqa + return None + + +@lru_cache +def get_docker_version() -> str | None: + import subprocess + + try: + docker_version = subprocess.check_output(["docker", "--version"]).decode("utf-8").strip() + except FileNotFoundError: + docker_version = "unknown" + except: # noqa + return None + return docker_version + + +@lru_cache +def get_docker_compose_version() -> str | None: + try: + docker_compose_version = subprocess.check_output(["docker-compose", "--version"]).decode("utf-8").strip() + except FileNotFoundError: + docker_compose_version = "unknown" + except: # noqa + return None + return docker_compose_version + + +@lru_cache +def _get_compose_command() -> list[str] | None: + try: + compose_command = get_docker_compose_command() + except ValueError as e: + compose_command = [f"NOT INSTALLED: {e}"] + except: # noqa + return None + return compose_command + + +@lru_cache +def get_docker_environment() -> dict: + """Get information about the environment.""" + compose_command = _get_compose_command() + return { + "docker_version": get_docker_version(), + "docker_compose_command": " ".join(compose_command) if compose_command is not None else None, + "docker_compose_version": get_docker_compose_version(), + } + + +def _is_localhost(url: str) -> bool: + """Check if the URL is localhost. + + Parameters + ---------- + url : str + The URL to check. + + Returns + ------- + bool + True if the URL is localhost, False otherwise. + """ + try: + netloc = urlsplit(url).netloc.split(":")[0] + ip = socket.gethostbyname(netloc) + return ip == "127.0.0.1" or ip.startswith("0.0.0.0") or ip.startswith("::") + except socket.gaierror: + return False + + +ID_TYPE = Union[UUID, str] + + +def _default_retry_config() -> Retry: + """Get the default retry configuration. + + Returns + ------- + Retry + The default retry configuration. + """ + return Retry( + total=3, + allowed_methods=None, # Retry on all methods + status_forcelist=[502, 503, 504, 408, 425, 429], + backoff_factor=0.5, + # Sadly urllib3 1.x doesn't support backoff_jitter + raise_on_redirect=False, + raise_on_status=False, + ) + + +def _serialize_json(obj: Any) -> str: + """Serialize an object to JSON. + + Parameters + ---------- + obj : Any + The object to serialize. + + Returns + ------- + str + The serialized JSON string. + + Raises + ------ + TypeError + If the object type is not serializable. + """ + if isinstance(obj, datetime): + return obj.isoformat() + else: + return str(obj) + + +def close_session(session: Session) -> None: + """Close the session. + + Parameters + ---------- + session : Session + The session to close. + """ + logger.debug("Closing Client.session") + session.close() + + +def _validate_api_key_if_hosted(api_url: str, api_key: str | None) -> None: + """Verify API key is provided if url not localhost. + + Parameters + ---------- + api_url : str + The API URL. + api_key : str or None + The API key. + + Raises + ------ + LangSmithUserError + If the API key is not provided when using the hosted service. + """ + if not _is_localhost(api_url): + if not api_key: + raise PareaUserError("API key must be provided when using hosted LangSmith API") + + +def _get_api_key(api_key: str | None) -> str | None: + api_key = api_key if api_key is not None else os.getenv("DEV_API_KEY") + if api_key is None or not api_key.strip(): + return None + return api_key.strip().strip('"').strip("'") + + +def _get_api_url(api_url: str | None, api_key: str | None) -> str: + _api_url = api_url if api_url is not None else "http://localhost:8000/api/parea/v1" + if not _api_url.strip(): + raise PareaUserError("Parea API URL cannot be empty") + return _api_url.strip().strip('"').strip("'").rstrip("/") + + +class Client: + """Client for interacting with the LangSmith API.""" + + __slots__ = [ + "__weakref__", + "api_url", + "api_key", + "retry_config", + "timeout_ms", + "session", + ] + + def __init__( + self, + api_url: str | None = None, + *, + api_key: str | None = None, + retry_config: Retry | None = None, + timeout_ms: int | None = None, + ) -> None: + """Initialize a Client instance. + + Parameters + ---------- + api_url : str or None, default=None + URL for the LangSmith API. Defaults to the LANGCHAIN_ENDPOINT + environment variable or http://localhost:1984 if not set. + api_key : str or None, default=None + API key for the LangSmith API. Defaults to the LANGCHAIN_API_KEY + environment variable. + retry_config : Retry or None, default=None + Retry configuration for the HTTPAdapter. + timeout_ms : int or None, default=None + Timeout in milliseconds for the HTTPAdapter. + + Raises + ------ + LangSmithUserError + If the API key is not provided when using the hosted service. + """ + self.api_key = _get_api_key(api_key) + self.api_url = _get_api_url(api_url, self.api_key) + _validate_api_key_if_hosted(self.api_url, self.api_key) + self.retry_config = retry_config or _default_retry_config() + self.timeout_ms = timeout_ms or 7000 + # Create a session and register a finalizer to close it + self.session = Session() + weakref.finalize(self, close_session, self.session) + + # Mount the HTTPAdapter with the retry configuration + adapter = HTTPAdapter(max_retries=self.retry_config) + self.session.mount("http://", adapter) + self.session.mount("https://", adapter) + + def _repr_html_(self) -> str: + """Return an HTML representation of the instance with a link to the URL. + + Returns + ------- + str + The HTML representation of the instance. + """ + link = self._host_url + return f'LangSmith Client' + + def __repr__(self) -> str: + """Return a string representation of the instance with a link to the URL. + + Returns + ------- + str + The string representation of the instance. + """ + return f"Client (API URL: {self.api_url})" + + @property + def _host_url(self) -> str: + """The web host url.""" + if _is_localhost(self.api_url): + link = "http://localhost" + elif "dev" in self.api_url.split(".", maxsplit=1)[0]: + link = "http://localhost" + else: + link = "https://optimus-prompt-backend.vercel.app" + return link + + @property + def _headers(self) -> dict[str, str]: + """Get the headers for the API request. + + Returns + ------- + Dict[str, str] + The headers for the API request. + """ + headers = {} + if self.api_key: + headers["x-api-key"] = self.api_key + return headers + + def request_with_retries( + self, + request_method: str, + url: str, + request_kwargs: Mapping, + ) -> Response: + """Send a request with retries. + + Parameters + ---------- + request_method : str + The HTTP request method. + url : str + The URL to send the request to. + request_kwargs : Mapping + Additional request parameters. + + Returns + ------- + Response + The response object. + + Raises + ------ + LangSmithAPIError + If a server error occurs. + LangSmithUserError + If the request fails. + LangSmithConnectionError + If a connection error occurs. + LangSmithError + If the request fails. + """ + try: + response = self.session.request(request_method, url, stream=False, **request_kwargs) + raise_for_status_with_text(response) + return response + except HTTPError as e: + if response is not None and response.status_code == 500: + raise PareaAPIError(f"Server error caused failure to {request_method} {url} in" f" Parea API. {e}") + else: + raise PareaUserError(f"Failed to {request_method} {url} in LangSmith API. {e}") + except ConnectionError as e: + raise PareaConnectionError(f"Connection error caused failure to {request_method} {url}" " in Parea API. Please confirm your PAREA_ENDPOINT.") from e + except Exception as e: + raise PareaError(f"Failed to {request_method} {url} in Parea API. {e}") from e + + def _get_with_retries(self, path: str, params: dict[str, Any] | None = None) -> Response: + """Send a GET request with retries. + + Parameters + ---------- + path : str + The path of the request URL. + params : Dict[str, Any] or None, default=None + The query parameters. + + Returns + ------- + Response + The response object. + + Raises + ------ + LangSmithAPIError + If a server error occurs. + LangSmithUserError + If the request fails. + LangSmithConnectionError + If a connection error occurs. + LangSmithError + If the request fails. + """ + return self.request_with_retries( + "get", + f"{self.api_url}/{path}", + request_kwargs={ + "params": params, + "headers": self._headers, + "timeout": self.timeout_ms / 1000, + }, + ) + + def _get_paginated_list(self, path: str, *, params: dict | None = None) -> Iterator[dict]: + """Get a paginated list of items. + + Parameters + ---------- + path : str + The path of the request URL. + params : dict or None, default=None + The query parameters. + + Yields + ------ + dict + The items in the paginated list. + """ + params_ = params.copy() if params else {} + offset = params_.get("offset", 0) + params_["limit"] = params_.get("limit", 100) + while True: + params_["offset"] = offset + response = self._get_with_retries(path, params=params_) + items = response.json() + if not items: + break + yield from items + if len(items) < params_["limit"]: + # offset and limit isn't respected if we're + # querying for specific values + break + offset += len(items) + + def create_run( + self, + name: str, + inputs: dict[str, Any], + run_type: str, + *, + execution_order: int | None = None, + **kwargs: Any, + ) -> None: + """Persist a run to the LangSmith API. + + Parameters + ---------- + name : str + The name of the run. + inputs : Dict[str, Any] + The input values for the run. + run_type : str + The type of the run, such as tool, chain, llm, retriever, + embedding, prompt, or parser. + execution_order : int or None, default=None + The execution order of the run. + **kwargs : Any + Additional keyword arguments. + + Raises + ------ + LangSmithUserError + If the API key is not provided when using the hosted service. + """ + project_name = kwargs.pop( + "project_name", + kwargs.pop( + "session_name", + os.environ.get( + # TODO: Deprecate PAREA_SESSION + "PAREA_PROJECT", + os.environ.get("PAREA_SESSION", "default"), + ), + ), + ) + run_create = { + **kwargs, + "session_name": project_name, + "name": name, + "inputs": inputs, + "run_type": run_type, + "execution_order": execution_order if execution_order is not None else 1, + } + run_extra = cast(dict, run_create.setdefault("extra", {})) + runtime = run_extra.setdefault("runtime", {}) + runtime_env = get_runtime_environment() + run_extra["runtime"] = {**runtime_env, **runtime} + headers = {**self._headers, "Accept": "application/json"} + self.request_with_retries( + "post", + f"{self.api_url}/runs", + request_kwargs={ + "data": json.dumps(run_create, default=_serialize_json), + "headers": headers, + "timeout": self.timeout_ms / 1000, + }, + ) + + def completion(self, data: Completion) -> CompletionResponse: + headers = {**self._headers, "Accept": "application/json"} + r = self.request_with_retries( + "post", + f"{self.api_url}/completion", + request_kwargs={ + "data": json.dumps(asdict(data), default=_serialize_json), + "headers": headers, + "timeout": self.timeout_ms / 1000, + }, + ) + return CompletionResponse(**r.json()) + + def update_run( + self, + run_id: ID_TYPE, + **kwargs: Any, + ) -> None: + """Update a run in the LangSmith API. + + Parameters + ---------- + run_id : str or UUID + The ID of the run to update. + **kwargs : Any + Additional keyword arguments. + """ + headers = {**self._headers, "Accept": "application/json"} + self.request_with_retries( + "patch", + f"{self.api_url}/runs/{run_id}", + request_kwargs={ + "data": json.dumps(kwargs, default=_serialize_json), + "headers": headers, + "timeout": self.timeout_ms / 1000, + }, + ) + + # def _load_child_runs(self, run: Run) -> Run: + # """Load child runs for a given run. + # + # Parameters + # ---------- + # run : Run + # The run to load child runs for. + # + # Returns + # ------- + # Run + # The run with loaded child runs. + # + # Raises + # ------ + # LangSmithError + # If a child run has no parent. + # """ + # child_runs = self.list_runs(id=run.child_run_ids) + # treemap: DefaultDict[UUID, List[Run]] = defaultdict(list) + # runs: Dict[UUID, Run] = {} + # for child_run in sorted(child_runs, key=lambda r: r.execution_order): + # if child_run.parent_run_id is None: + # raise PareaError(f"Child run {child_run.id} has no parent") + # treemap[child_run.parent_run_id].append(child_run) + # runs[child_run.id] = child_run + # run.child_runs = treemap.pop(run.id, []) + # for run_id, children in treemap.items(): + # runs[run_id].child_runs = children + # return run + + # + # def read_run(self, run_id: ID_TYPE, load_child_runs: bool = False) -> Run: + # """Read a run from the LangSmith API. + # + # Parameters + # ---------- + # run_id : str or UUID + # The ID of the run to read. + # load_child_runs : bool, default=False + # Whether to load nested child runs. + # + # Returns + # ------- + # Run + # The run. + # """ + # response = self._get_with_retries(f"/runs/{run_id}") + # run = Run(**response.json(), _host_url=self._host_url) + # if load_child_runs and run.child_run_ids: + # run = self._load_child_runs(run) + # return run + # + # def list_runs( + # self, + # *, + # project_id: Optional[ID_TYPE] = None, + # project_name: Optional[str] = None, + # run_type: Optional[str] = None, + # dataset_name: Optional[str] = None, + # dataset_id: Optional[ID_TYPE] = None, + # reference_example_id: Optional[ID_TYPE] = None, + # query: Optional[str] = None, + # filter: Optional[str] = None, + # execution_order: Optional[int] = None, + # parent_run_id: Optional[ID_TYPE] = None, + # start_time: Optional[datetime] = None, + # end_time: Optional[datetime] = None, + # error: Optional[bool] = None, + # run_ids: Optional[List[ID_TYPE]] = None, + # limit: Optional[int] = None, + # offset: Optional[int] = None, + # order_by: Optional[Sequence[str]] = None, + # **kwargs: Any, + # ) -> Iterator[Run]: + # """List runs from the LangSmith API. + # + # Parameters + # ---------- + # project_id : UUID or None, default=None + # The ID of the project to filter by. + # project_name : str or None, default=None + # The name of the project to filter by. + # run_type : str or None, default=None + # The type of the runs to filter by. + # dataset_name : str or None, default=None + # The name of the dataset to filter by. + # dataset_id : UUID or None, default=None + # The ID of the dataset to filter by. + # reference_example_id : UUID or None, default=None + # The ID of the reference example to filter by. + # query : str or None, default=None + # The query string to filter by. + # filter : str or None, default=None + # The filter string to filter by. + # execution_order : int or None, default=None + # The execution order to filter by. + # parent_run_id : UUID or None, default=None + # The ID of the parent run to filter by. + # start_time : datetime or None, default=None + # The start time to filter by. + # end_time : datetime or None, default=None + # The end time to filter by. + # error : bool or None, default=None + # Whether to filter by error status. + # run_ids : List[str or UUID] or None, default=None + # The IDs of the runs to filter by. + # limit : int or None, default=None + # The maximum number of runs to return. + # offset : int or None, default=None + # The number of runs to skip. + # order_by : Sequence[str] or None, default=None + # The fields to order the runs by. + # **kwargs : Any + # Additional keyword arguments. + # + # Yields + # ------ + # Run + # The runs. + # """ + # if project_name is not None: + # if project_id is not None: + # raise ValueError("Only one of project_id or project_name may be given") + # project_id = self.read_project(project_name=project_name).id + # if dataset_name is not None: + # if dataset_id is not None: + # raise ValueError("Only one of dataset_id or dataset_name may be given") + # dataset_id = self.read_dataset(dataset_name=dataset_name).id + # query_params: Dict[str, Any] = { + # "session": project_id, + # "run_type": run_type, + # **kwargs, + # } + # if reference_example_id is not None: + # query_params["reference_example"] = reference_example_id + # if dataset_id is not None: + # query_params["dataset"] = dataset_id + # if query is not None: + # query_params["query"] = query + # if filter is not None: + # query_params["filter"] = filter + # if execution_order is not None: + # query_params["execution_order"] = execution_order + # if parent_run_id is not None: + # query_params["parent_run"] = parent_run_id + # if start_time is not None: + # query_params["start_time"] = start_time.isoformat() + # if end_time is not None: + # query_params["end_time"] = end_time.isoformat() + # if error is not None: + # query_params["error"] = error + # if run_ids is not None: + # query_params["id"] = run_ids + # if limit is not None: + # query_params["limit"] = limit + # if offset is not None: + # query_params["offset"] = offset + # if order_by is not None: + # query_params["order"] = order_by + # yield from (Run(**run, _host_url=self._host_url) for run in self._get_paginated_list("/runs", params=query_params)) + # + # def delete_run(self, run_id: ID_TYPE) -> None: + # """Delete a run from the LangSmith API. + # + # Parameters + # ---------- + # run_id : str or UUID + # The ID of the run to delete. + # """ + # response = self.session.delete( + # f"{self.api_url}/runs/{run_id}", + # headers=self._headers, + # ) + # raise_for_status_with_text(response) + # + # def share_run(self, run_id: ID_TYPE, *, share_id: Optional[ID_TYPE] = None) -> str: + # """Get a share link for a run.""" + # data = { + # "run_id": str(run_id), + # "share_token": share_id or str(uuid4()), + # } + # response = self.session.put( + # f"{self.api_url}/runs/{run_id}/share", + # headers=self._headers, + # json=data, + # ) + # raise_for_status_with_text(response) + # share_token = response.json()["share_token"] + # return f"{self._host_url}/public/{share_token}/r" + # + # def unshare_run(self, run_id: ID_TYPE) -> None: + # """Delete share link for a run.""" + # response = self.session.delete( + # f"{self.api_url}/runs/{run_id}/share", + # headers=self._headers, + # ) + # raise_for_status_with_text(response) + # + # def read_run_shared_link(self, run_id: ID_TYPE) -> Optional[str]: + # response = self.session.get( + # f"{self.api_url}/runs/{run_id}/share", + # headers=self._headers, + # ) + # raise_for_status_with_text(response) + # result = response.json() + # if result is None or "share_token" not in result: + # return None + # return f"{self._host_url}/public/{result['share_token']}/r" + # + # def run_is_shared(self, run_id: ID_TYPE) -> bool: + # """Get share state for a run.""" + # link = self.read_run_shared_link(run_id) + # return link is not None + + +# import logging +# import os +# import platform +# import socket +# import weakref +# from datetime import datetime +# from enum import Enum +# from functools import lru_cache +# from typing import Any, Callable, Dict, Mapping, Optional, Tuple, Union, AsyncIterator +# from typing import ( +# TYPE_CHECKING, +# cast, +# ) +# from urllib.parse import urlsplit +# from uuid import UUID +# +# import httpx +# from attrs import asdict +# from dotenv import load_dotenv +# from httpx import HTTPStatusError +# +# from parea.schemas.models import Completion, CompletionResponse +# +# if TYPE_CHECKING: +# pass +# +# load_dotenv() +# +# logger = logging.getLogger(__name__) +# +# +# class PareaAPIError(Exception): +# """An error occurred while communicating with the Parea API.""" +# +# +# class PareaUserError(Exception): +# """An error occurred while communicating with the Parea API.""" +# +# +# class PareaError(Exception): +# """An error occurred while communicating with the Parea API.""" +# +# +# class PareaConnectionError(Exception): +# """Couldn't connect to the Parea API.""" +# +# +# def xor_args(*arg_groups: Tuple[str, ...]) -> Callable: +# """Validate specified keyword args are mutually exclusive.""" +# +# def decorator(func: Callable) -> Callable: +# def wrapper(*args: Any, **kwargs: Any) -> Callable: +# """Validate exactly one arg in each group is not None.""" +# counts = [sum(1 for arg in arg_group if kwargs.get(arg) is not None) for arg_group in arg_groups] +# invalid_groups = [i for i, count in enumerate(counts) if count != 1] +# if invalid_groups: +# invalid_group_names = [", ".join(arg_groups[i]) for i in invalid_groups] +# raise ValueError("Exactly one argument in each of the following" " groups must be defined:" f" {', '.join(invalid_group_names)}") +# return func(*args, **kwargs) +# +# return wrapper +# +# return decorator +# +# +# def raise_for_status_with_text(response: httpx.Response) -> None: +# """Raise an error with the response text.""" +# try: +# response.raise_for_status() +# except HTTPStatusError as e: +# raise ValueError(response.text) from e +# +# +# def get_enum_value(enum: Union[Enum, str]) -> str: +# """Get the value of a string enum.""" +# if isinstance(enum, Enum): +# return enum.value +# return enum +# +# +# @lru_cache +# def get_runtime_environment() -> dict: +# """Get information about the environment.""" +# # Lazy import to avoid circular imports +# from parea import version +# +# return { +# "sdk_version": version, +# "library": "langsmith", +# "platform": platform.platform(), +# "runtime": "python", +# "runtime_version": platform.python_version(), +# } +# +# def _is_localhost(url: str) -> bool: +# """Check if the URL is localhost.""" +# try: +# netloc = urlsplit(url).netloc.split(":")[0] +# ip = socket.gethostbyname(netloc) +# return ip == "127.0.0.1" or ip.startswith("0.0.0.0") or ip.startswith("::") +# except socket.gaierror: +# return False +# +# +# ID_TYPE = Union[UUID, str] +# +# +# def _serialize_json(obj: Any) -> str: +# """Serialize an object to JSON.""" +# if isinstance(obj, datetime): +# return obj.isoformat() +# else: +# return str(obj) +# +# +# async def close_session(session: httpx.AsyncClient) -> None: +# """Close the session.""" +# logger.debug("Closing Client.session") +# await session.aclose() +# +# +# def _validate_api_key_if_hosted(api_url: str, api_key: Optional[str]) -> None: +# """Verify API key is provided if url not localhost.""" +# if not _is_localhost(api_url): +# if not api_key: +# raise PareaUserError("API key must be provided when using hosted LangSmith API") +# +# +# def _get_api_key(api_key: Optional[str]) -> Optional[str]: +# api_key = api_key if api_key is not None else os.getenv("DEV_API_KEY") +# if api_key is None or not api_key.strip(): +# return None +# return api_key.strip().strip('"').strip("'") +# +# +# def _get_api_url(api_url: Optional[str], api_key: Optional[str]) -> str: +# _api_url = api_url if api_url is not None else "http://localhost:8000/api/parea/v1" +# if not _api_url.strip(): +# raise PareaUserError("Parea API URL cannot be empty") +# return _api_url.strip().strip('"').strip("'").rstrip("/") +# +# +# class Client: +# """Client for interacting with the LangSmith API.""" +# +# def __init__( +# self, +# api_url: Optional[str] = None, +# *, +# api_key: Optional[str] = None, +# ) -> None: +# """Initialize a Client instance.""" +# self.api_key = _get_api_key(api_key) +# self.api_url = _get_api_url(api_url, self.api_key) +# _validate_api_key_if_hosted(self.api_url, self.api_key) +# +# # Create a session and register a finalizer to close it +# self.session = httpx.AsyncClient() +# weakref.finalize(self, close_session, self.session) +# +# def _repr_html_(self) -> str: +# """Return an HTML representation of the instance with a link to the URL.""" +# link = self._host_url +# return f'LangSmith Client' +# +# def __repr__(self) -> str: +# """Return a string representation of the instance with a link to the URL.""" +# return f"Client (API URL: {self.api_url})" +# +# @property +# def _host_url(self) -> str: +# """The web host url.""" +# if _is_localhost(self.api_url): +# link = "http://localhost" +# elif "dev" in self.api_url.split(".", maxsplit=1)[0]: +# link = "http://localhost" +# else: +# link = "https://optimus-prompt-backend.vercel.app" +# return link +# +# @property +# def _headers(self) -> Dict[str, str]: +# """Get the headers for the API request.""" +# headers = {} +# if self.api_key: +# headers["x-api-key"] = self.api_key +# return headers +# +# async def request_with_retries( +# self, +# request_method: str, +# url: str, +# request_kwargs: Mapping, +# ) -> httpx.Response: +# """Send a request with retries.""" +# +# try: +# response = await self.session.request(request_method, url, **request_kwargs) +# raise_for_status_with_text(response) +# return response +# except HTTPStatusError as e: +# if response.status_code == 500: +# raise PareaAPIError(f"Server error caused failure to {request_method} {url} in Parea API. {e}") +# else: +# raise PareaUserError(f"Failed to {request_method} {url} in LangSmith API. {e}") +# except httpx.ConnectError as e: +# raise PareaConnectionError(f"Connection error caused failure to {request_method} {url} in Parea API. Please confirm your PAREA_ENDPOINT.") from e +# except Exception as e: +# raise PareaError(f"Failed to {request_method} {url} in Parea API. {e}") from e +# +# async def _get_with_retries(self, path: str, params: Optional[Dict[str, Any]] = None) -> httpx.Response: +# """Send a GET request with retries.""" +# return await self.request_with_retries( +# "get", +# f"{self.api_url}/{path}", +# request_kwargs={ +# "params": params, +# "headers": self._headers, +# }, +# ) +# +# async def _get_paginated_list(self, path: str, *, params: Optional[dict] = None) -> AsyncIterator[dict]: +# """Get a paginated list of items.""" +# params_ = params.copy() if params else {} +# offset = params_.get("offset", 0) +# params_["limit"] = params_.get("limit", 100) +# while True: +# params_["offset"] = offset +# response = await self._get_with_retries(path, params=params_) +# items = response.json() +# if not items: +# break +# for item in items: +# yield item +# if len(items) < params_["limit"]: +# break +# offset += len(items) +# +# async def create_run( +# self, +# name: str, +# inputs: Dict[str, Any], +# run_type: str, +# *, +# execution_order: Optional[int] = None, +# **kwargs: Any, +# ) -> None: +# """Persist a run to the LangSmith API.""" +# +# project_name = kwargs.pop( +# "project_name", +# kwargs.pop( +# "session_name", +# os.environ.get( +# "PAREA_PROJECT", +# os.environ.get("PAREA_SESSION", "default"), +# ), +# ), +# ) +# run_create = { +# **kwargs, +# "session_name": project_name, +# "name": name, +# "inputs": inputs, +# "run_type": run_type, +# "execution_order": execution_order if execution_order is not None else 1, +# } +# run_extra = cast(dict, run_create.setdefault("extra", {})) +# runtime = run_extra.setdefault("runtime", {}) +# runtime_env = get_runtime_environment() +# run_extra["runtime"] = {**runtime_env, **runtime} +# headers = {**self._headers, "Accept": "application/json"} +# await self.request_with_retries( +# "post", +# f"{self.api_url}/runs", +# request_kwargs={ +# "json": run_create, +# "headers": headers, +# }, +# ) +# +# async def completion(self, data: Completion) -> CompletionResponse: +# headers = {**self._headers, "Accept": "application/json"} +# r = await self.request_with_retries( +# "post", +# f"{self.api_url}/completion", +# request_kwargs={ +# "json": asdict(data), +# "headers": headers, +# }, +# ) +# return CompletionResponse(**r.json()) +# +# async def update_run( +# self, +# run_id: ID_TYPE, +# **kwargs: Any, +# ) -> None: +# """Update a run in the LangSmith API.""" +# headers = {**self._headers, "Accept": "application/json"} +# await self.request_with_retries( +# "patch", +# f"{self.api_url}/runs/{run_id}", +# request_kwargs={ +# "json": kwargs, +# "headers": headers, +# }, +# ) diff --git a/parea/cookbook/example2.py b/parea/cookbook/example2.py new file mode 100644 index 00000000..b25d906d --- /dev/null +++ b/parea/cookbook/example2.py @@ -0,0 +1,307 @@ +from typing import Dict, List + +import os + +from dotenv import load_dotenv + +from parea.client_two import Client +from parea.schemas.models import Completion, LLMInputs, Message, ModelParams, Role +from parea.trace_utils.run_helpers import traceable + +load_dotenv() + +client = Client(api_key=os.getenv("DEV_API_KEY")) + +LIMIT = 1 + + +# dump task array to string +def dump_task(task): + d = "" # init + for tasklet in task: + d += f"\n{tasklet.get('task_name','')}" + d = d.strip() + return d + + +@traceable(run_type="llm") +def open_ai_inference( + prompt: str, + model: str = "gpt-3.5-turbo", + temperature: float = 0.5, +) -> str: + return client.completion( + data=Completion( + llm_configuration=LLMInputs( + model=model, + provider="openai", + model_params=ModelParams(model=model, temp=temperature), + messages=[Message(role=Role.system, content=prompt)], + ), + ) + ).content.strip() + + +@traceable(run_type="chain") +def expound_task(main_objective: str, current_task: str) -> list[dict[str, str]]: + print(f"****Expounding based on task:**** {current_task}") + prompt = f"You are an AI who performs one task based on the following objective: {main_objective}\n" f"Your task: {current_task}\nResponse:" + response = open_ai_inference(prompt) + new_tasks = response.split("\n") if "\n" in response else [response] + return [{"task_name": task_name} for task_name in new_tasks][0:1] + + +@traceable(run_type="chain") +def generate_tasks(main_objective: str, expounded_initial_task: list[dict[str, str]]) -> list[str]: + task_expansion = dump_task(expounded_initial_task) + prompt = ( + f"You are an AI who creates tasks based on the following MAIN OBJECTIVE: {main_objective}\n" + f"Create tasks pertaining directly to your previous research here:\n" + f"{task_expansion}\nResponse:" + ) + response = open_ai_inference(prompt) + new_tasks = response.split("\n") if "\n" in response else [response] + task_list = [{"task_name": task_name} for task_name in new_tasks] + new_tasks_list: list[str] = [] + for task_item in task_list: + # print(task_item) + task_description = task_item.get("task_name") + if task_description: + # print(task_description) + task_parts = task_description.strip().split(".", 1) + # print(task_parts) + if len(task_parts) == 2: + new_task = task_parts[1].strip() + new_tasks_list.append(new_task) + + return new_tasks_list[0:1] + + +@traceable(run_type="chain") +def run_agent(main_objective: str, initial_task: str = "") -> list[dict[str, str]]: + generated_tasks = [] + expounded_initial_task = expound_task(main_objective, initial_task) + new_tasks = generate_tasks(main_objective, expounded_initial_task) + print(f"Generated {len(new_tasks)} tasks") + task_counter = 0 + for task in new_tasks: + task_counter += 1 + print(f"#### ({task_counter}) Generated Task ####") + q = expound_task(main_objective, task) + exp = dump_task(q) + generated_tasks.append({f"task_{task_counter}": exp}) + if task_counter >= LIMIT: + print(f"Stopping after {LIMIT} tasks") + break + return generated_tasks + + +if __name__ == "__main__": + main_objective = "Become a machine learning expert." # overall objective + initial_task = "Learn about tensors." # first task to research + + print("*****OBJECTIVE*****") + print(f"{main_objective}") + + # Simple version here, just generate tasks based on the initial task and objective, + # then expound with GPT against the main objective and the newly generated tasks. + result = run_agent(main_objective, initial_task) + print("*****RESULT*****") + print(result) + + +# # Create a ContextVar to store the current trace context +# _TRACE_CONTEXT = contextvars.ContextVar("_TRACE_CONTEXT", default=None) +# +# +# def get_trace_context() -> Optional[str]: +# """Get the current trace context.""" +# return _TRACE_CONTEXT.get() +# +# +# def log_decorator(func): +# @functools.wraps(func) +# def wrapper(*args, **kwargs): +# # Get the parent trace_id from the current context +# parent_trace_id = get_trace_context() +# +# # Generate a new trace_id for this function call +# trace_id = gen_trace_id() +# +# # Set the new trace_id as the current context +# _TRACE_CONTEXT.set(trace_id) +# trace_name = func.__name__ +# +# start_timestamp = time.time() +# +# # Get function arguments using inspect +# arg_names = inspect.getfullargspec(func)[0] +# print(f"arg_names: {arg_names}") +# inputs = {**dict(zip(arg_names, args)), **kwargs} +# print(f"inputs: {inputs}") +# +# try: +# partial_func = functools.partial(func, trace_id=trace_id, trace_name=trace_name, metadata={"parent_trace_id": parent_trace_id}) +# result = partial_func(*args, **kwargs) +# except Exception as e: +# # Log the error and re-raise +# end_timestamp = time.time() +# log_chain( +# trace_id=trace_id, +# trace_name=trace_name, +# llm_inputs=inputs, +# output=None, +# error=str(e), +# start_timestamp=start_timestamp, +# end_timestamp=end_timestamp, +# parent_trace_id=parent_trace_id, +# ) +# raise +# else: +# # Log the successful execution +# end_timestamp = time.time() +# log_chain( +# trace_id=trace_id, +# trace_name=trace_name, +# llm_inputs=inputs, +# output=result, +# error=None, +# start_timestamp=start_timestamp, +# end_timestamp=end_timestamp, +# parent_trace_id=parent_trace_id, +# ) +# return result +# finally: +# # Reset the trace context to the parent trace_id +# _TRACE_CONTEXT.set(parent_trace_id) +# +# return wrapper +# +# +# def to_date_and_time_string(timestamp: float) -> str: +# return datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S %Z") +# +# +# def log_chain( +# trace_id: str, +# trace_name: str, +# llm_inputs: Optional[dict], +# output: Optional[str], +# error: Optional[str], +# start_timestamp: float, +# end_timestamp: float, +# parent_trace_id: Optional[str], +# ) -> None: +# httpx.post( +# "http://localhost:8000/api/parea/v1/log", +# json={ +# "trace_id": trace_id, +# "name": trace_name, +# "error": error, +# "status": "success" if error is None else "error", +# "llm_inputs": llm_inputs, +# "output": output, +# "start_timestamp": to_date_and_time_string(start_timestamp), +# "end_timestamp": to_date_and_time_string(end_timestamp), +# "user_defined_metadata": {"parent_trace_id": parent_trace_id}, +# }, +# headers={"x-api-key": os.getenv("DEV_API_KEY")}, +# timeout=60 * 3.0, +# ) +# +# +# # dump task array to string +# def dump_task(task): +# d = "" # init +# for tasklet in task: +# d += f"\n{tasklet.get('task_name','')}" +# d = d.strip() +# return d +# +# +# def open_ai_inference( +# prompt: str, +# model: str = "gpt-3.5-turbo", +# temperature: float = 0.5, +# max_tokens: int = 1024, +# **kwargs, +# ) -> str: +# return p.completion( +# data=Completion( +# llm_configuration=LLMInputs( +# model=model, +# provider="openai", +# model_params=ModelParams(model=model, temp=temperature, max_length=max_tokens), +# messages=[Message(role=Role.system, content=prompt)], +# ), +# **kwargs, +# ) +# ).content.strip() +# +# +# @log_decorator +# def expound_task(main_objective: str, current_task: str, **kwargs) -> List[Dict[str, str]]: +# print(f"****Expounding based on task:**** {current_task}") +# prompt = f"You are an AI who performs one task based on the following objective: {main_objective}\n" f"Your task: {current_task}\nResponse:" +# response = open_ai_inference(prompt, name="expound_task", **kwargs) +# new_tasks = response.split("\n") if "\n" in response else [response] +# return [{"task_name": task_name} for task_name in new_tasks] +# +# +# @log_decorator +# def generate_tasks(main_objective: str, expounded_initial_task: List[Dict[str, str]], **kwargs) -> List[str]: +# task_expansion = dump_task(expounded_initial_task) +# prompt = ( +# f"You are an AI who creates tasks based on the following MAIN OBJECTIVE: {main_objective}\n" +# f"Create tasks pertaining directly to your previous research here:\n" +# f"{task_expansion}\nResponse:" +# ) +# response = open_ai_inference(prompt, name="generate_tasks", **kwargs) +# new_tasks = response.split("\n") if "\n" in response else [response] +# task_list = [{"task_name": task_name} for task_name in new_tasks] +# new_tasks_list: List[str] = [] +# for task_item in task_list: +# # print(task_item) +# task_description = task_item.get("task_name") +# if task_description: +# # print(task_description) +# task_parts = task_description.strip().split(".", 1) +# # print(task_parts) +# if len(task_parts) == 2: +# new_task = task_parts[1].strip() +# new_tasks_list.append(new_task) +# +# return new_tasks_list +# +# +# @log_decorator +# def run_agent(main_objective: str, initial_task: str = "", **kwargs) -> List[Dict[str, str]]: +# generated_tasks = [] +# expounded_initial_task = expound_task(main_objective, initial_task, **kwargs) +# new_tasks = generate_tasks(main_objective, expounded_initial_task, **kwargs) +# print(f"Generated {len(new_tasks)} tasks") +# task_counter = 0 +# for task in new_tasks: +# task_counter += 1 +# print(f"#### ({task_counter}) Generated Task ####") +# q = expound_task(main_objective, task, **kwargs) +# exp = dump_task(q) +# generated_tasks.append({f"task_{task_counter}": exp}) +# if task_counter >= LIMIT: +# print(f"Stopping after {LIMIT} tasks") +# break +# return generated_tasks +# +# +# if __name__ == "__main__": +# main_objective = "Become a machine learning expert." # overall objective +# initial_task = "Learn about tensors." # first task to research +# +# print("*****OBJECTIVE*****") +# print(f"{main_objective}") +# +# # Simple version here, just generate tasks based on the initial task and objective, +# # then expound with GPT against the main objective and the newly generated tasks. +# result = run_agent(main_objective, initial_task) +# print("*****RESULT*****") +# print(result) diff --git a/parea/cookbook/tracing_with_Parea_sdk.ipynb b/parea/cookbook/tracing_with_Parea_sdk.ipynb index 9a28d626..b94f5796 100644 --- a/parea/cookbook/tracing_with_Parea_sdk.ipynb +++ b/parea/cookbook/tracing_with_Parea_sdk.ipynb @@ -113,54 +113,55 @@ "\n", "# We pass the deployment_id and the required inputs to the completion function along with the trace_id\n", "def argument_generator(query: str, additional_description: str = \"\", trace_id: Optional[str] = None, **kwargs) -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-RG8d9sssc_0cctwfpb_n6\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " },\n", - " trace_id=trace_id,\n", - " **kwargs,\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-RG8d9sssc_0cctwfpb_n6\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " },\n", + " trace_id=trace_id,\n", + " **kwargs,\n", + " )\n", + " ).content\n", "\n", "\n", "def critic(argument: str, trace_id: Optional[str] = None, **kwargs) -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-fXgZytVVVJjXD_71TDR4s\",\n", - " llm_inputs={\"argument\": argument},\n", - " trace_id=trace_id,\n", - " **kwargs,\n", - " )\n", - " ).content\n", - "\n", - "\n", - "def refiner(query: str, additional_description: str, current_arg: str, criticism: str, trace_id: Optional[str] = None, **kwargs) -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p--G2s9okMTWWWh3d8YqLY2\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " \"current_arg\": current_arg,\n", - " \"criticism\": criticism,\n", - " },\n", - " trace_id=trace_id,\n", - " **kwargs,\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-fXgZytVVVJjXD_71TDR4s\",\n", + " llm_inputs={\"argument\": argument},\n", + " trace_id=trace_id,\n", + " **kwargs,\n", + " )\n", + " ).content\n", + "\n", + "\n", + "def refiner(query: str, additional_description: str, current_arg: str, criticism: str, trace_id: Optional[str] = None,\n", + " **kwargs) -> str:\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p--G2s9okMTWWWh3d8YqLY2\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " \"current_arg\": current_arg,\n", + " \"criticism\": criticism,\n", + " },\n", + " trace_id=trace_id,\n", + " **kwargs,\n", + " )\n", + " ).content\n", "\n", "\n", "# This is the parent function which orchestrates the chaining. We'll define our trace_id and trace_name here\n", "def argument_chain(query: str, additional_description: str = \"\") -> str:\n", - " trace_id, trace_name = gen_trace_id(), \"argument_chain\"\n", - " argument = argument_generator(query, additional_description, trace_id, trace_name=trace_name)\n", - " criticism = critic(argument, trace_id)\n", - " return refiner(query, additional_description, argument, criticism, trace_id)" + " trace_id, trace_name = gen_trace_id(), \"argument_chain\"\n", + " argument = argument_generator(query, additional_description, trace_id, trace_name=trace_name)\n", + " criticism = critic(argument, trace_id)\n", + " return refiner(query, additional_description, argument, criticism, trace_id)" ] }, { @@ -188,8 +189,8 @@ "outputs": [], "source": [ "result = argument_chain(\n", - " \"Whether moonshine is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why moonshine is good for you.\",\n", + " \"Whether moonshine is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why moonshine is good for you.\",\n", ")\n", "print(result)" ] @@ -222,10 +223,10 @@ "outputs": [], "source": [ "def argument_chain2(query: str, additional_description: str = \"\") -> Tuple[str, str]:\n", - " trace_id, trace_name = gen_trace_id(), \"argument_chain\"\n", - " argument = argument_generator(query, additional_description, trace_id, trace_name=trace_name)\n", - " criticism = critic(argument, trace_id)\n", - " return refiner(query, additional_description, argument, criticism, trace_id), trace_id" + " trace_id, trace_name = gen_trace_id(), \"argument_chain\"\n", + " argument = argument_generator(query, additional_description, trace_id, trace_name=trace_name)\n", + " criticism = critic(argument, trace_id)\n", + " return refiner(query, additional_description, argument, criticism, trace_id), trace_id" ] }, { @@ -239,8 +240,8 @@ "outputs": [], "source": [ "result, trace_id = argument_chain2(\n", - " \"Whether moonshine is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why moonshine is good for you.\",\n", + " \"Whether moonshine is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why moonshine is good for you.\",\n", ")\n", "print(result)" ] @@ -306,21 +307,22 @@ "\n", "\n", "# let's return the full CompletionResponse to see what other information is returned\n", - "def refiner2(query: str, additional_description: str, current_arg: str, criticism: str, trace_id: Optional[str] = None, **kwargs) -> CompletionResponse:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p--G2s9okMTvBEhXXXYqLY2\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " \"current_arg\": current_arg,\n", - " \"criticism\": criticism,\n", - " },\n", - " trace_id=trace_id,\n", - " **kwargs,\n", - " )\n", - " )" + "def refiner2(query: str, additional_description: str, current_arg: str, criticism: str, trace_id: Optional[str] = None,\n", + " **kwargs) -> CompletionResponse:\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p--G2s9okMTvBEhXXXYqLY2\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " \"current_arg\": current_arg,\n", + " \"criticism\": criticism,\n", + " },\n", + " trace_id=trace_id,\n", + " **kwargs,\n", + " )\n", + " )" ], "metadata": { "id": "cXUHZpZbegIn", @@ -348,12 +350,13 @@ "outputs": [], "source": [ "def argument_chain_3(query: str, additional_description: str = \"\") -> CompletionResponse:\n", - " trace_id, parent_trace_name = gen_trace_id(), \"argument_chain\"\n", - " tags = [\"tutorial\"]\n", - " metadata = {\"githash\": \"e38f04c83\"}\n", - " argument = argument_generator(query, additional_description, trace_id, trace_name=parent_trace_name, tags=tags, metadata=metadata)\n", - " criticism = critic(argument, trace_id)\n", - " return refiner2(query, additional_description, argument, criticism, trace_id)" + " trace_id, parent_trace_name = gen_trace_id(), \"argument_chain\"\n", + " tags = [\"tutorial\"]\n", + " metadata = {\"githash\": \"e38f04c83\"}\n", + " argument = argument_generator(query, additional_description, trace_id, trace_name=parent_trace_name, tags=tags,\n", + " metadata=metadata)\n", + " criticism = critic(argument, trace_id)\n", + " return refiner2(query, additional_description, argument, criticism, trace_id)" ] }, { @@ -362,16 +365,16 @@ "import json, attrs\n", "\n", "result = argument_chain_3(\n", - " \"Whether moonshine is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why sunshine is good for you.\",\n", + " \"Whether moonshine is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why sunshine is good for you.\",\n", ")\n", "\n", "p.record_feedback(\n", - " FeedbackRequest(\n", - " trace_id=result.trace_id,\n", - " score=0.5,\n", - " target=\"Moonshine is nice. Full stop.\",\n", - " )\n", + " FeedbackRequest(\n", + " trace_id=result.trace_id,\n", + " score=0.5,\n", + " target=\"Moonshine is nice. Full stop.\",\n", + " )\n", ")\n", "print(json.dumps(attrs.asdict(result), indent=4))" ], diff --git a/parea/cookbook/tracing_with_parea_sdk.py b/parea/cookbook/tracing_with_parea_sdk.py index 0b52e1b4..a79d304a 100644 --- a/parea/cookbook/tracing_with_parea_sdk.py +++ b/parea/cookbook/tracing_with_parea_sdk.py @@ -1,4 +1,4 @@ -from typing import Optional, Tuple +from typing import Optional import os from datetime import datetime diff --git a/parea/example.py b/parea/example.py index ab427912..65a82c36 100644 --- a/parea/example.py +++ b/parea/example.py @@ -1,50 +1,110 @@ -import asyncio import os +from datetime import datetime from dotenv import load_dotenv from parea.client import Parea from parea.schemas.models import Completion, CompletionResponse, UseDeployedPrompt, UseDeployedPromptResponse +from parea.trace_utils.trace import traceable load_dotenv() -p = Parea(api_key=os.getenv("API_KEY")) +p = Parea(api_key=os.getenv("DEV_API_KEY")) -# You will find this deployment_id in the Parea dashboard -deployment_id = os.getenv("DEPLOYMENT_ID") -# Assuming your deployed prompt's message is: -# {"role": "user", "content": "Write a hello world program using {{x}} and the {{y}} framework."} -llm_inputs = {"x": "Golang", "y": "Fiber"} -# You can easily unpack a dictionary into an attrs class -test_completion = Completion(**{"deployment_id": deployment_id, "llm_inputs": llm_inputs, "metadata": {"purpose": "testing"}}) +@traceable +def main(llm_inputs, metadata): + # You will find this deployment_id in the Parea dashboard + deployment_id = os.getenv("DEV_DEPLOYMENT_ID") -# By passing in my inputs, in addition to the raw message with unfilled variables {{x}} and {{y}}, -# you we will also get the filled-in prompt: -# {"role": "user", "content": "Write a hello world program using Golang and the Fiber framework."} -test_get_prompt = UseDeployedPrompt(deployment_id=deployment_id, llm_inputs=llm_inputs) - - -def main(): + # You can easily unpack a dictionary into an attrs class + test_completion = Completion(**{"deployment_id": deployment_id, "llm_inputs": llm_inputs, "metadata": metadata}) completion_response: CompletionResponse = p.completion(data=test_completion) print(completion_response) + + # By passing in my inputs, in addition to the raw message with unfilled variables {{x}} and {{y}}, + # you we will also get the filled-in prompt: + # {"role": "user", "content": "Write a hello world program using Golang and the Fiber framework."} + test_get_prompt = UseDeployedPrompt(deployment_id=deployment_id, llm_inputs=llm_inputs) deployed_prompt: UseDeployedPromptResponse = p.get_prompt(data=test_get_prompt) print("\n\n") - print(deployed_prompt) + return completion_response, deployed_prompt -async def main_async(): - completion_response: CompletionResponse = await p.acompletion(data=test_completion) - print(completion_response) - deployed_prompt: UseDeployedPromptResponse = await p.aget_prompt(data=test_get_prompt) - print("\n\n") - print(deployed_prompt) +# @traceable +# async def main_async(): +# completion_response: CompletionResponse = await p.acompletion(data=test_completion) +# print(completion_response) +# deployed_prompt: UseDeployedPromptResponse = await p.aget_prompt(data=test_get_prompt) +# print("\n\n") +# print(deployed_prompt) + +# +# def hello(name: str) -> str: +# return f"Hello {name}!" + +@traceable +def argument_generator(query: str, additional_description: str = "") -> str: + return p.completion( + Completion( + deployment_id="p-ee6hsbh1_4WtIz6UO6rEA", + llm_inputs={ + "additional_description": additional_description, + "date": f"{datetime.now()}", + "query": query, + }, + ) + ).content -def hello(name: str) -> str: - return f"Hello {name}!" + +@traceable +def critic(argument: str) -> str: + return p.completion( + Completion( + deployment_id="p-_4w8th0eJlWAx9g8g20Ov", + llm_inputs={"argument": argument}, + ) + ).content + + +@traceable +def refiner(query: str, additional_description: str, current_arg: str, criticism: str) -> str: + return p.completion( + Completion( + deployment_id="p-k2Iuvik12X_Uk4y-fOFPp", + llm_inputs={ + "additional_description": additional_description, + "date": f"{datetime.now()}", + "query": query, + "current_arg": current_arg, + "criticism": criticism, + }, + ) + ).content + + +@traceable +def argument_chain(query: str, additional_description: str = "") -> str: + argument = argument_generator(query, additional_description) + criticism = critic(argument) + return refiner(query, additional_description, argument, criticism) if __name__ == "__main__": - main() - asyncio.run(main_async()) + result = argument_chain( + "Whether sunshine is good for you.", + additional_description="Provide a concise, few sentence argument on why sunshine is good for you.", + ) + + +# if __name__ == "__main__": +# # Assuming your deployed prompt's message is: +# # {"role": "user", "content": "Write a hello world program using {{x}} and the {{y}} framework."} +# llm_inputs = {"x": "Golang", "y": "Fiber"} +# metadata= {"purpose": "testing"} +# completion_response, deployed_prompt = main(llm_inputs, metadata) +# print(completion_response) +# # print("\n\n") +# # print(deployed_prompt) +# # asyncio.run(main_async()) diff --git a/parea/parea_logger.py b/parea/parea_logger.py new file mode 100644 index 00000000..31c92757 --- /dev/null +++ b/parea/parea_logger.py @@ -0,0 +1,25 @@ +from attrs import asdict, define, field + +from parea.api_client import HTTPClient +from parea.schemas.models import TraceLog + +LOG_ENDPOINT = "/trace_log" + + +@define +class PareaLogger: + _client: HTTPClient = field(init=False) + + def set_client(self, client: HTTPClient) -> None: + self._client = client + + def record_log(self, data: TraceLog) -> None: + print(f"Logging to database: {data}") + self._client.request( + "POST", + LOG_ENDPOINT, + data=asdict(data), + ) + + +parea_logger = PareaLogger() diff --git a/parea/schemas/models.py b/parea/schemas/models.py index 33ad8625..d2d7eeb2 100644 --- a/parea/schemas/models.py +++ b/parea/schemas/models.py @@ -1,4 +1,4 @@ -from typing import Any, Optional, Union +from typing import Any, Dict, List, Optional, Union from enum import Enum @@ -41,7 +41,7 @@ class LLMInputs: @define class Completion: - trace_id: Optional[str] = None + inference_id: Optional[str] = None trace_name: Optional[str] = None llm_inputs: Optional[dict[str, Any]] = None llm_configuration: LLMInputs = LLMInputs() @@ -108,3 +108,42 @@ class FeedbackRequest: inference_id: Optional[str] = None name: Optional[str] = None target: Optional[str] = None + + +@define +class TraceLog: + trace_id: str + start_timestamp: str + organization_id: Optional[str] = None + + # metrics filled from completion + error: Optional[str] = None + status: Optional[str] = None + deployment_id: Optional[str] = None + evaluation_metric_ids: Optional[list[int]] = None + cache_hit: bool = False + configuration: LLMInputs = LLMInputs() + latency: Optional[float] = 0.0 + input_tokens: Optional[int] = 0 + output_tokens: Optional[int] = 0 + total_tokens: Optional[int] = 0 + cost: Optional[float] = 0.0 + feedback_score: Optional[float] = None + + # info filled from decorator + trace_name: Optional[str] = None + children: list[str] = field(factory=list) + + # metrics filled from either decorator or completion + end_timestamp: Optional[str] = None + end_user_identifier: Optional[str] = None + metadata: Optional[dict[str, str]] = None + target: Optional[str] = None + tags: Optional[list[str]] = None + inputs: Optional[dict[str, str]] = None + output: Optional[str] = None + + +@define +class TraceLogTree(TraceLog): + children: Optional[list[TraceLog]] = None diff --git a/parea/trace_utils/__init__.py b/parea/trace_utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/parea/trace_utils/log_tree.py b/parea/trace_utils/log_tree.py new file mode 100644 index 00000000..de319d8d --- /dev/null +++ b/parea/trace_utils/log_tree.py @@ -0,0 +1,52 @@ +from typing import Dict, List + +import json +import logging + +from attrs import asdict + +from parea.schemas.models import Completion, PartialLog + +logger = logging.getLogger() + + +def build_trees(db_entries: list[PartialLog]) -> list[PartialLog]: + entries_by_id: dict[str, PartialLog] = {entry.inference_id: entry for entry in db_entries} + all_child_ids = {child_id for entry in db_entries for child_id in entry.children} + root_ids = set(entries_by_id.keys()) - all_child_ids + + def build_subtree(entry_id: str) -> PartialLog: + entry: PartialLog = entries_by_id[entry_id] + + if entry.llm_inputs: + for k, v in entry.llm_inputs.items(): + if isinstance(v, Completion): + entry.llm_inputs[k] = asdict(v) + + subtree = PartialLog( + **{ + "inference_id": entry.inference_id, + "name": entry.trace_name, + "start_timestamp": entry.start_timestamp, + "llm_inputs": entry.llm_inputs, + "output": entry.output, + "end_timestamp": entry.end_timestamp, + "children": [build_subtree(child_id) for child_id in entry.children], + "metadata": entry.metadata, + "tags": entry.tags, + "target": entry.target, + "end_user_identifier": entry.end_user_identifier, + } + ) + + return subtree + + return [build_subtree(root_id) for root_id in root_ids] + + +def output_trace_data(db_entries: list[PartialLog]): + trees: list[PartialLog] = build_trees(db_entries) + for i, tree in enumerate(trees, start=1): + print(f"Tree {i}:") + print(tree) + print(json.dumps(asdict(tree), indent=2)) diff --git a/parea/trace_utils/run_helpers.py b/parea/trace_utils/run_helpers.py new file mode 100644 index 00000000..c005f396 --- /dev/null +++ b/parea/trace_utils/run_helpers.py @@ -0,0 +1,563 @@ +"""Decorator for creating a run tree from functions.""" +from typing import Any, Callable, Dict, List, Optional, TypedDict, Union + +import contextvars +import inspect +import logging +import os +from collections.abc import Generator, Mapping +from concurrent.futures import ThreadPoolExecutor +from contextlib import contextmanager +from functools import wraps +from uuid import uuid4 + +from parea.client_two import ID_TYPE, Client +from parea.trace_utils.run_trees import RunTree + +logger = logging.getLogger(__name__) +_PARENT_RUN_TREE = contextvars.ContextVar[Optional[RunTree]]("_PARENT_RUN_TREE", default=None) +_PROJECT_NAME = contextvars.ContextVar[Optional[str]]("_PROJECT_NAME", default=None) + + +def get_run_tree_context() -> Optional[RunTree]: + """Get the current run tree context.""" + return _PARENT_RUN_TREE.get() + + +def _get_inputs(signature: inspect.Signature, *args: Any, **kwargs: Any) -> dict[str, Any]: + """Return a dictionary of inputs from the function signature.""" + bound = signature.bind_partial(*args, **kwargs) + bound.apply_defaults() + arguments = dict(bound.arguments) + arguments.pop("self", None) + arguments.pop("cls", None) + for param_name, param in signature.parameters.items(): + if param.kind == inspect.Parameter.VAR_KEYWORD: + # Update with the **kwargs, and remove the original entry + # This is to help flatten out keyword arguments + if param_name in arguments: + arguments.update(arguments[param_name]) + arguments.pop(param_name) + + return arguments + + +class PareaExtra(TypedDict): + """Any additional info to be injected into the run dynamically.""" + + reference_example_id: Optional[ID_TYPE] + run_extra: Optional[dict] + run_tree: Optional[RunTree] + project_name: Optional[str] + metadata: Optional[dict[str, Any]] + tags: Optional[list[str]] + run_id: Optional[ID_TYPE] + + +def traceable( + run_type: str, + *, + name: Optional[str] = None, + extra: Optional[dict] = None, + executor: Optional[ThreadPoolExecutor] = None, + metadata: Optional[Mapping[str, Any]] = None, + tags: Optional[list[str]] = None, +) -> Callable: + """Decorator for creating or adding a run to a run tree.""" + extra_outer = extra or {} + + def decorator(func: Callable): + @wraps(func) + async def async_wrapper( + *args: Any, + langsmith_extra: Optional[Union[PareaExtra, dict]] = None, + **kwargs: Any, + ) -> Any: + """Async version of wrapper function""" + outer_project = _PROJECT_NAME.get() or os.environ.get("PAREA_PROJECT", os.environ.get("PAREA_PROJECT", "default")) + langsmith_extra = langsmith_extra or {} + run_tree = langsmith_extra.get("run_tree", kwargs.get("run_tree", None)) + project_name_ = langsmith_extra.get("project_name", outer_project) + run_extra = langsmith_extra.get("run_extra", None) + reference_example_id = langsmith_extra.get("reference_example_id", None) + if run_tree is None: + parent_run_ = _PARENT_RUN_TREE.get() + else: + parent_run_ = run_tree + signature = inspect.signature(func) + name_ = name or func.__name__ + docstring = func.__doc__ + if run_extra: + extra_inner = {**extra_outer, **run_extra} + else: + extra_inner = extra_outer + metadata_ = {**(metadata or {}), **(langsmith_extra.get("metadata") or {})} + if metadata_: + extra_inner["metadata"] = metadata_ + inputs = _get_inputs(signature, *args, **kwargs) + tags_ = (tags or []) + (langsmith_extra.get("tags") or []) + id_ = langsmith_extra.get("run_id", uuid4()) + if parent_run_ is not None: + new_run = parent_run_.create_child( + name=name_, + run_type=run_type, + serialized={ + "name": name, + "signature": str(signature), + "doc": docstring, + }, + inputs=inputs, + tags=tags_, + extra=extra_inner, + run_id=id_, + ) + else: + new_run = RunTree( + id=id_, + name=name_, + serialized={ + "name": name, + "signature": str(signature), + "doc": docstring, + }, + inputs=inputs, + run_type=run_type, + reference_example_id=reference_example_id, + project_name=project_name_, + extra=extra_inner, + tags=tags_, + executor=executor, + client=Client(api_key=os.getenv("DEV_API_KEY")), + ) + new_run.post() + _PROJECT_NAME.set(project_name_) + _PARENT_RUN_TREE.set(new_run) + func_accepts_parent_run = inspect.signature(func).parameters.get("run_tree", None) is not None + try: + if func_accepts_parent_run: + function_result = await func(*args, run_tree=new_run, **kwargs) + else: + function_result = await func(*args, **kwargs) + except Exception as e: + new_run.end(error=str(e)) + new_run.patch() + _PARENT_RUN_TREE.set(parent_run_) + _PROJECT_NAME.set(outer_project) + raise e + _PARENT_RUN_TREE.set(parent_run_) + _PROJECT_NAME.set(outer_project) + if isinstance(function_result, dict): + new_run.end(outputs=function_result) + else: + new_run.end(outputs={"output": function_result}) + new_run.patch() + return function_result + + @wraps(func) + def wrapper( + *args: Any, + langsmith_extra: Optional[Union[PareaExtra, dict]] = None, + **kwargs: Any, + ) -> Any: + """Create a new run or create_child() if run is passed in kwargs.""" + outer_project = _PROJECT_NAME.get() or os.environ.get("PAREA_PROJECT", os.environ.get("PAREA_PROJECT", "default")) + langsmith_extra = langsmith_extra or {} + run_tree = langsmith_extra.get("run_tree", kwargs.get("run_tree", None)) + project_name_ = langsmith_extra.get("project_name", outer_project) + run_extra = langsmith_extra.get("run_extra", None) + reference_example_id = langsmith_extra.get("reference_example_id", None) + if run_tree is None: + parent_run_ = _PARENT_RUN_TREE.get() + else: + parent_run_ = run_tree + signature = inspect.signature(func) + name_ = name or func.__name__ + docstring = func.__doc__ + if run_extra: + extra_inner = {**extra_outer, **run_extra} + else: + extra_inner = extra_outer + metadata_ = {**(metadata or {}), **(langsmith_extra.get("metadata") or {})} + if metadata_: + extra_inner["metadata"] = metadata_ + inputs = _get_inputs(signature, *args, **kwargs) + tags_ = (tags or []) + (langsmith_extra.get("tags") or []) + id_ = langsmith_extra.get("run_id", uuid4()) + if parent_run_ is not None: + new_run = parent_run_.create_child( + name=name_, + run_id=id_, + run_type=run_type, + serialized={ + "name": name, + "signature": str(signature), + "doc": docstring, + }, + inputs=inputs, + tags=tags_, + extra=extra_inner, + ) + else: + new_run = RunTree( + name=name_, + id=id_, + serialized={ + "name": name, + "signature": str(signature), + "doc": docstring, + }, + inputs=inputs, + run_type=run_type, + reference_example_id=reference_example_id, + project_name=project_name_, + extra=extra_inner, + tags=tags_, + executor=executor, + ) + new_run.post() + _PARENT_RUN_TREE.set(new_run) + _PROJECT_NAME.set(project_name_) + func_accepts_parent_run = inspect.signature(func).parameters.get("run_tree", None) is not None + try: + if func_accepts_parent_run: + function_result = func(*args, run_tree=new_run, **kwargs) + else: + function_result = func(*args, **kwargs) + except Exception as e: + new_run.end(error=str(e)) + new_run.patch() + _PARENT_RUN_TREE.set(parent_run_) + _PROJECT_NAME.set(outer_project) + raise e + _PARENT_RUN_TREE.set(parent_run_) + _PROJECT_NAME.set(outer_project) + if isinstance(function_result, dict): + new_run.end(outputs=function_result) + else: + new_run.end(outputs={"output": function_result}) + new_run.patch() + return function_result + + if inspect.iscoroutinefunction(func): + return async_wrapper + else: + return wrapper + + return decorator + + +@contextmanager +def trace( + name: str, + run_type: str, + *, + inputs: Optional[dict] = None, + extra: Optional[dict] = None, + executor: Optional[ThreadPoolExecutor] = None, + project_name: Optional[str] = None, + run_tree: Optional[RunTree] = None, + tags: Optional[list[str]] = None, + metadata: Optional[Mapping[str, Any]] = None, +) -> Generator[RunTree, None, None]: + """Context manager for creating a run tree.""" + extra_outer = extra or {} + if metadata: + extra_outer["metadata"] = metadata + parent_run_ = _PARENT_RUN_TREE.get() if run_tree is None else run_tree + outer_project = _PROJECT_NAME.get() or os.environ.get("PAREA_PROJECT", os.environ.get("PAREA_PROJECT", "default")) + project_name_ = project_name or outer_project + if parent_run_ is not None: + new_run = parent_run_.create_child( + name=name, + run_type=run_type, + extra=extra_outer, + inputs=inputs, + tags=tags, + ) + else: + new_run = RunTree( + name=name, + run_type=run_type, + extra=extra_outer, + executor=executor, + project_name=project_name_, + inputs=inputs or {}, + tags=tags, + ) + new_run.post() + _PARENT_RUN_TREE.set(new_run) + _PROJECT_NAME.set(project_name_) + try: + yield new_run + except Exception as e: + new_run.end(error=str(e)) + new_run.patch() + _PARENT_RUN_TREE.set(parent_run_) + _PROJECT_NAME.set(outer_project) + raise e + _PARENT_RUN_TREE.set(parent_run_) + _PROJECT_NAME.set(outer_project) + if new_run.end_time is None: + # User didn't call end() on the run, so we'll do it for them + new_run.end() + new_run.patch() + + +# import contextvars +# import inspect +# import logging +# import os +# from concurrent.futures import ThreadPoolExecutor +# from contextlib import contextmanager +# from datetime import datetime +# from enum import Enum +# from functools import wraps +# from typing import Any, Callable, Dict, Generator, List, Mapping, Optional, Union, TypedDict +# from uuid import uuid4 +# +# from parea.client_two import ID_TYPE, Client +# from parea.run_trees import RunTree +# +# logger = logging.getLogger(__name__) +# _PARENT_RUN_TREE = contextvars.ContextVar[Optional[RunTree]]("_PARENT_RUN_TREE", default=None) +# _PROJECT_NAME = contextvars.ContextVar[Optional[str]]("_PROJECT_NAME", default=None) +# +# +# def get_run_tree_context() -> Optional[RunTree]: +# """Get the current run tree context.""" +# return _PARENT_RUN_TREE.get() +# +# +# def _get_inputs(signature: inspect.Signature, *args: Any, **kwargs: Any) -> Dict[str, Any]: +# """Return a dictionary of inputs from the function signature.""" +# bound = signature.bind_partial(*args, **kwargs) +# bound.apply_defaults() +# arguments = dict(bound.arguments) +# arguments.pop("self", None) +# arguments.pop("cls", None) +# for param_name, param in signature.parameters.items(): +# if param.kind == inspect.Parameter.VAR_KEYWORD: +# # Update with the **kwargs, and remove the original entry +# # This is to help flatten out keyword arguments +# if param_name in arguments: +# arguments.update(arguments[param_name]) +# arguments.pop(param_name) +# +# return arguments +# +# +# class PareaExtra(TypedDict): +# """Any additional info to be injected into the run dynamically.""" +# +# reference_example_id: Optional[ID_TYPE] +# run_extra: Optional[Dict] +# run_tree: Optional[RunTree] +# project_name: Optional[str] +# metadata: Optional[Dict[str, Any]] +# tags: Optional[List[str]] +# run_id: Optional[ID_TYPE] +# +# +# class RunTypeEnum(str, Enum): +# """Enum for run types.""" +# +# tool = "tool" +# chain = "chain" +# llm = "llm" +# retriever = "retriever" +# embedding = "embedding" +# prompt = "prompt" +# parser = "parser" +# +# +# def _get_outer_project() -> Optional[str]: +# return _PROJECT_NAME.get() or os.environ.get("PAREA_PROJECT", os.environ.get("PAREA_PROJECT", "default")) +# +# +# def _get_project_name(langsmith_extra: Optional[Union[PareaExtra, Dict]], outer_project: Optional[str]) -> Optional[str]: +# return langsmith_extra.get("project_name", outer_project) if langsmith_extra else outer_project +# +# +# def _get_parent_run(run_tree: Optional[RunTree]) -> Optional[RunTree]: +# return _PARENT_RUN_TREE.get() if run_tree is None else run_tree +# +# +# def _get_run_extra(langsmith_extra: Optional[Union[PareaExtra, Dict]], extra_outer: Optional[Dict]) -> Optional[Dict]: +# run_extra = langsmith_extra.get("run_extra", None) if langsmith_extra else None +# if run_extra: +# return {**extra_outer, **run_extra} +# else: +# return extra_outer +# +# +# def _get_metadata(langsmith_extra: Optional[Union[PareaExtra, Dict]], metadata: Optional[Mapping[str, Any]]) -> Optional[Dict[str, Any]]: +# metadata_ = {**(metadata or {}), **(langsmith_extra.get("metadata") or {})} if langsmith_extra else {} +# if metadata_: +# return metadata_ +# return None +# +# +# def _get_tags(langsmith_extra: Optional[Union[PareaExtra, Dict]], tags: Optional[List[str]]) -> Optional[List[str]]: +# return (tags or []) + (langsmith_extra.get("tags") or []) if langsmith_extra else tags +# +# +# def _get_id(langsmith_extra: Optional[Union[PareaExtra, Dict]]) -> str: +# return langsmith_extra.get("run_id", uuid4()) if langsmith_extra else uuid4() +# +# +# def _get_func_accepts_parent_run(func: Callable) -> bool: +# return inspect.signature(func).parameters.get("run_tree", None) is not None +# +# +# async def _get_function_result(func: Callable, new_run: RunTree, func_accepts_parent_run: bool, *args: Any, **kwargs: Any) -> Any: +# if func_accepts_parent_run: +# return await func(*args, run_tree=new_run, **kwargs) +# else: +# return await func(*args, **kwargs) +# +# +# def _end_run(new_run: RunTree, function_result: Any) -> None: +# if isinstance(function_result, dict): +# new_run.end(outputs=function_result) +# else: +# new_run.end(outputs={"output": function_result}) +# +# +# def create_run_tree( +# run_type: RunTypeEnum, +# name: str, +# inputs: Dict[str, Any], +# extra: Optional[Dict] = None, +# tags: Optional[List[str]] = None, +# id_: Optional[str] = None, +# parent_run: Optional[RunTree] = None, +# executor: Optional[ThreadPoolExecutor] = None, +# reference_example_id: Optional[ID_TYPE] = None, +# start_time: Optional[datetime] = None, +# ) -> RunTree: +# """Helper function to create a new run tree or child run.""" +# if parent_run is not None: +# return parent_run.create_child( +# name=name, +# run_type=run_type, +# serialized={"name": name}, +# inputs=inputs, +# tags=tags, +# extra=extra, +# run_id=id_, +# ) +# else: +# return RunTree( +# name=name, +# id=id_, +# serialized={"name": name}, +# inputs=inputs, +# run_type=run_type, +# reference_example_id=reference_example_id, +# start_time=start_time or datetime.utcnow(), +# extra=extra, +# tags=tags, +# executor=executor, +# client=Client(api_key=os.getenv("DEV_API_KEY")), +# ) +# +# +# def traceable( +# run_type: RunTypeEnum, +# *, +# name: Optional[str] = None, +# extra: Optional[Dict] = None, +# executor: Optional[ThreadPoolExecutor] = None, +# metadata: Optional[Mapping[str, Any]] = None, +# tags: Optional[List[str]] = None, +# ) -> Callable: +# """Decorator for creating or adding a run to a run tree.""" +# extra_outer = extra or {} +# +# def decorator(func: Callable): +# @wraps(func) +# async def async_wrapper( +# *args: Any, +# langsmith_extra: Optional[Union[PareaExtra, Dict]] = None, +# **kwargs: Any, +# ) -> Any: +# """Async version of wrapper function""" +# outer_project = _get_outer_project() +# project_name_ = _get_project_name(langsmith_extra, outer_project) +# parent_run_ = _get_parent_run(langsmith_extra.get("run_tree", kwargs.get("run_tree", None)) if langsmith_extra else None) +# signature = inspect.signature(func) +# name_ = name or func.__name__ +# docstring = func.__doc__ +# extra_inner = _get_run_extra(langsmith_extra, extra_outer) +# metadata_ = _get_metadata(langsmith_extra, metadata) +# if metadata_: +# extra_inner["metadata"] = metadata_ +# inputs = _get_inputs(signature, *args, **kwargs) +# tags_ = _get_tags(langsmith_extra, tags) +# id_ = _get_id(langsmith_extra) +# new_run = create_run_tree(run_type, name_, inputs, extra_inner, tags_, id_, parent_run_, project_name_, executor) +# new_run.post() +# _PROJECT_NAME.set(project_name_) +# _PARENT_RUN_TREE.set(new_run) +# func_accepts_parent_run = _get_func_accepts_parent_run(func) +# try: +# function_result = await _get_function_result(func, new_run, func_accepts_parent_run, *args, **kwargs) +# except Exception as e: +# new_run.end(error=str(e)) +# new_run.patch() +# _PARENT_RUN_TREE.set(parent_run_) +# _PROJECT_NAME.set(outer_project) +# raise e +# _PARENT_RUN_TREE.set(parent_run_) +# _PROJECT_NAME.set(outer_project) +# _end_run(new_run, function_result) +# new_run.patch() +# return function_result +# +# return async_wrapper +# +# return decorator +# +# +# @contextmanager +# def trace( +# name: str, +# run_type: RunTypeEnum, +# *, +# inputs: Optional[Dict] = None, +# extra: Optional[Dict] = None, +# executor: Optional[ThreadPoolExecutor] = None, +# project_name: Optional[str] = None, +# run_tree: Optional[RunTree] = None, +# tags: Optional[List[str]] = None, +# metadata: Optional[Mapping[str, Any]] = None, +# ) -> Generator[RunTree, None, None]: +# """Context manager for creating a run tree.""" +# extra_outer = extra or {} +# outer_project = _get_outer_project() +# project_name_ = project_name or outer_project +# parent_run_ = _get_parent_run(run_tree) +# extra_inner = _get_run_extra(None, extra_outer) +# metadata_ = _get_metadata(None, metadata) +# if metadata_: +# extra_inner["metadata"] = metadata_ +# new_run = create_run_tree( +# run_type, name, inputs or {}, extra_inner, tags, str(uuid4()), parent_run_, project_name_, executor +# ) +# new_run.post() +# _PROJECT_NAME.set(project_name_) +# _PARENT_RUN_TREE.set(new_run) +# try: +# yield new_run +# except Exception as e: +# new_run.end(error=str(e)) +# new_run.patch() +# _PARENT_RUN_TREE.set(parent_run_) +# _PROJECT_NAME.set(outer_project) +# raise e +# _PARENT_RUN_TREE.set(parent_run_) +# _PROJECT_NAME.set(outer_project) +# if new_run.end_time is None: +# # User didn't call end() on the run, so we'll do it for them +# new_run.end() +# new_run.patch() diff --git a/parea/trace_utils/run_trees.py b/parea/trace_utils/run_trees.py new file mode 100644 index 00000000..c8cbd0ec --- /dev/null +++ b/parea/trace_utils/run_trees.py @@ -0,0 +1,423 @@ +from typing import Any, Dict, List, Optional, cast + +import logging +import os +from concurrent.futures import Future, ThreadPoolExecutor, wait +from datetime import datetime +from enum import Enum +from uuid import UUID, uuid4 + +from parea.client_two import ID_TYPE, Client, get_runtime_environment + +try: + from pydantic.v1 import BaseModel, Field, PrivateAttr, root_validator, validator # type: ignore[import] +except ImportError: + from pydantic import BaseModel, Field, PrivateAttr, StrictBool, StrictFloat, StrictInt, root_validator, validator + +logger = logging.getLogger(__name__) + + +class RunTypeEnum(str, Enum): + """(Deprecated) Enum for run types. Use string directly.""" + + tool = "tool" + chain = "chain" + llm = "llm" + retriever = "retriever" + embedding = "embedding" + prompt = "prompt" + parser = "parser" + + +class RunBase(BaseModel): + """Base Run schema.""" + + id: UUID + name: str + start_time: datetime + run_type: str + """The type of run, such as tool, chain, llm, retriever, + embedding, prompt, parser.""" + end_time: Optional[datetime] = None + extra: Optional[dict] = None + error: Optional[str] = None + serialized: Optional[dict] + events: Optional[list[dict]] = None + inputs: dict + outputs: Optional[dict] = None + reference_example_id: Optional[UUID] = None + parent_run_id: Optional[UUID] = None + tags: Optional[list[str]] = None + + +class Run(RunBase): + """Run schema when loading from the DB.""" + + execution_order: int + """The execution order of the run within a run trace.""" + session_id: Optional[UUID] = None + """The project ID this run belongs to.""" + child_run_ids: Optional[list[UUID]] = None + """The child run IDs of this run.""" + child_runs: Optional[list["Run"]] = None + """The child runs of this run, if instructed to load using the client + These are not populated by default, as it is a heavier query to make.""" + feedback_stats: Optional[dict[str, Any]] = None + """Feedback stats for this run.""" + app_path: Optional[str] = None + """Relative URL path of this run within the app.""" + _host_url: Optional[str] = PrivateAttr(default=None) + + def __init__(self, _host_url: Optional[str] = None, **kwargs: Any) -> None: + """Initialize a Run object.""" + super().__init__(**kwargs) + self._host_url = _host_url + + @property + def url(self) -> Optional[str]: + """URL of this run within the app.""" + if self._host_url and self.app_path: + return f"{self._host_url}{self.app_path}" + return None + + +def _make_thread_pool() -> ThreadPoolExecutor: + """Ensure a thread pool exists in the current context.""" + return ThreadPoolExecutor(max_workers=1) + + +class RunTree(RunBase): + """Run Schema with back-references for posting runs.""" + + name: str + id: UUID = Field(default_factory=uuid4) + start_time: datetime = Field(default_factory=datetime.utcnow) + parent_run: Optional["RunTree"] = Field(default=None, exclude=True) + child_runs: list["RunTree"] = Field( + default_factory=list, + exclude={"__all__": {"parent_run_id"}}, + ) + session_name: str = Field( + default_factory=lambda: os.environ.get( + # TODO: Deprecate PAREA_SESSION + "PAREA_PROJECT", + os.environ.get("PAREA_SESSION", "default"), + ), + alias="project_name", + ) + session_id: Optional[UUID] = Field(default=None, alias="project_id") + execution_order: int = 1 + child_execution_order: int = Field(default=1, exclude=True) + extra: dict = Field(default_factory=dict) + client: Client = Field(default_factory=Client, exclude=True) + executor: ThreadPoolExecutor = Field(default_factory=_make_thread_pool, exclude=True) + _futures: list[Future] = PrivateAttr(default_factory=list) + + class Config: + arbitrary_types_allowed = True + allow_population_by_field_name = True + + @validator("executor", pre=True) + def validate_executor(cls, v: Optional[ThreadPoolExecutor]) -> ThreadPoolExecutor: + """Ensure the executor is running.""" + if v is None: + return _make_thread_pool() + if v._shutdown: + raise ValueError("Executor has been shutdown.") + return v + + @root_validator(pre=True) + def infer_defaults(cls, values: dict) -> dict: + """Assign name to the run.""" + if "serialized" not in values: + values["serialized"] = {"name": values["name"]} + if "execution_order" not in values: + values["execution_order"] = 1 + if "child_execution_order" not in values: + values["child_execution_order"] = values["execution_order"] + if values.get("parent_run") is not None: + values["parent_run_id"] = values["parent_run"].id + extra = cast(dict, values.setdefault("extra", {})) + runtime = cast(dict, extra.setdefault("runtime", {})) + runtime.update(get_runtime_environment()) + return values + + def end( + self, + *, + outputs: Optional[dict] = None, + error: Optional[str] = None, + end_time: Optional[datetime] = None, + ) -> None: + """Set the end time of the run and all child runs.""" + self.end_time = end_time or datetime.utcnow() + if outputs is not None: + self.outputs = outputs + if error is not None: + self.error = error + if self.parent_run: + self.parent_run.child_execution_order = max( + self.parent_run.child_execution_order, + self.child_execution_order, + ) + + def create_child( + self, + name: str, + run_type: str, + *, + run_id: Optional[ID_TYPE] = None, + serialized: Optional[dict] = None, + inputs: Optional[dict] = None, + outputs: Optional[dict] = None, + error: Optional[str] = None, + reference_example_id: Optional[UUID] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, + tags: Optional[list[str]] = None, + extra: Optional[dict] = None, + ) -> "RunTree": + """Add a child run to the run tree.""" + execution_order = self.child_execution_order + 1 + serialized_ = serialized or {"name": name} + run = RunTree( + name=name, + id=run_id or uuid4(), + serialized=serialized_, + inputs=inputs or {}, + outputs=outputs or {}, + error=error, + run_type=run_type, + reference_example_id=reference_example_id, + start_time=start_time or datetime.utcnow(), + end_time=end_time, + execution_order=execution_order, + child_execution_order=execution_order, + extra=extra or {}, + parent_run=self, + session_name=self.session_name, + client=self.client, + executor=self.executor, + tags=tags, + ) + self.child_runs.append(run) + return run + + def post(self, exclude_child_runs: bool = True) -> Future: + """Post the run tree to the API asynchronously.""" + exclude = {"child_runs"} if exclude_child_runs else None + kwargs = self.dict(exclude=exclude, exclude_none=True) + self._futures.append( + self.executor.submit( + self.client.create_run, + **kwargs, + ) + ) + return self._futures[-1] + + def patch(self) -> Future: + """Patch the run tree to the API in a background thread.""" + self._futures.append( + self.executor.submit( + self.client.update_run, + run_id=self.id, + outputs=self.outputs.copy() if self.outputs else None, + error=self.error, + parent_run_id=self.parent_run_id, + reference_example_id=self.reference_example_id, + ) + ) + return self._futures[-1] + + def wait(self) -> None: + """Wait for all _futures to complete.""" + futures = self._futures + wait(self._futures) + for future in futures: + self._futures.remove(future) + + +# import logging +# import os +# from concurrent.futures import Future, ThreadPoolExecutor, as_completed +# from dataclasses import dataclass, field +# from datetime import datetime +# from enum import Enum +# from functools import lru_cache +# from typing import Dict, List, Optional, Any +# from uuid import uuid4 +# +# from parea.client_two import Client, get_runtime_environment, ID_TYPE +# +# logger = logging.getLogger(__name__) +# +# # Using Enum for run types. It prevents invalid values and improves code readability. +# class RunTypeEnum(str, Enum): +# tool = "tool" +# chain = "chain" +# llm = "llm" +# retriever = "retriever" +# embedding = "embedding" +# prompt = "prompt" +# parser = "parser" +# +# +# @dataclass +# class RunBase: +# """Base Run schema.""" +# +# id: str +# name: str +# start_time: datetime +# run_type: RunTypeEnum +# end_time: Optional[datetime] = None +# extra: Optional[dict] = None +# error: Optional[str] = None +# serialized: Optional[dict] = None +# events: Optional[List[Dict]] = None +# inputs: dict = field(default_factory=dict) +# outputs: Optional[dict] = None +# reference_example_id: Optional[str] = None +# parent_run_id: Optional[str] = None +# tags: Optional[List[str]] = None +# +# +# @dataclass +# class Run(RunBase): +# """Run schema when loading from the DB.""" +# +# execution_order: Optional[int] = None +# session_id: Optional[str] = None +# child_run_ids: Optional[List[str]] = None +# child_runs: Optional[List["Run"]] = None +# feedback_stats: Optional[Dict[str, Any]] = None +# app_path: Optional[str] = None +# _host_url: Optional[str] = None +# +# @property +# def url(self) -> Optional[str]: +# """URL of this run within the app.""" +# if self._host_url and self.app_path: +# return f"{self._host_url}{self.app_path}" +# return None +# +# +# @lru_cache +# def _make_thread_pool() -> ThreadPoolExecutor: +# """Ensure a thread pool exists in the current context.""" +# return ThreadPoolExecutor(max_workers=1) +# +# +# @dataclass +# class RunTree(RunBase): +# """Run Schema with back-references for posting runs.""" +# +# parent_run: Optional["RunTree"] = None +# child_runs: List["RunTree"] = field(default_factory=list) +# session_name: str = field(default_factory=lambda: os.environ.get("PAREA_PROJECT", os.environ.get("PAREA_SESSION", "default"))) +# session_id: Optional[str] = None +# execution_order: int = 1 +# child_execution_order: int = 1 +# extra: Dict = field(default_factory=dict) +# client: Client = field(default_factory=Client) +# executor: ThreadPoolExecutor = field(default_factory=_make_thread_pool) +# _futures: List[Future] = field(default_factory=list) +# +# def __post_init__(self): +# """Assign name to the run.""" +# if self.serialized is None: +# self.serialized = {"name": self.name} +# if self.extra is None: +# self.extra = {} +# runtime = self.extra.setdefault("runtime", {}) +# runtime.update(get_runtime_environment()) +# +# def end( +# self, +# *, +# outputs: Optional[Dict] = None, +# error: Optional[str] = None, +# end_time: Optional[datetime] = None, +# ) -> None: +# """Set the end time of the run and all child runs.""" +# self.end_time = end_time or datetime.utcnow() +# if outputs is not None: +# self.outputs = outputs +# if error is not None: +# self.error = error +# if self.parent_run: +# self.parent_run.child_execution_order = max( +# self.parent_run.child_execution_order, +# self.child_execution_order, +# ) +# +# def create_child( +# self, +# name: str, +# run_type: RunTypeEnum, +# *, +# run_id: Optional[ID_TYPE] = None, +# serialized: Optional[Dict] = None, +# inputs: Optional[Dict] = None, +# outputs: Optional[Dict] = None, +# error: Optional[str] = None, +# reference_example_id: Optional[str] = None, +# start_time: Optional[datetime] = None, +# end_time: Optional[datetime] = None, +# tags: Optional[List[str]] = None, +# extra: Optional[Dict] = None, +# ) -> "RunTree": +# """Add a child run to the run tree.""" +# execution_order = self.child_execution_order + 1 +# serialized_ = serialized or {"name": name} +# run = RunTree( +# name=name, +# id=run_id or str(uuid4()), +# serialized=serialized_, +# inputs=inputs or {}, +# outputs=outputs or {}, +# error=error, +# run_type=run_type, +# reference_example_id=reference_example_id, +# start_time=start_time or datetime.utcnow(), +# end_time=end_time, +# execution_order=execution_order, +# child_execution_order=execution_order, +# extra=extra or {}, +# parent_run=self, +# session_name=self.session_name, +# client=self.client, +# executor=self.executor, +# tags=tags, +# ) +# self.child_runs.append(run) +# return run +# +# def post(self, exclude_child_runs: bool = True) -> Future: +# """Post the run tree to the API asynchronously.""" +# self._futures.append( +# self.executor.submit( +# self.client.create_run, +# **self.__dict__, +# ) +# ) +# return self._futures[-1] +# +# def patch(self) -> Future: +# """Patch the run tree to the API in a background thread.""" +# self._futures.append( +# self.executor.submit( +# self.client.update_run, +# run_id=self.id, +# outputs=self.outputs, +# error=self.error, +# parent_run_id=self.parent_run_id, +# reference_example_id=self.reference_example_id, +# ) +# ) +# return self._futures[-1] +# +# def wait(self) -> None: +# """Wait for all _futures to complete.""" +# for future in as_completed(self._futures): +# self._futures.remove(future) diff --git a/parea/trace_utils/trace.py b/parea/trace_utils/trace.py new file mode 100644 index 00000000..436427c9 --- /dev/null +++ b/parea/trace_utils/trace.py @@ -0,0 +1,201 @@ +from typing import Any, Dict, List, Optional + +import asyncio +import contextvars +import inspect +import json +import logging +import threading +import time +from collections import ChainMap +from datetime import datetime +from functools import wraps +from uuid import uuid4 + +from attrs import asdict + +from parea.parea_logger import parea_logger +from parea.schemas.models import CompletionResponse, TraceLog + +logger = logging.getLogger() + + +# Context variable to maintain the current trace context stack +trace_context = contextvars.ContextVar("trace_context", default=[]) + +# A dictionary to hold trace data for each trace +trace_data = contextvars.ContextVar("trace_data", default={}) + + +def to_date_and_time_string(timestamp: float) -> str: + return datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S %Z").strip() + + +def merge(old, new): + if isinstance(old, dict) and isinstance(new, dict): + return dict(ChainMap(new, old)) + if isinstance(old, list) and isinstance(new, list): + return old + new + return new + + +def trace_insert(data: dict[str, Any]): + current_trace_id = trace_context.get()[-1] + current_trace_data: TraceLog = trace_data.get()[current_trace_id] + + for key, new_value in data.items(): + print(key, new_value) + existing_value = current_trace_data.__getattribute__(key) + current_trace_data.__setattr__(key, merge(existing_value, new_value) if existing_value else new_value) + + +def traceable( + name: Optional[str] = None, + tags: Optional[list[str]] = None, + metadata: Optional[dict[str, Any]] = None, + target: Optional[str] = None, + end_user_identifier: Optional[str] = None, +): + def init_trace(func_name, args, kwargs, func): + start_time = time.time() + trace_id = str(uuid4()) + trace_context.get().append(trace_id) + + sig = inspect.signature(func) + parameters = sig.parameters + + inputs = {k: v for k, v in zip(parameters.keys(), args)} + inputs.update(kwargs) + + trace_data.get()[trace_id] = TraceLog( + trace_id=trace_id, + start_timestamp=to_date_and_time_string(start_time), + trace_name=name or func_name, + end_user_identifier=end_user_identifier, + metadata=metadata, + target=target, + tags=tags, + inputs=inputs, + ) + parent_trace_id = trace_context.get()[-2] if len(trace_context.get()) > 1 else None + if parent_trace_id: + trace_data.get()[parent_trace_id].children.append(trace_id) + + return trace_id + + def cleanup_trace(trace_id): + logging_thread = threading.Thread( + target=parea_logger.record_log, + kwargs={"data": trace_data.get()[trace_id]}, + ) + logging_thread.start() + trace_context.get().pop() + + def decorator(func): + @wraps(func) + async def async_wrapper(*args, **kwargs): + trace_id = init_trace(func.__name__, args, kwargs, func) + try: + result = await func(*args, **kwargs) + end_time = time.time() + trace_data.get()[trace_id].end_timestamp = to_date_and_time_string(end_time) + output = asdict(result) if isinstance(result, CompletionResponse) else result + trace_data.get()[trace_id].output = json.dumps(output) + except Exception as e: + logger.exception(f"Error occurred in function {func.__name__}") + raise e + finally: + cleanup_trace(trace_id) + return result + + @wraps(func) + def wrapper(*args, **kwargs): + trace_id = init_trace(func.__name__, args, kwargs, func) + try: + result = func(*args, **kwargs) + end_time = time.time() + trace_data.get()[trace_id].end_timestamp = to_date_and_time_string(end_time) + output = asdict(result) if isinstance(result, CompletionResponse) else result + trace_data.get()[trace_id].output = json.dumps(output) + except Exception as e: + logger.exception(f"Error occurred in function {func.__name__}") + raise e + finally: + cleanup_trace(trace_id) + return result + + if inspect.iscoroutinefunction(func): + return async_wrapper + else: + return wrapper + + if callable(name): + func = name + name = None + return decorator(func) + + return decorator + + +@traceable +def run_child1(x): + return 1 + x + + +@traceable +def run_child2(y): + return run_grand_child1(y) + y + + +@traceable +def run_grand_child1(z): + # Add metadata to the trace data for this function + trace_insert({"metadata": {"internal": True, "tokens": 3}}) + return 3 * z + + +@traceable +def parent(x, y): + answer1 = run_child1(x) + answer2 = run_child2(y) + return (answer1 + answer2) / 2 + + +@traceable +def parent2(x, y): + return (x + y) / 2 + + +@traceable +async def arun_child1(x): + await asyncio.sleep(1) # simulate IO-bound operation + return 1 + x + + +@traceable +async def arun_child2(y): + res = await arun_grand_child1(y) + return res + y + + +@traceable +async def arun_grand_child1(z): + await asyncio.sleep(1) # simulate IO-bound operation + current_trace_id = trace_context.get()[-1] + trace_data.get()[current_trace_id]["metadata"] = { + "internal": True, + "tokens": 3, + } + return 3 * z + + +@traceable +async def aparent(x, y): + answer1 = await arun_child1(x) + answer2 = await arun_child2(y) + return (answer1 + answer2) / 2 + + +@traceable +async def aparent2(x, y): + return (x + y) / 2 diff --git a/poetry.lock b/poetry.lock index 9a7c3d4d..1e9d6090 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,138 @@ # This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +[[package]] +name = "aiohttp" +version = "3.8.5" +description = "Async http client/server framework (asyncio)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "aiohttp-3.8.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a94159871304770da4dd371f4291b20cac04e8c94f11bdea1c3478e557fbe0d8"}, + {file = "aiohttp-3.8.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:13bf85afc99ce6f9ee3567b04501f18f9f8dbbb2ea11ed1a2e079670403a7c84"}, + {file = "aiohttp-3.8.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ce2ac5708501afc4847221a521f7e4b245abf5178cf5ddae9d5b3856ddb2f3a"}, + {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96943e5dcc37a6529d18766597c491798b7eb7a61d48878611298afc1fca946c"}, + {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ad5c3c4590bb3cc28b4382f031f3783f25ec223557124c68754a2231d989e2b"}, + {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c413c633d0512df4dc7fd2373ec06cc6a815b7b6d6c2f208ada7e9e93a5061d"}, + {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df72ac063b97837a80d80dec8d54c241af059cc9bb42c4de68bd5b61ceb37caa"}, + {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c48c5c0271149cfe467c0ff8eb941279fd6e3f65c9a388c984e0e6cf57538e14"}, + {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:368a42363c4d70ab52c2c6420a57f190ed3dfaca6a1b19afda8165ee16416a82"}, + {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7607ec3ce4993464368505888af5beb446845a014bc676d349efec0e05085905"}, + {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0d21c684808288a98914e5aaf2a7c6a3179d4df11d249799c32d1808e79503b5"}, + {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:312fcfbacc7880a8da0ae8b6abc6cc7d752e9caa0051a53d217a650b25e9a691"}, + {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ad093e823df03bb3fd37e7dec9d4670c34f9e24aeace76808fc20a507cace825"}, + {file = "aiohttp-3.8.5-cp310-cp310-win32.whl", hash = "sha256:33279701c04351a2914e1100b62b2a7fdb9a25995c4a104259f9a5ead7ed4802"}, + {file = "aiohttp-3.8.5-cp310-cp310-win_amd64.whl", hash = "sha256:6e4a280e4b975a2e7745573e3fc9c9ba0d1194a3738ce1cbaa80626cc9b4f4df"}, + {file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae871a964e1987a943d83d6709d20ec6103ca1eaf52f7e0d36ee1b5bebb8b9b9"}, + {file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:461908b2578955045efde733719d62f2b649c404189a09a632d245b445c9c975"}, + {file = "aiohttp-3.8.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:72a860c215e26192379f57cae5ab12b168b75db8271f111019509a1196dfc780"}, + {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc14be025665dba6202b6a71cfcdb53210cc498e50068bc088076624471f8bb9"}, + {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8af740fc2711ad85f1a5c034a435782fbd5b5f8314c9a3ef071424a8158d7f6b"}, + {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:841cd8233cbd2111a0ef0a522ce016357c5e3aff8a8ce92bcfa14cef890d698f"}, + {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed1c46fb119f1b59304b5ec89f834f07124cd23ae5b74288e364477641060ff"}, + {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84f8ae3e09a34f35c18fa57f015cc394bd1389bce02503fb30c394d04ee6b938"}, + {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62360cb771707cb70a6fd114b9871d20d7dd2163a0feafe43fd115cfe4fe845e"}, + {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:23fb25a9f0a1ca1f24c0a371523546366bb642397c94ab45ad3aedf2941cec6a"}, + {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0ba0d15164eae3d878260d4c4df859bbdc6466e9e6689c344a13334f988bb53"}, + {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5d20003b635fc6ae3f96d7260281dfaf1894fc3aa24d1888a9b2628e97c241e5"}, + {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0175d745d9e85c40dcc51c8f88c74bfbaef9e7afeeeb9d03c37977270303064c"}, + {file = "aiohttp-3.8.5-cp311-cp311-win32.whl", hash = "sha256:2e1b1e51b0774408f091d268648e3d57f7260c1682e7d3a63cb00d22d71bb945"}, + {file = "aiohttp-3.8.5-cp311-cp311-win_amd64.whl", hash = "sha256:043d2299f6dfdc92f0ac5e995dfc56668e1587cea7f9aa9d8a78a1b6554e5755"}, + {file = "aiohttp-3.8.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cae533195e8122584ec87531d6df000ad07737eaa3c81209e85c928854d2195c"}, + {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f21e83f355643c345177a5d1d8079f9f28b5133bcd154193b799d380331d5d3"}, + {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a75ef35f2df54ad55dbf4b73fe1da96f370e51b10c91f08b19603c64004acc"}, + {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e2e9839e14dd5308ee773c97115f1e0a1cb1d75cbeeee9f33824fa5144c7634"}, + {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44e65da1de4403d0576473e2344828ef9c4c6244d65cf4b75549bb46d40b8dd"}, + {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d847e4cde6ecc19125ccbc9bfac4a7ab37c234dd88fbb3c5c524e8e14da543"}, + {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:c7a815258e5895d8900aec4454f38dca9aed71085f227537208057853f9d13f2"}, + {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:8b929b9bd7cd7c3939f8bcfffa92fae7480bd1aa425279d51a89327d600c704d"}, + {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:5db3a5b833764280ed7618393832e0853e40f3d3e9aa128ac0ba0f8278d08649"}, + {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:a0215ce6041d501f3155dc219712bc41252d0ab76474615b9700d63d4d9292af"}, + {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:fd1ed388ea7fbed22c4968dd64bab0198de60750a25fe8c0c9d4bef5abe13824"}, + {file = "aiohttp-3.8.5-cp36-cp36m-win32.whl", hash = "sha256:6e6783bcc45f397fdebc118d772103d751b54cddf5b60fbcc958382d7dd64f3e"}, + {file = "aiohttp-3.8.5-cp36-cp36m-win_amd64.whl", hash = "sha256:b5411d82cddd212644cf9360879eb5080f0d5f7d809d03262c50dad02f01421a"}, + {file = "aiohttp-3.8.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:01d4c0c874aa4ddfb8098e85d10b5e875a70adc63db91f1ae65a4b04d3344cda"}, + {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5980a746d547a6ba173fd5ee85ce9077e72d118758db05d229044b469d9029a"}, + {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a482e6da906d5e6e653be079b29bc173a48e381600161c9932d89dfae5942ef"}, + {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80bd372b8d0715c66c974cf57fe363621a02f359f1ec81cba97366948c7fc873"}, + {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1161b345c0a444ebcf46bf0a740ba5dcf50612fd3d0528883fdc0eff578006a"}, + {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd56db019015b6acfaaf92e1ac40eb8434847d9bf88b4be4efe5bfd260aee692"}, + {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:153c2549f6c004d2754cc60603d4668899c9895b8a89397444a9c4efa282aaf4"}, + {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4a01951fabc4ce26ab791da5f3f24dca6d9a6f24121746eb19756416ff2d881b"}, + {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bfb9162dcf01f615462b995a516ba03e769de0789de1cadc0f916265c257e5d8"}, + {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:7dde0009408969a43b04c16cbbe252c4f5ef4574ac226bc8815cd7342d2028b6"}, + {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4149d34c32f9638f38f544b3977a4c24052042affa895352d3636fa8bffd030a"}, + {file = "aiohttp-3.8.5-cp37-cp37m-win32.whl", hash = "sha256:68c5a82c8779bdfc6367c967a4a1b2aa52cd3595388bf5961a62158ee8a59e22"}, + {file = "aiohttp-3.8.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2cf57fb50be5f52bda004b8893e63b48530ed9f0d6c96c84620dc92fe3cd9b9d"}, + {file = "aiohttp-3.8.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:eca4bf3734c541dc4f374ad6010a68ff6c6748f00451707f39857f429ca36ced"}, + {file = "aiohttp-3.8.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1274477e4c71ce8cfe6c1ec2f806d57c015ebf84d83373676036e256bc55d690"}, + {file = "aiohttp-3.8.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28c543e54710d6158fc6f439296c7865b29e0b616629767e685a7185fab4a6b9"}, + {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:910bec0c49637d213f5d9877105d26e0c4a4de2f8b1b29405ff37e9fc0ad52b8"}, + {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5443910d662db951b2e58eb70b0fbe6b6e2ae613477129a5805d0b66c54b6cb7"}, + {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e460be6978fc24e3df83193dc0cc4de46c9909ed92dd47d349a452ef49325b7"}, + {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb1558def481d84f03b45888473fc5a1f35747b5f334ef4e7a571bc0dfcb11f8"}, + {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34dd0c107799dcbbf7d48b53be761a013c0adf5571bf50c4ecad5643fe9cfcd0"}, + {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aa1990247f02a54185dc0dff92a6904521172a22664c863a03ff64c42f9b5410"}, + {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0e584a10f204a617d71d359fe383406305a4b595b333721fa50b867b4a0a1548"}, + {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:a3cf433f127efa43fee6b90ea4c6edf6c4a17109d1d037d1a52abec84d8f2e42"}, + {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c11f5b099adafb18e65c2c997d57108b5bbeaa9eeee64a84302c0978b1ec948b"}, + {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:84de26ddf621d7ac4c975dbea4c945860e08cccde492269db4e1538a6a6f3c35"}, + {file = "aiohttp-3.8.5-cp38-cp38-win32.whl", hash = "sha256:ab88bafedc57dd0aab55fa728ea10c1911f7e4d8b43e1d838a1739f33712921c"}, + {file = "aiohttp-3.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:5798a9aad1879f626589f3df0f8b79b3608a92e9beab10e5fda02c8a2c60db2e"}, + {file = "aiohttp-3.8.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a6ce61195c6a19c785df04e71a4537e29eaa2c50fe745b732aa937c0c77169f3"}, + {file = "aiohttp-3.8.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:773dd01706d4db536335fcfae6ea2440a70ceb03dd3e7378f3e815b03c97ab51"}, + {file = "aiohttp-3.8.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f83a552443a526ea38d064588613aca983d0ee0038801bc93c0c916428310c28"}, + {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f7372f7341fcc16f57b2caded43e81ddd18df53320b6f9f042acad41f8e049a"}, + {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea353162f249c8097ea63c2169dd1aa55de1e8fecbe63412a9bc50816e87b761"}, + {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d47ae48db0b2dcf70bc8a3bc72b3de86e2a590fc299fdbbb15af320d2659de"}, + {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d827176898a2b0b09694fbd1088c7a31836d1a505c243811c87ae53a3f6273c1"}, + {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3562b06567c06439d8b447037bb655ef69786c590b1de86c7ab81efe1c9c15d8"}, + {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4e874cbf8caf8959d2adf572a78bba17cb0e9d7e51bb83d86a3697b686a0ab4d"}, + {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6809a00deaf3810e38c628e9a33271892f815b853605a936e2e9e5129762356c"}, + {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:33776e945d89b29251b33a7e7d006ce86447b2cfd66db5e5ded4e5cd0340585c"}, + {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eaeed7abfb5d64c539e2db173f63631455f1196c37d9d8d873fc316470dfbacd"}, + {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e91d635961bec2d8f19dfeb41a539eb94bd073f075ca6dae6c8dc0ee89ad6f91"}, + {file = "aiohttp-3.8.5-cp39-cp39-win32.whl", hash = "sha256:00ad4b6f185ec67f3e6562e8a1d2b69660be43070bd0ef6fcec5211154c7df67"}, + {file = "aiohttp-3.8.5-cp39-cp39-win_amd64.whl", hash = "sha256:c0a9034379a37ae42dea7ac1e048352d96286626251862e448933c0f59cbd79c"}, + {file = "aiohttp-3.8.5.tar.gz", hash = "sha256:b9552ec52cc147dbf1944ac7ac98af7602e51ea2dcd076ed194ca3c0d1c7d0bc"}, +] + +[package.dependencies] +aiosignal = ">=1.1.2" +async-timeout = ">=4.0.0a3,<5.0" +attrs = ">=17.3.0" +charset-normalizer = ">=2.0,<4.0" +frozenlist = ">=1.1.1" +multidict = ">=4.5,<7.0" +yarl = ">=1.0,<2.0" + +[package.extras] +speedups = ["Brotli", "aiodns", "cchardet"] + +[[package]] +name = "aiosignal" +version = "1.3.1" +description = "aiosignal: a list of registered asynchronous callbacks" +optional = false +python-versions = ">=3.7" +files = [ + {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, + {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, +] + +[package.dependencies] +frozenlist = ">=1.1.0" + +[[package]] +name = "annotated-types" +version = "0.5.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.7" +files = [ + {file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"}, + {file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"}, +] + [[package]] name = "anyio" version = "3.7.1" @@ -153,6 +286,17 @@ files = [ [package.dependencies] typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} +[[package]] +name = "async-timeout" +version = "4.0.3" +description = "Timeout context manager for asyncio programs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, + {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, +] + [[package]] name = "attrs" version = "23.1.0" @@ -965,6 +1109,76 @@ files = [ {file = "fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f"}, ] +[[package]] +name = "frozenlist" +version = "1.4.0" +description = "A list-like structure which implements collections.abc.MutableSequence" +optional = false +python-versions = ">=3.8" +files = [ + {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab"}, + {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559"}, + {file = "frozenlist-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62"}, + {file = "frozenlist-1.4.0-cp310-cp310-win32.whl", hash = "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0"}, + {file = "frozenlist-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956"}, + {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95"}, + {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3"}, + {file = "frozenlist-1.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb"}, + {file = "frozenlist-1.4.0-cp311-cp311-win32.whl", hash = "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431"}, + {file = "frozenlist-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1"}, + {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3"}, + {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503"}, + {file = "frozenlist-1.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8"}, + {file = "frozenlist-1.4.0-cp38-cp38-win32.whl", hash = "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc"}, + {file = "frozenlist-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7"}, + {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf"}, + {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963"}, + {file = "frozenlist-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3"}, + {file = "frozenlist-1.4.0-cp39-cp39-win32.whl", hash = "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f"}, + {file = "frozenlist-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167"}, + {file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"}, +] + [[package]] name = "gitdb" version = "4.0.10" @@ -1984,6 +2198,89 @@ files = [ {file = "msgpack-1.0.5.tar.gz", hash = "sha256:c075544284eadc5cddc70f4757331d99dcbc16b2bbd4849d15f8aae4cf36d31c"}, ] +[[package]] +name = "multidict" +version = "6.0.4" +description = "multidict implementation" +optional = false +python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, + {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, + {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, + {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, + {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, + {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, + {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, + {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, + {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, + {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, + {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, + {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, + {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, +] + [[package]] name = "mypy" version = "1.5.1" @@ -2187,6 +2484,28 @@ jupyter-server = ">=1.8,<3" [package.extras] test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync"] +[[package]] +name = "openai" +version = "0.27.8" +description = "Python client library for the OpenAI API" +optional = false +python-versions = ">=3.7.1" +files = [ + {file = "openai-0.27.8-py3-none-any.whl", hash = "sha256:e0a7c2f7da26bdbe5354b03c6d4b82a2f34bd4458c7a17ae1a7092c3e397e03c"}, + {file = "openai-0.27.8.tar.gz", hash = "sha256:2483095c7db1eee274cebac79e315a986c4e55207bb4fa7b82d185b3a2ed9536"}, +] + +[package.dependencies] +aiohttp = "*" +requests = ">=2.20" +tqdm = "*" + +[package.extras] +datalib = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] +dev = ["black (>=21.6b0,<22.0)", "pytest (==6.*)", "pytest-asyncio", "pytest-mock"] +embeddings = ["matplotlib", "numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "plotly", "scikit-learn (>=1.0.2)", "scipy", "tenacity (>=8.0.1)"] +wandb = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "wandb"] + [[package]] name = "overrides" version = "7.4.0" @@ -2526,6 +2845,143 @@ files = [ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] +[[package]] +name = "pydantic" +version = "2.2.1" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic-2.2.1-py3-none-any.whl", hash = "sha256:0c88bd2b63ed7a5109c75ab180d55f58f80a4b559682406812d0684d3f4b9192"}, + {file = "pydantic-2.2.1.tar.gz", hash = "sha256:31b5cada74b2320999fb2577e6df80332a200ff92e7775a52448b6b036fce24a"}, +] + +[package.dependencies] +annotated-types = ">=0.4.0" +pydantic-core = "2.6.1" +typing-extensions = ">=4.6.1" + +[package.extras] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.6.1" +description = "" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic_core-2.6.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:f55001a689111a297c0006c46c0589cfd559261baaa9a37bc35eff05b8cae1a6"}, + {file = "pydantic_core-2.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bb6273068e9450c5c91f58dd277fbd406b896ffa30f0ef312edc5519d07f16ae"}, + {file = "pydantic_core-2.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:043212f21c75cb6ee3a92fffbc747410e32b08e1a419ce16a9da98a16d660a7c"}, + {file = "pydantic_core-2.6.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:db0c12f1e9d3bf658634621f3423486803d749fef77a64cfb4252f9d619e1817"}, + {file = "pydantic_core-2.6.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:81424dc05c4342a19fb64323bb9d4468e7407b745c00377ccc4d3dd96d5e02fe"}, + {file = "pydantic_core-2.6.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3c8f3aebaf92f088b1dafd7101d1ccca0459ae0f5b26017411b9969667d289a9"}, + {file = "pydantic_core-2.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd9f14454b4bc89c705ce17951f9c783db82efd2b44a424487c593e2269eef61"}, + {file = "pydantic_core-2.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2effc71653247e76c5b95d15c58d4ca3f591f42f714eb3b32df9d6ec613794a5"}, + {file = "pydantic_core-2.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:56672429f8a89d2a0f4402d912f0dad68c2d05f7c278d3152c6fb4a76c2a429a"}, + {file = "pydantic_core-2.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d0bf1c2545ab253732229c7fe8294d98eb08f99aa25a388267e1bc4d2d7e0a34"}, + {file = "pydantic_core-2.6.1-cp310-none-win32.whl", hash = "sha256:c5be947ad41a7602f941dc834d03e64dd1c7fae65fa85cb4f1004a95c5d50df1"}, + {file = "pydantic_core-2.6.1-cp310-none-win_amd64.whl", hash = "sha256:3d14ae98a8d251402ef8ed017039d2fc3e29fb155f909cd3816ba259fd30fb48"}, + {file = "pydantic_core-2.6.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:4a3c20808d3ced90e29439f72a563eadf21d29560935cc818b2dab80b92c114a"}, + {file = "pydantic_core-2.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:da240bbd8191edc6009e7793d5d4d67c55f56225c4788f068d6286c20e5a2038"}, + {file = "pydantic_core-2.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de1a3e56e34264d5216c67d2a48185216ada8f5f35a7f4c96a3971847c0de897"}, + {file = "pydantic_core-2.6.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9b623e09239ed333d14c02c9fcd1a7bb350b95eca8383f6e9b0d8e373d5a14b5"}, + {file = "pydantic_core-2.6.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a12520a6d502a25f6e47319874e47056b290f1b3c2ed9391444ce81c8cc5b83"}, + {file = "pydantic_core-2.6.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1141f18414aee8865c7917ae1432e419c1983272f53625152493692ff3d6783"}, + {file = "pydantic_core-2.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7888b3ee7566865cff3e9edab5d6cdf2e7cf793df17fe53d5e7be3e57eae45ec"}, + {file = "pydantic_core-2.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3bdf293b6304bc451678b7016c2505b7d97aa85ff13dac4420027b1b69e15d3d"}, + {file = "pydantic_core-2.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7ef56a05bb60336d5e795bf166d6712b2362e6478522c77e8336cb0da8909913"}, + {file = "pydantic_core-2.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3210eb73707e3487c16ef25cfd1663660f4e7d647a181d6c2fb18bc6167985fb"}, + {file = "pydantic_core-2.6.1-cp311-none-win32.whl", hash = "sha256:707e3005e8c129bdac117285b71717c13b9ed81a81eae0b1642f4ddc60028e63"}, + {file = "pydantic_core-2.6.1-cp311-none-win_amd64.whl", hash = "sha256:2b8ccec2189d8a8b83929f79e5bc00c0656f6c2ba4345125c0c82d1b77e15a26"}, + {file = "pydantic_core-2.6.1-cp311-none-win_arm64.whl", hash = "sha256:c1e44b77442fb5b1b6fccea30e3359b14d0a2e5896801243defe54482a591500"}, + {file = "pydantic_core-2.6.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:c82fb25f965f6777032fc2f2856c86149f7709c8f7fd0c020a8631b8211f2bab"}, + {file = "pydantic_core-2.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:494b211b12b8fedd184dbba609f6ed582e23561db57c1996fd6773989dbaef9b"}, + {file = "pydantic_core-2.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1281c940f47e5c89b594ef7580045647df1f9ad687edd503bcc0485be94576f4"}, + {file = "pydantic_core-2.6.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2d41701c88d8b678c16c10562949f2d28aceacd767cbe51dac9c8c41e6e609fb"}, + {file = "pydantic_core-2.6.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6a839c95d5cc91eed053d8dafde4e200c4bc82f56fb1cf7bbfaeb03e2d907929"}, + {file = "pydantic_core-2.6.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c22e4fbfb5823d0fcb2c20ed164b39c3588554f9635f70765e8c9cff0fef67ad"}, + {file = "pydantic_core-2.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2fed4ad60ccf2698bd04e95dfc3bd84149ced9605a29fd27d624701e1da300c"}, + {file = "pydantic_core-2.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33b9343aa464d60c31937b361abde08d3af9943f3eb09d3216211b6236bd40c4"}, + {file = "pydantic_core-2.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:56e4953cd911293d6d755e2a97c651826aca76201db8f1ee298939e703721390"}, + {file = "pydantic_core-2.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cd163109047ab41ef1ea34258b35beb3ccac90af2012927ee8ab6ff122fef671"}, + {file = "pydantic_core-2.6.1-cp312-none-win32.whl", hash = "sha256:f5b51ec04743c94288c46e3759769611ab7c5ce0f941113363da96d20d345fb6"}, + {file = "pydantic_core-2.6.1-cp312-none-win_amd64.whl", hash = "sha256:ca5606bd82e255b1d704a4334e5ebf05ae966b69686fae02dcd31c057bdcb113"}, + {file = "pydantic_core-2.6.1-cp312-none-win_arm64.whl", hash = "sha256:dfc8f534a21b60b00f87e5a4fc36b8b8945160a6cc9e7b6e67db541c766c9597"}, + {file = "pydantic_core-2.6.1-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:b1aed20778092f8334c8eaf91550fa2805221d5e9b40ebdd1f46ee7efc159a48"}, + {file = "pydantic_core-2.6.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:64ff7a4b7ee2a56735af28da76c5dacbba6995801080f739d14610f4aa3de35d"}, + {file = "pydantic_core-2.6.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2d8faedb138c704957642fdf154c94f1b3d2a15cbd2472e45665f80463e85ee"}, + {file = "pydantic_core-2.6.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:55aac69d7339a63e37164f0a629c3034becc6746d68d126118a3ee4493514bed"}, + {file = "pydantic_core-2.6.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dfdb1617af455a551be4cc0471f0bf3bfb1e882db71afad0e587c821326bb749"}, + {file = "pydantic_core-2.6.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aadc84f5bd7b1421b5a6b389ceff46062dd4a58c44cfb75990e9ca2d9d8270df"}, + {file = "pydantic_core-2.6.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1a01dce87507b9a8f1b71933ade85c573a22c9bd4649590e28d8a497afb68bd"}, + {file = "pydantic_core-2.6.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cd6f05f3e237ed6b3949464e7679e55843645fe0fe8d3b33277c321386836f6a"}, + {file = "pydantic_core-2.6.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:760f8a0aeb43ceeff1e536859e071a72e91075d4d37d51470812c4f49e682702"}, + {file = "pydantic_core-2.6.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a1ad48e77935d7dbbc2d75aeb638abbfbd0df0cfacf774dbe98d52271468f00c"}, + {file = "pydantic_core-2.6.1-cp37-none-win32.whl", hash = "sha256:153a5dd24c09ab7544beda967366afbaae8350b327a4ebd5807ed45ec791baa0"}, + {file = "pydantic_core-2.6.1-cp37-none-win_amd64.whl", hash = "sha256:cc7fc3e81b4ea6bce7e0e1d9797f496e957c5e66adf483f89afdce2d81d19986"}, + {file = "pydantic_core-2.6.1-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:5482d692ae37857695feccb179022728b275b7bfcc1c85bcdf7b556e76bffcd8"}, + {file = "pydantic_core-2.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:45d248c3c5c5c23a8d048cfdebc8151ae7b32a6dc6d68fbca995521e54692207"}, + {file = "pydantic_core-2.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6dd6c9f47e26779bf1f7da4d6ccd60f66973e63b0a143438f1e20bae296c3fde"}, + {file = "pydantic_core-2.6.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:55701608e60418a423db2486b5c64d790f86eb78a11b9077efb6302c50e62564"}, + {file = "pydantic_core-2.6.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:420a76a62dd20a6ef08445abf7cf04dcd8a845a5bb15932c2e88a8e518c70d43"}, + {file = "pydantic_core-2.6.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5f253d20314e53ba0fb2b95541b6ed23f44fbcd927fe7674de341545c3327c3d"}, + {file = "pydantic_core-2.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5127b811c6a26deb85f5b17a06c26c28ce204e51e0a963b75bdf8612b22546d"}, + {file = "pydantic_core-2.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:51ffa985b874ca7d0dc199bb75c67b77907379291c91532a9e2d981f7b681527"}, + {file = "pydantic_core-2.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4902300e763a2fcc49ae14366493ef1fdbd3c7128b9acf37aef505f671aa681f"}, + {file = "pydantic_core-2.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e1c69334bb843c9bff98f52a1fa6c06420081a561fcecb03c6b9376960bd7de2"}, + {file = "pydantic_core-2.6.1-cp38-none-win32.whl", hash = "sha256:e84812b1ca989b2e9f4913d7b75ae0eece2a90154de35b4c5411ad640bfd387c"}, + {file = "pydantic_core-2.6.1-cp38-none-win_amd64.whl", hash = "sha256:775098e3629a959dfec8444667a53e0916839e9fbf6b55e07d6e2aadde006400"}, + {file = "pydantic_core-2.6.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:a32ed5a794918a61bf77b967c197eb78f31ad4e3145860193dc381bde040717e"}, + {file = "pydantic_core-2.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:66eda8ac48ac33e9e5c6541c8e30c702924b70a6f2e9732b74230d9b2dd35fb6"}, + {file = "pydantic_core-2.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb5131d75d69b0547ef9a8f46f7b94857411c9badcdd5092de61a3b4943f08c7"}, + {file = "pydantic_core-2.6.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:20e850f3242d7836a5e15453f798d8569b9754350c8e184ba32d102c515dd507"}, + {file = "pydantic_core-2.6.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f4327fa6a1ac3da62b27d43bb0f27657ed4e601b141ecbfcf8523814b6c33b6"}, + {file = "pydantic_core-2.6.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c7b89b2875b967ad5c3c980bf72773851554f80c2529796e815a10c99295d872"}, + {file = "pydantic_core-2.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78eadd8d7d5cd8c3616e363c394d721437c339feaa4c28404e2eda79add69781"}, + {file = "pydantic_core-2.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17ab25bb24e98b61d120b7248c2b49ea56ce754a050d6b348be42015fcb7aa25"}, + {file = "pydantic_core-2.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6ea8dd2854fe6cee5ea0d60304ee7877dffe487cf118f221e85029269dd1235d"}, + {file = "pydantic_core-2.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9bf3ba6b4878ee692f6e24230801f682807fd97356bc2064f630fc0a2ad2ead6"}, + {file = "pydantic_core-2.6.1-cp39-none-win32.whl", hash = "sha256:b974d65692333931b4c7f730e7a3135ff854a1e5384bc260de3327ea364c835a"}, + {file = "pydantic_core-2.6.1-cp39-none-win_amd64.whl", hash = "sha256:f34f26d8a5f1a45366189ec30a57f43b21e2172d0d3b62822638dd885cc8eaab"}, + {file = "pydantic_core-2.6.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:f7ec4c6edafa3f0eb1aa461e31ea263736cc541b2459dddfbda7085b30844801"}, + {file = "pydantic_core-2.6.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:3679b9a1f41eb1b699e9556f91281d78c416cdc59ae90d5733fbe2017f1effe9"}, + {file = "pydantic_core-2.6.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ff36f945342086ee917d4219dd0e59660a2dfcdb86a07696c2791f5d59c07d"}, + {file = "pydantic_core-2.6.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:734864605d722a6f8db3b9c96371710f7cb591fbfca40cfeaedf5b67df282438"}, + {file = "pydantic_core-2.6.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7188359b95a2b1aef5744a2ee6af2d9cfc733dd823f8840f4c896129477a172b"}, + {file = "pydantic_core-2.6.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:382d40843ae759d43ef65b67dec713390f9417135c1dd730afbf03cf2f450f45"}, + {file = "pydantic_core-2.6.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:4525b8498d362e4e324e3e175239b364768f52bd3563ac4ef9750160f5789de8"}, + {file = "pydantic_core-2.6.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e55514a022c768cccf07a675d20d07b847980dcd9250f6b516a86bab5612fc01"}, + {file = "pydantic_core-2.6.1-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:34734d486d059f0f6f5bfa9ba4a41449f666e2abbde002e9fa8b050bc50e3347"}, + {file = "pydantic_core-2.6.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a809498dceb0cd1cd1e57a2bfdc70ea82f424776e0196f4d63c4b6fcdaeb5aab"}, + {file = "pydantic_core-2.6.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:588a5ffd8bbf1b2230611ed1b45221adcf05b981037b2f853b5f20465849b5c1"}, + {file = "pydantic_core-2.6.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:26b81017aeae0d96f776fbce34a3a763d26ac575d8ad3f1202bdfdd2b935954b"}, + {file = "pydantic_core-2.6.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7ddaa2c3c66682f0ff4ebc8c85ef2d8305f32deba79416464c47c93d94ca3740"}, + {file = "pydantic_core-2.6.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d6971131de66d1a37293f2e032206b6984b0dec44f568b453dfe89a84a2de0cc"}, + {file = "pydantic_core-2.6.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:200704f6824f8014bdccb1ce57cbd328666e6de4ecd77f0b8ab472cdea9c49ce"}, + {file = "pydantic_core-2.6.1-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:6916b27072c957947919fb32551f08486562bb8616f2e3db9e4e9c1d83d36886"}, + {file = "pydantic_core-2.6.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:136de286abf53f326b90389aaaca8a8050c2570adfc74afe06ab1c35d5d242bf"}, + {file = "pydantic_core-2.6.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60a238bb4ab09a81a6b25c9a0bb12756cfab2d9f3a7a471f857a179f83da0df6"}, + {file = "pydantic_core-2.6.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2034d9b83a59b3b74b9dbf97ddb99de86c08863c1c33aabf80bc95791c7d50c3"}, + {file = "pydantic_core-2.6.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7c3a2b4d1636446dc71da1e949d2cf9ac1ee691ca63a640b77fce0360b4b75be"}, + {file = "pydantic_core-2.6.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:09e4ebd11a0b333b1fca75c1004c76dc9719f3aaf83ae38c42358754d8a76148"}, + {file = "pydantic_core-2.6.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:a4536d132a8bbd05bf368fb802a264cb9828f6c85e4029a6a3670bc98ba97323"}, + {file = "pydantic_core-2.6.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:6221c97d6d58f2370650cfe3d81408901a1951c99960e1df9f6f9f8482d73d08"}, + {file = "pydantic_core-2.6.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4223e8bdad41d846a84cda400cd538e1cdc63d98eb4d41951396bfdb88fd8ce9"}, + {file = "pydantic_core-2.6.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c07cdb2e02733e5f26b9b004a1a8b99814d175f8953fa9f59e4293de2b8e9787"}, + {file = "pydantic_core-2.6.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8714e958d01342d08e520ffec6c1acf66cdec83ce51302f9a1a6efb2f784d0b6"}, + {file = "pydantic_core-2.6.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f03541c25a77fb5445055e070b69d292c9818a9195ffbfd3962c0ad0da983e8"}, + {file = "pydantic_core-2.6.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:364c13ef48c9e2f8c2ea8ee0da5ea23db5e218f99e796cbf360a2a7cab511439"}, + {file = "pydantic_core-2.6.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:27ba58bbfd1b2b9da45bfe524e680e2bc747a1ca9738ee5aa18d8cbdcc08e5e6"}, + {file = "pydantic_core-2.6.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:92321582e59da185b76b2eca4488ea95e41800672e57107509d32ebf8ad550f8"}, + {file = "pydantic_core-2.6.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2da1d21a4f2675d5b8a749674993a65c0537e2066e7ab7b1a4a54ef0b3ac8efd"}, + {file = "pydantic_core-2.6.1.tar.gz", hash = "sha256:5b4efa68bcfa6f2b93624c6660b6cf4b7b4336d4225afb314254a0ed9c9f4153"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + [[package]] name = "pydocstyle" version = "6.3.0" @@ -3397,17 +3853,17 @@ win32 = ["pywin32"] [[package]] name = "setuptools" -version = "68.1.0" +version = "68.1.2" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-68.1.0-py3-none-any.whl", hash = "sha256:e13e1b0bc760e9b0127eda042845999b2f913e12437046e663b833aa96d89715"}, - {file = "setuptools-68.1.0.tar.gz", hash = "sha256:d59c97e7b774979a5ccb96388efc9eb65518004537e85d52e81eaee89ab6dd91"}, + {file = "setuptools-68.1.2-py3-none-any.whl", hash = "sha256:3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b"}, + {file = "setuptools-68.1.2.tar.gz", hash = "sha256:3d4dfa6d95f1b101d695a6160a7626e15583af71a5f52176efa5d39a054d475d"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5,<=7.1.2)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] @@ -3601,6 +4057,26 @@ files = [ {file = "tornado-6.3.3.tar.gz", hash = "sha256:e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe"}, ] +[[package]] +name = "tqdm" +version = "4.66.1" +description = "Fast, Extensible Progress Meter" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"}, + {file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[package.extras] +dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] +notebook = ["ipywidgets (>=6)"] +slack = ["slack-sdk"] +telegram = ["requests"] + [[package]] name = "traitlets" version = "5.9.0" @@ -3920,6 +4396,93 @@ files = [ [package.dependencies] cffi = ">=1.0" +[[package]] +name = "yarl" +version = "1.9.2" +description = "Yet another URL library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, + {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, + {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, + {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, + {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, + {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, + {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, + {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, + {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, + {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, + {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, + {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, + {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" + [[package]] name = "zipp" version = "3.16.2" @@ -3938,4 +4501,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "d43b7ecf531579cf4bb4802196642b89655fcada52235c4c318147d0c6b03ec7" +content-hash = "6b26260643c21e6a64a1bbb0609ebcd42ac75e7b45d6fe6131209275613b205b" diff --git a/pyproject.toml b/pyproject.toml index 6ce621b8..e5367935 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,7 @@ python-dotenv = "^1.0.0" poetry-plugin-dotenv = "^0.5.1" pyupgrade = "^3.9.0" jupyter = "^1.0.0" +pydantic = "^2.2.1" [tool.poetry.dev-dependencies] bandit = "^1.7.1" @@ -57,6 +58,8 @@ coverage = "^7.2.7" coverage-badge = "^1.1.0" pytest-html = "^3.1.1" pytest-cov = "^4.1.0" +pydantic = "^2.2.1" +openai = "^0.27.8" [tool.black] # https://github.com/psf/black diff --git a/requirements.txt b/requirements.txt index bcad6b87..23ae643f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,146 @@ -attrs -httpx -python-dotenv +This package has been deprecated and is no longer maintained, `poetry-dotenv` has moved to `poetry-plugin-dotenv` (https://pypi.org/project/poetry-plugin-dotenv) +annotated-types==0.5.0 ; python_version >= "3.9" and python_version < "4.0" +anyio==3.7.1 ; python_version >= "3.9" and python_version < "4.0" +appnope==0.1.3 ; python_version >= "3.9" and python_version < "4.0" and (platform_system == "Darwin" or sys_platform == "darwin") +argon2-cffi-bindings==21.2.0 ; python_version >= "3.9" and python_version < "4.0" +argon2-cffi==23.1.0 ; python_version >= "3.9" and python_version < "4.0" +arrow==1.2.3 ; python_version >= "3.9" and python_version < "4.0" +asttokens==2.2.1 ; python_version >= "3.9" and python_version < "4.0" +async-lru==2.0.4 ; python_version >= "3.9" and python_version < "4.0" +attrs==23.1.0 ; python_version >= "3.9" and python_version < "4.0" +babel==2.12.1 ; python_version >= "3.9" and python_version < "4.0" +backcall==0.2.0 ; python_version >= "3.9" and python_version < "4.0" +beautifulsoup4==4.12.2 ; python_version >= "3.9" and python_version < "4.0" +bleach==6.0.0 ; python_version >= "3.9" and python_version < "4.0" +build==0.10.0 ; python_version >= "3.9" and python_version < "4.0" +cachecontrol[filecache]==0.12.14 ; python_version >= "3.9" and python_version < "4.0" +certifi==2023.7.22 ; python_version >= "3.9" and python_version < "4.0" +cffi==1.15.1 ; python_version >= "3.9" and python_version < "4.0" +charset-normalizer==3.2.0 ; python_version >= "3.9" and python_version < "4.0" +cleo==2.0.1 ; python_version >= "3.9" and python_version < "4.0" +colorama==0.4.6 ; python_version >= "3.9" and python_version < "4.0" and (os_name == "nt" or sys_platform == "win32") +comm==0.1.4 ; python_version >= "3.9" and python_version < "4.0" +crashtest==0.4.1 ; python_version >= "3.9" and python_version < "4.0" +cryptography==41.0.3 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "linux" +debugpy==1.6.7.post1 ; python_version >= "3.9" and python_version < "4.0" +decorator==5.1.1 ; python_version >= "3.9" and python_version < "4.0" +defusedxml==0.7.1 ; python_version >= "3.9" and python_version < "4.0" +distlib==0.3.7 ; python_version >= "3.9" and python_version < "4.0" +dulwich==0.21.5 ; python_version >= "3.9" and python_version < "4.0" +exceptiongroup==1.1.3 ; python_version >= "3.9" and python_version < "3.11" +executing==1.2.0 ; python_version >= "3.9" and python_version < "4.0" +fastjsonschema==2.18.0 ; python_version >= "3.9" and python_version < "4.0" +filelock==3.12.2 ; python_version >= "3.9" and python_version < "4.0" +fqdn==1.5.1 ; python_version >= "3.9" and python_version < "4" +h11==0.14.0 ; python_version >= "3.9" and python_version < "4.0" +html5lib==1.1 ; python_version >= "3.9" and python_version < "4.0" +httpcore==0.17.3 ; python_version >= "3.9" and python_version < "4.0" +httpx==0.24.1 ; python_version >= "3.9" and python_version < "4.0" +idna==3.4 ; python_version >= "3.9" and python_version < "4.0" +importlib-metadata==6.8.0 ; python_version >= "3.9" and python_version < "3.12" +installer==0.7.0 ; python_version >= "3.9" and python_version < "4.0" +ipykernel==6.25.1 ; python_version >= "3.9" and python_version < "4.0" +ipython-genutils==0.2.0 ; python_version >= "3.9" and python_version < "4.0" +ipython==8.14.0 ; python_version >= "3.9" and python_version < "4.0" +ipywidgets==8.1.0 ; python_version >= "3.9" and python_version < "4.0" +isoduration==20.11.0 ; python_version >= "3.9" and python_version < "4.0" +jaraco-classes==3.3.0 ; python_version >= "3.9" and python_version < "4.0" +jedi==0.19.0 ; python_version >= "3.9" and python_version < "4.0" +jeepney==0.8.0 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "linux" +jinja2==3.1.2 ; python_version >= "3.9" and python_version < "4.0" +json5==0.9.14 ; python_version >= "3.9" and python_version < "4.0" +jsonpointer==2.4 ; python_version >= "3.9" and python_version < "4.0" +jsonschema-specifications==2023.7.1 ; python_version >= "3.9" and python_version < "4.0" +jsonschema==4.19.0 ; python_version >= "3.9" and python_version < "4.0" +jsonschema[format-nongpl]==4.19.0 ; python_version >= "3.9" and python_version < "4.0" +jupyter-client==8.3.0 ; python_version >= "3.9" and python_version < "4.0" +jupyter-console==6.6.3 ; python_version >= "3.9" and python_version < "4.0" +jupyter-core==5.3.1 ; python_version >= "3.9" and python_version < "4.0" +jupyter-events==0.7.0 ; python_version >= "3.9" and python_version < "4.0" +jupyter-lsp==2.2.0 ; python_version >= "3.9" and python_version < "4.0" +jupyter-server-terminals==0.4.4 ; python_version >= "3.9" and python_version < "4.0" +jupyter-server==2.7.2 ; python_version >= "3.9" and python_version < "4.0" +jupyter==1.0.0 ; python_version >= "3.9" and python_version < "4.0" +jupyterlab-pygments==0.2.2 ; python_version >= "3.9" and python_version < "4.0" +jupyterlab-server==2.24.0 ; python_version >= "3.9" and python_version < "4.0" +jupyterlab-widgets==3.0.8 ; python_version >= "3.9" and python_version < "4.0" +jupyterlab==4.0.5 ; python_version >= "3.9" and python_version < "4.0" +keyring==23.13.1 ; python_version >= "3.9" and python_version < "4.0" +lockfile==0.12.2 ; python_version >= "3.9" and python_version < "4.0" +markupsafe==2.1.3 ; python_version >= "3.9" and python_version < "4.0" +matplotlib-inline==0.1.6 ; python_version >= "3.9" and python_version < "4.0" +mistune==3.0.1 ; python_version >= "3.9" and python_version < "4.0" +more-itertools==10.1.0 ; python_version >= "3.9" and python_version < "4.0" +msgpack==1.0.5 ; python_version >= "3.9" and python_version < "4.0" +nbclient==0.8.0 ; python_version >= "3.9" and python_version < "4.0" +nbconvert==7.7.4 ; python_version >= "3.9" and python_version < "4.0" +nbformat==5.9.2 ; python_version >= "3.9" and python_version < "4.0" +nest-asyncio==1.5.7 ; python_version >= "3.9" and python_version < "4.0" +notebook-shim==0.2.3 ; python_version >= "3.9" and python_version < "4.0" +notebook==7.0.2 ; python_version >= "3.9" and python_version < "4.0" +overrides==7.4.0 ; python_version >= "3.9" and python_version < "4.0" +packaging==23.0 ; python_version >= "3.9" and python_version < "4.0" +pandocfilters==1.5.0 ; python_version >= "3.9" and python_version < "4.0" +parso==0.8.3 ; python_version >= "3.9" and python_version < "4.0" +pexpect==4.8.0 ; python_version >= "3.9" and python_version < "4.0" +pickleshare==0.7.5 ; python_version >= "3.9" and python_version < "4.0" +pkginfo==1.9.6 ; python_version >= "3.9" and python_version < "4.0" +platformdirs==3.10.0 ; python_version >= "3.9" and python_version < "4.0" +poetry-core==1.6.1 ; python_version >= "3.9" and python_version < "4.0" +poetry-plugin-dotenv==0.5.2 ; python_version >= "3.9" and python_version < "4.0" +poetry-plugin-export==1.4.0 ; python_version >= "3.9" and python_version < "4.0" +poetry==1.5.1 ; python_version >= "3.9" and python_version < "4.0" +prometheus-client==0.17.1 ; python_version >= "3.9" and python_version < "4.0" +prompt-toolkit==3.0.39 ; python_version >= "3.9" and python_version < "4.0" +psutil==5.9.5 ; python_version >= "3.9" and python_version < "4.0" +ptyprocess==0.7.0 ; python_version >= "3.9" and python_version < "4.0" +pure-eval==0.2.2 ; python_version >= "3.9" and python_version < "4.0" +pycparser==2.21 ; python_version >= "3.9" and python_version < "4.0" +pydantic-core==2.6.1 ; python_version >= "3.9" and python_version < "4.0" +pydantic==2.2.1 ; python_version >= "3.9" and python_version < "4.0" +pygments==2.16.1 ; python_version >= "3.9" and python_version < "4.0" +pyproject-hooks==1.0.0 ; python_version >= "3.9" and python_version < "4.0" +python-dateutil==2.8.2 ; python_version >= "3.9" and python_version < "4.0" +python-dotenv==1.0.0 ; python_version >= "3.9" and python_version < "4.0" +python-json-logger==2.0.7 ; python_version >= "3.9" and python_version < "4.0" +pyupgrade==3.10.1 ; python_version >= "3.9" and python_version < "4.0" +pywin32-ctypes==0.2.2 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "win32" +pywin32==306 ; sys_platform == "win32" and platform_python_implementation != "PyPy" and python_version >= "3.9" and python_version < "4.0" +pywinpty==2.0.11 ; python_version >= "3.9" and python_version < "4.0" and os_name == "nt" +pyyaml==6.0.1 ; python_version >= "3.9" and python_version < "4.0" +pyzmq==25.1.1 ; python_version >= "3.9" and python_version < "4.0" +qtconsole==5.4.3 ; python_version >= "3.9" and python_version < "4.0" +qtpy==2.3.1 ; python_version >= "3.9" and python_version < "4.0" +rapidfuzz==2.15.1 ; python_version >= "3.9" and python_version < "4.0" +referencing==0.30.2 ; python_version >= "3.9" and python_version < "4.0" +requests-toolbelt==1.0.0 ; python_version >= "3.9" and python_version < "4.0" +requests==2.31.0 ; python_version >= "3.9" and python_version < "4.0" +rfc3339-validator==0.1.4 ; python_version >= "3.9" and python_version < "4.0" +rfc3986-validator==0.1.1 ; python_version >= "3.9" and python_version < "4.0" +rpds-py==0.9.2 ; python_version >= "3.9" and python_version < "4.0" +secretstorage==3.3.3 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "linux" +send2trash==1.8.2 ; python_version >= "3.9" and python_version < "4.0" +shellingham==1.5.3 ; python_version >= "3.9" and python_version < "4.0" +six==1.16.0 ; python_version >= "3.9" and python_version < "4.0" +sniffio==1.3.0 ; python_version >= "3.9" and python_version < "4.0" +soupsieve==2.4.1 ; python_version >= "3.9" and python_version < "4.0" +stack-data==0.6.2 ; python_version >= "3.9" and python_version < "4.0" +terminado==0.17.1 ; python_version >= "3.9" and python_version < "4.0" +tinycss2==1.2.1 ; python_version >= "3.9" and python_version < "4.0" +tokenize-rt==5.2.0 ; python_version >= "3.9" and python_version < "4.0" +tomli==2.0.1 ; python_version >= "3.9" and python_version < "3.11" +tomlkit==0.12.1 ; python_version >= "3.9" and python_version < "4.0" +tornado==6.3.3 ; python_version >= "3.9" and python_version < "4.0" +traitlets==5.9.0 ; python_version >= "3.9" and python_version < "4.0" +trove-classifiers==2023.8.7 ; python_version >= "3.9" and python_version < "4.0" +typing-extensions==4.7.1 ; python_version >= "3.9" and python_version < "4.0" +uri-template==1.3.0 ; python_version >= "3.9" and python_version < "4.0" +urllib3==1.26.16 ; python_version >= "3.9" and python_version < "4.0" +virtualenv==20.24.3 ; python_version >= "3.9" and python_version < "4.0" +wcwidth==0.2.6 ; python_version >= "3.9" and python_version < "4.0" +webcolors==1.13 ; python_version >= "3.9" and python_version < "4.0" +webencodings==0.5.1 ; python_version >= "3.9" and python_version < "4.0" +websocket-client==1.6.1 ; python_version >= "3.9" and python_version < "4.0" +widgetsnbextension==4.0.8 ; python_version >= "3.9" and python_version < "4.0" +xattr==0.10.1 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "darwin" +zipp==3.16.2 ; python_version >= "3.9" and python_version < "3.12" From 44f681daf23d3dbc0ba95d5ff94639a042672d80 Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Wed, 23 Aug 2023 18:54:38 -0700 Subject: [PATCH 02/15] close WIP --- parea/example.py | 96 +++++++++++++++++++++++++++++++------- parea/schemas/models.py | 4 +- parea/trace_utils/trace.py | 68 +-------------------------- 3 files changed, 82 insertions(+), 86 deletions(-) diff --git a/parea/example.py b/parea/example.py index 65a82c36..abd45685 100644 --- a/parea/example.py +++ b/parea/example.py @@ -1,3 +1,4 @@ +import asyncio import os from datetime import datetime @@ -5,7 +6,7 @@ from parea.client import Parea from parea.schemas.models import Completion, CompletionResponse, UseDeployedPrompt, UseDeployedPromptResponse -from parea.trace_utils.trace import traceable +from parea.trace_utils.trace import trace_insert, traceable load_dotenv() @@ -44,6 +45,78 @@ def main(llm_inputs, metadata): # return f"Hello {name}!" +@traceable +def run_child1(x): + return 1 + x + + +@traceable +def run_child2(y): + return run_grand_child1(y) + y + + +@traceable +def run_grand_child1(z): + # Add metadata to the trace data for this function + trace_insert({"metadata": {"internal": True, "tokens": 3}}) + return 3 * z + + +@traceable +def parent(x, y): + answer1 = run_child1(x) + answer2 = run_child2(y) + return (answer1 + answer2) / 2 + + +@traceable +def parent2(x, y): + return (x + y) / 2 + + +@traceable +async def arun_child1(x): + await asyncio.sleep(1) # simulate IO-bound operation + return 1 + x + + +@traceable +async def arun_child2(y): + res = await arun_grand_child1(y) + return res + y + + +@traceable +async def arun_grand_child1(z): + await asyncio.sleep(1) # simulate IO-bound operation + trace_insert({"metadata": {"internal": True, "tokens": 3}}) + return 3 * z + + +@traceable +async def aparent(x, y): + answer1 = await arun_child1(x) + answer2 = await arun_child2(y) + return (answer1 + answer2) / 2 + + +@traceable +async def aparent2(x, y): + return (x + y) / 2 + + +def retester_main(): + parent(6, 2) + parent(3, 4) + parent2(3, 12) + + +async def atester_main(): + await aparent(6, 2) + await aparent(3, 4) + await aparent2(3, 12) + + @traceable def argument_generator(query: str, additional_description: str = "") -> str: return p.completion( @@ -92,19 +165,8 @@ def argument_chain(query: str, additional_description: str = "") -> str: if __name__ == "__main__": - result = argument_chain( - "Whether sunshine is good for you.", - additional_description="Provide a concise, few sentence argument on why sunshine is good for you.", - ) - - -# if __name__ == "__main__": -# # Assuming your deployed prompt's message is: -# # {"role": "user", "content": "Write a hello world program using {{x}} and the {{y}} framework."} -# llm_inputs = {"x": "Golang", "y": "Fiber"} -# metadata= {"purpose": "testing"} -# completion_response, deployed_prompt = main(llm_inputs, metadata) -# print(completion_response) -# # print("\n\n") -# # print(deployed_prompt) -# # asyncio.run(main_async()) + # result = argument_chain( + # "Whether sunshine is good for you.", + # additional_description="Provide a concise, few sentence argument on why sunshine is good for you.", + # ) + retester_main() diff --git a/parea/schemas/models.py b/parea/schemas/models.py index d2d7eeb2..ade3d084 100644 --- a/parea/schemas/models.py +++ b/parea/schemas/models.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Optional, Union +from typing import Any, Optional, Union from enum import Enum @@ -137,7 +137,7 @@ class TraceLog: # metrics filled from either decorator or completion end_timestamp: Optional[str] = None end_user_identifier: Optional[str] = None - metadata: Optional[dict[str, str]] = None + metadata: Optional[dict[str, Any]] = None target: Optional[str] = None tags: Optional[list[str]] = None inputs: Optional[dict[str, str]] = None diff --git a/parea/trace_utils/trace.py b/parea/trace_utils/trace.py index 436427c9..0b686e7d 100644 --- a/parea/trace_utils/trace.py +++ b/parea/trace_utils/trace.py @@ -1,6 +1,5 @@ -from typing import Any, Dict, List, Optional +from typing import Any, Optional -import asyncio import contextvars import inspect import json @@ -44,7 +43,6 @@ def trace_insert(data: dict[str, Any]): current_trace_data: TraceLog = trace_data.get()[current_trace_id] for key, new_value in data.items(): - print(key, new_value) existing_value = current_trace_data.__getattribute__(key) current_trace_data.__setattr__(key, merge(existing_value, new_value) if existing_value else new_value) @@ -135,67 +133,3 @@ def wrapper(*args, **kwargs): return decorator(func) return decorator - - -@traceable -def run_child1(x): - return 1 + x - - -@traceable -def run_child2(y): - return run_grand_child1(y) + y - - -@traceable -def run_grand_child1(z): - # Add metadata to the trace data for this function - trace_insert({"metadata": {"internal": True, "tokens": 3}}) - return 3 * z - - -@traceable -def parent(x, y): - answer1 = run_child1(x) - answer2 = run_child2(y) - return (answer1 + answer2) / 2 - - -@traceable -def parent2(x, y): - return (x + y) / 2 - - -@traceable -async def arun_child1(x): - await asyncio.sleep(1) # simulate IO-bound operation - return 1 + x - - -@traceable -async def arun_child2(y): - res = await arun_grand_child1(y) - return res + y - - -@traceable -async def arun_grand_child1(z): - await asyncio.sleep(1) # simulate IO-bound operation - current_trace_id = trace_context.get()[-1] - trace_data.get()[current_trace_id]["metadata"] = { - "internal": True, - "tokens": 3, - } - return 3 * z - - -@traceable -async def aparent(x, y): - answer1 = await arun_child1(x) - answer2 = await arun_child2(y) - return (answer1 + answer2) / 2 - - -@traceable -async def aparent2(x, y): - return (x + y) / 2 From d90d21b4cb1b876945c0add3051d23b19e751895 Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Wed, 23 Aug 2023 22:15:37 -0700 Subject: [PATCH 03/15] done, needs clean up --- parea/example.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/parea/example.py b/parea/example.py index abd45685..56ab786c 100644 --- a/parea/example.py +++ b/parea/example.py @@ -137,6 +137,10 @@ def critic(argument: str) -> str: Completion( deployment_id="p-_4w8th0eJlWAx9g8g20Ov", llm_inputs={"argument": argument}, + end_user_identifier="user_1", + metadata={"githash": "e38f04c83"}, + tags=["tutorial"], + target="you're right, i give up", ) ).content @@ -165,8 +169,8 @@ def argument_chain(query: str, additional_description: str = "") -> str: if __name__ == "__main__": - # result = argument_chain( - # "Whether sunshine is good for you.", - # additional_description="Provide a concise, few sentence argument on why sunshine is good for you.", - # ) - retester_main() + result = argument_chain( + "Whether sunshine is good for you.", + additional_description="Provide a concise, few sentence argument on why sunshine is good for you.", + ) + # retester_main() From 99ce85bb76db2782a4bd52472155e086a436348b Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Thu, 24 Aug 2023 13:43:18 -0700 Subject: [PATCH 04/15] using trace --- parea/api_client.py | 2 +- parea/client.py | 25 +- parea/client_two.py | 1212 ----------------- parea/cookbook/example2.py | 307 ----- parea/cookbook/tracing_with_parea_sdk.py | 73 +- parea/example.py | 176 --- parea/parea_logger.py | 1 - parea/trace_utils/log_tree.py | 52 - parea/trace_utils/run_helpers.py | 563 -------- parea/trace_utils/run_trees.py | 423 ------ parea/{trace_utils => utils}/__init__.py | 0 .../trace.py => utils/trace_utils.py} | 8 +- 12 files changed, 56 insertions(+), 2786 deletions(-) delete mode 100644 parea/client_two.py delete mode 100644 parea/cookbook/example2.py delete mode 100644 parea/example.py delete mode 100644 parea/trace_utils/log_tree.py delete mode 100644 parea/trace_utils/run_helpers.py delete mode 100644 parea/trace_utils/run_trees.py rename parea/{trace_utils => utils}/__init__.py (100%) rename parea/{trace_utils/trace.py => utils/trace_utils.py} (97%) diff --git a/parea/api_client.py b/parea/api_client.py index 2af1ac70..1546a5e2 100644 --- a/parea/api_client.py +++ b/parea/api_client.py @@ -5,7 +5,7 @@ class HTTPClient: _instance = None - base_url = "http://localhost:8000/api/parea/v1" # "https://optimus-prompt-backend.vercel.app/api/parea/v1" + base_url = "https://optimus-prompt-backend.vercel.app/api/parea/v1" api_key = None def __new__(cls, *args, **kwargs): diff --git a/parea/client.py b/parea/client.py index 488a9892..491e2c1e 100644 --- a/parea/client.py +++ b/parea/client.py @@ -5,7 +5,7 @@ from parea.api_client import HTTPClient from parea.parea_logger import parea_logger from parea.schemas.models import Completion, CompletionResponse, FeedbackRequest, UseDeployedPrompt, UseDeployedPromptResponse -from parea.trace_utils.trace import trace_context +from parea.utils.trace_utils import get_current_trace_id COMPLETION_ENDPOINT = "/completion" DEPLOYED_PROMPT_ENDPOINT = "/deployed-prompt" @@ -22,7 +22,7 @@ def __attrs_post_init__(self): parea_logger.set_client(self._client) def completion(self, data: Completion) -> CompletionResponse: - data.inference_id = trace_context.get()[-1] + data.inference_id = get_current_trace_id() r = self._client.request( "POST", COMPLETION_ENDPOINT, @@ -31,8 +31,7 @@ def completion(self, data: Completion) -> CompletionResponse: return CompletionResponse(**r.json()) async def acompletion(self, data: Completion) -> CompletionResponse: - trace_id = trace_context.get()[-1] - data.trace_id = trace_id + data.inference_id = get_current_trace_id() r = await self._client.request_async( "POST", COMPLETION_ENDPOINT, @@ -70,24 +69,6 @@ async def arecord_feedback(self, data: FeedbackRequest) -> None: data=asdict(data), ) - # def record_log(self, data: LogRequest) -> None: - # print(f"Logging to database: {data}") - # db_entries.append(data) - # # self._client.request( - # # "POST", - # # LOG_ENDPOINT, - # # data=asdict(data), - # # ) - # - # async def arecord_log(self, data: LogRequest) -> None: - # print(f"Logging to database: {data}") - # db_entries.append(data) - # # await self._client.request_async( - # # "POST", - # # LOG_ENDPOINT, - # # data=asdict(data), - # # ) - def gen_trace_id() -> str: """Generate a unique trace id for each chain of requests""" diff --git a/parea/client_two.py b/parea/client_two.py deleted file mode 100644 index 14ad5ea2..00000000 --- a/parea/client_two.py +++ /dev/null @@ -1,1212 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union, cast - -import json -import logging -import os -import platform -import socket -import subprocess -import weakref -from collections.abc import Iterator, Mapping -from datetime import datetime -from enum import Enum -from functools import lru_cache -from urllib.parse import urlsplit -from uuid import UUID - -from attrs import asdict -from dotenv import load_dotenv -from requests import ConnectionError, HTTPError, Response, Session -from requests.adapters import HTTPAdapter -from urllib3.util import Retry - -from parea.schemas.models import Completion, CompletionResponse - -if TYPE_CHECKING: - pass - - -load_dotenv() - -logger = logging.getLogger(__name__) - - -class PareaAPIError(Exception): - """An error occurred while communicating with the Parea API.""" - - -class PareaUserError(Exception): - """An error occurred while communicating with the Parea API.""" - - -class PareaError(Exception): - """An error occurred while communicating with the Parea API.""" - - -class PareaConnectionError(Exception): - """Couldn't connect to the Parea API.""" - - -def xor_args(*arg_groups: tuple[str, ...]) -> Callable: - """Validate specified keyword args are mutually exclusive.""" - - def decorator(func: Callable) -> Callable: - def wrapper(*args: Any, **kwargs: Any) -> Callable: - """Validate exactly one arg in each group is not None.""" - counts = [sum(1 for arg in arg_group if kwargs.get(arg) is not None) for arg_group in arg_groups] - invalid_groups = [i for i, count in enumerate(counts) if count != 1] - if invalid_groups: - invalid_group_names = [", ".join(arg_groups[i]) for i in invalid_groups] - raise ValueError("Exactly one argument in each of the following" " groups must be defined:" f" {', '.join(invalid_group_names)}") - return func(*args, **kwargs) - - return wrapper - - return decorator - - -def raise_for_status_with_text(response: Response) -> None: - """Raise an error with the response text.""" - try: - response.raise_for_status() - except HTTPError as e: - raise ValueError(response.text) from e - - -def get_enum_value(enum: Enum | str) -> str: - """Get the value of a string enum.""" - if isinstance(enum, Enum): - return enum.value - return enum - - -@lru_cache -def get_runtime_environment() -> dict: - """Get information about the environment.""" - # Lazy import to avoid circular imports - from parea import version - - return { - "sdk_version": version, - "library": "langsmith", - "platform": platform.platform(), - "runtime": "python", - "runtime_version": platform.python_version(), - "langchain_version": get_langchain_environment(), - } - - -def _get_message_type(message: Mapping[str, Any]) -> str: - if not message: - raise ValueError("Message is empty.") - if "lc" in message: - if "id" not in message: - raise ValueError(f"Unexpected format for serialized message: {message}" " Message does not have an id.") - return message["id"][-1].replace("Message", "").lower() - else: - if "type" not in message: - raise ValueError(f"Unexpected format for stored message: {message}" " Message does not have a type.") - return message["type"] - - -def _get_message_fields(message: Mapping[str, Any]) -> Mapping[str, Any]: - if not message: - raise ValueError("Message is empty.") - if "lc" in message: - if "kwargs" not in message: - raise ValueError(f"Unexpected format for serialized message: {message}" " Message does not have kwargs.") - return message["kwargs"] - else: - if "data" not in message: - raise ValueError(f"Unexpected format for stored message: {message}" " Message does not have data.") - return message["data"] - - -def _convert_message(message: Mapping[str, Any]) -> dict[str, Any]: - """Extract message from a message object.""" - message_type = _get_message_type(message) - message_data = _get_message_fields(message) - return {"type": message_type, "data": message_data} - - -def get_messages_from_inputs(inputs: Mapping[str, Any]) -> list[dict[str, Any]]: - if "messages" in inputs: - return [_convert_message(message) for message in inputs["messages"]] - if "message" in inputs: - return [_convert_message(inputs["message"])] - raise ValueError(f"Could not find message(s) in run with inputs {inputs}.") - - -def get_message_generation_from_outputs(outputs: Mapping[str, Any]) -> dict[str, Any]: - if "generations" not in outputs: - raise ValueError(f"No generations found in in run with output: {outputs}.") - generations = outputs["generations"] - if len(generations) != 1: - raise ValueError("Chat examples expect exactly one generation." f" Found {len(generations)} generations: {generations}.") - first_generation = generations[0] - if "message" not in first_generation: - raise ValueError(f"Unexpected format for generation: {first_generation}." " Generation does not have a message.") - return _convert_message(first_generation["message"]) - - -def get_prompt_from_inputs(inputs: Mapping[str, Any]) -> str: - if "prompt" in inputs: - return inputs["prompt"] - if "prompts" in inputs: - prompts = inputs["prompts"] - if len(prompts) == 1: - return prompts[0] - raise ValueError(f"Multiple prompts in run with inputs {inputs}." " Please create example manually.") - raise ValueError(f"Could not find prompt in run with inputs {inputs}.") - - -def get_llm_generation_from_outputs(outputs: Mapping[str, Any]) -> str: - if "generations" not in outputs: - raise ValueError(f"No generations found in in run with output: {outputs}.") - generations = outputs["generations"] - if len(generations) != 1: - raise ValueError(f"Multiple generations in run: {generations}") - first_generation = generations[0] - if "text" not in first_generation: - raise ValueError(f"No text in generation: {first_generation}") - return first_generation["text"] - - -@lru_cache -def get_docker_compose_command() -> list[str]: - """Get the correct docker compose command for this system.""" - try: - subprocess.check_call( - ["docker", "compose", "--version"], - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, - ) - return ["docker", "compose"] - except (subprocess.CalledProcessError, FileNotFoundError): - try: - subprocess.check_call( - ["docker-compose", "--version"], - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, - ) - return ["docker-compose"] - except (subprocess.CalledProcessError, FileNotFoundError): - raise ValueError( - "Neither 'docker compose' nor 'docker-compose'" - " commands are available. Please install the Docker" - " server following the instructions for your operating" - " system at https://docs.docker.com/engine/install/" - ) - - -@lru_cache -def get_langchain_environment() -> str | None: - try: - import parea # type: ignore - - return parea.version - except: # noqa - return None - - -@lru_cache -def get_docker_version() -> str | None: - import subprocess - - try: - docker_version = subprocess.check_output(["docker", "--version"]).decode("utf-8").strip() - except FileNotFoundError: - docker_version = "unknown" - except: # noqa - return None - return docker_version - - -@lru_cache -def get_docker_compose_version() -> str | None: - try: - docker_compose_version = subprocess.check_output(["docker-compose", "--version"]).decode("utf-8").strip() - except FileNotFoundError: - docker_compose_version = "unknown" - except: # noqa - return None - return docker_compose_version - - -@lru_cache -def _get_compose_command() -> list[str] | None: - try: - compose_command = get_docker_compose_command() - except ValueError as e: - compose_command = [f"NOT INSTALLED: {e}"] - except: # noqa - return None - return compose_command - - -@lru_cache -def get_docker_environment() -> dict: - """Get information about the environment.""" - compose_command = _get_compose_command() - return { - "docker_version": get_docker_version(), - "docker_compose_command": " ".join(compose_command) if compose_command is not None else None, - "docker_compose_version": get_docker_compose_version(), - } - - -def _is_localhost(url: str) -> bool: - """Check if the URL is localhost. - - Parameters - ---------- - url : str - The URL to check. - - Returns - ------- - bool - True if the URL is localhost, False otherwise. - """ - try: - netloc = urlsplit(url).netloc.split(":")[0] - ip = socket.gethostbyname(netloc) - return ip == "127.0.0.1" or ip.startswith("0.0.0.0") or ip.startswith("::") - except socket.gaierror: - return False - - -ID_TYPE = Union[UUID, str] - - -def _default_retry_config() -> Retry: - """Get the default retry configuration. - - Returns - ------- - Retry - The default retry configuration. - """ - return Retry( - total=3, - allowed_methods=None, # Retry on all methods - status_forcelist=[502, 503, 504, 408, 425, 429], - backoff_factor=0.5, - # Sadly urllib3 1.x doesn't support backoff_jitter - raise_on_redirect=False, - raise_on_status=False, - ) - - -def _serialize_json(obj: Any) -> str: - """Serialize an object to JSON. - - Parameters - ---------- - obj : Any - The object to serialize. - - Returns - ------- - str - The serialized JSON string. - - Raises - ------ - TypeError - If the object type is not serializable. - """ - if isinstance(obj, datetime): - return obj.isoformat() - else: - return str(obj) - - -def close_session(session: Session) -> None: - """Close the session. - - Parameters - ---------- - session : Session - The session to close. - """ - logger.debug("Closing Client.session") - session.close() - - -def _validate_api_key_if_hosted(api_url: str, api_key: str | None) -> None: - """Verify API key is provided if url not localhost. - - Parameters - ---------- - api_url : str - The API URL. - api_key : str or None - The API key. - - Raises - ------ - LangSmithUserError - If the API key is not provided when using the hosted service. - """ - if not _is_localhost(api_url): - if not api_key: - raise PareaUserError("API key must be provided when using hosted LangSmith API") - - -def _get_api_key(api_key: str | None) -> str | None: - api_key = api_key if api_key is not None else os.getenv("DEV_API_KEY") - if api_key is None or not api_key.strip(): - return None - return api_key.strip().strip('"').strip("'") - - -def _get_api_url(api_url: str | None, api_key: str | None) -> str: - _api_url = api_url if api_url is not None else "http://localhost:8000/api/parea/v1" - if not _api_url.strip(): - raise PareaUserError("Parea API URL cannot be empty") - return _api_url.strip().strip('"').strip("'").rstrip("/") - - -class Client: - """Client for interacting with the LangSmith API.""" - - __slots__ = [ - "__weakref__", - "api_url", - "api_key", - "retry_config", - "timeout_ms", - "session", - ] - - def __init__( - self, - api_url: str | None = None, - *, - api_key: str | None = None, - retry_config: Retry | None = None, - timeout_ms: int | None = None, - ) -> None: - """Initialize a Client instance. - - Parameters - ---------- - api_url : str or None, default=None - URL for the LangSmith API. Defaults to the LANGCHAIN_ENDPOINT - environment variable or http://localhost:1984 if not set. - api_key : str or None, default=None - API key for the LangSmith API. Defaults to the LANGCHAIN_API_KEY - environment variable. - retry_config : Retry or None, default=None - Retry configuration for the HTTPAdapter. - timeout_ms : int or None, default=None - Timeout in milliseconds for the HTTPAdapter. - - Raises - ------ - LangSmithUserError - If the API key is not provided when using the hosted service. - """ - self.api_key = _get_api_key(api_key) - self.api_url = _get_api_url(api_url, self.api_key) - _validate_api_key_if_hosted(self.api_url, self.api_key) - self.retry_config = retry_config or _default_retry_config() - self.timeout_ms = timeout_ms or 7000 - # Create a session and register a finalizer to close it - self.session = Session() - weakref.finalize(self, close_session, self.session) - - # Mount the HTTPAdapter with the retry configuration - adapter = HTTPAdapter(max_retries=self.retry_config) - self.session.mount("http://", adapter) - self.session.mount("https://", adapter) - - def _repr_html_(self) -> str: - """Return an HTML representation of the instance with a link to the URL. - - Returns - ------- - str - The HTML representation of the instance. - """ - link = self._host_url - return f'LangSmith Client' - - def __repr__(self) -> str: - """Return a string representation of the instance with a link to the URL. - - Returns - ------- - str - The string representation of the instance. - """ - return f"Client (API URL: {self.api_url})" - - @property - def _host_url(self) -> str: - """The web host url.""" - if _is_localhost(self.api_url): - link = "http://localhost" - elif "dev" in self.api_url.split(".", maxsplit=1)[0]: - link = "http://localhost" - else: - link = "https://optimus-prompt-backend.vercel.app" - return link - - @property - def _headers(self) -> dict[str, str]: - """Get the headers for the API request. - - Returns - ------- - Dict[str, str] - The headers for the API request. - """ - headers = {} - if self.api_key: - headers["x-api-key"] = self.api_key - return headers - - def request_with_retries( - self, - request_method: str, - url: str, - request_kwargs: Mapping, - ) -> Response: - """Send a request with retries. - - Parameters - ---------- - request_method : str - The HTTP request method. - url : str - The URL to send the request to. - request_kwargs : Mapping - Additional request parameters. - - Returns - ------- - Response - The response object. - - Raises - ------ - LangSmithAPIError - If a server error occurs. - LangSmithUserError - If the request fails. - LangSmithConnectionError - If a connection error occurs. - LangSmithError - If the request fails. - """ - try: - response = self.session.request(request_method, url, stream=False, **request_kwargs) - raise_for_status_with_text(response) - return response - except HTTPError as e: - if response is not None and response.status_code == 500: - raise PareaAPIError(f"Server error caused failure to {request_method} {url} in" f" Parea API. {e}") - else: - raise PareaUserError(f"Failed to {request_method} {url} in LangSmith API. {e}") - except ConnectionError as e: - raise PareaConnectionError(f"Connection error caused failure to {request_method} {url}" " in Parea API. Please confirm your PAREA_ENDPOINT.") from e - except Exception as e: - raise PareaError(f"Failed to {request_method} {url} in Parea API. {e}") from e - - def _get_with_retries(self, path: str, params: dict[str, Any] | None = None) -> Response: - """Send a GET request with retries. - - Parameters - ---------- - path : str - The path of the request URL. - params : Dict[str, Any] or None, default=None - The query parameters. - - Returns - ------- - Response - The response object. - - Raises - ------ - LangSmithAPIError - If a server error occurs. - LangSmithUserError - If the request fails. - LangSmithConnectionError - If a connection error occurs. - LangSmithError - If the request fails. - """ - return self.request_with_retries( - "get", - f"{self.api_url}/{path}", - request_kwargs={ - "params": params, - "headers": self._headers, - "timeout": self.timeout_ms / 1000, - }, - ) - - def _get_paginated_list(self, path: str, *, params: dict | None = None) -> Iterator[dict]: - """Get a paginated list of items. - - Parameters - ---------- - path : str - The path of the request URL. - params : dict or None, default=None - The query parameters. - - Yields - ------ - dict - The items in the paginated list. - """ - params_ = params.copy() if params else {} - offset = params_.get("offset", 0) - params_["limit"] = params_.get("limit", 100) - while True: - params_["offset"] = offset - response = self._get_with_retries(path, params=params_) - items = response.json() - if not items: - break - yield from items - if len(items) < params_["limit"]: - # offset and limit isn't respected if we're - # querying for specific values - break - offset += len(items) - - def create_run( - self, - name: str, - inputs: dict[str, Any], - run_type: str, - *, - execution_order: int | None = None, - **kwargs: Any, - ) -> None: - """Persist a run to the LangSmith API. - - Parameters - ---------- - name : str - The name of the run. - inputs : Dict[str, Any] - The input values for the run. - run_type : str - The type of the run, such as tool, chain, llm, retriever, - embedding, prompt, or parser. - execution_order : int or None, default=None - The execution order of the run. - **kwargs : Any - Additional keyword arguments. - - Raises - ------ - LangSmithUserError - If the API key is not provided when using the hosted service. - """ - project_name = kwargs.pop( - "project_name", - kwargs.pop( - "session_name", - os.environ.get( - # TODO: Deprecate PAREA_SESSION - "PAREA_PROJECT", - os.environ.get("PAREA_SESSION", "default"), - ), - ), - ) - run_create = { - **kwargs, - "session_name": project_name, - "name": name, - "inputs": inputs, - "run_type": run_type, - "execution_order": execution_order if execution_order is not None else 1, - } - run_extra = cast(dict, run_create.setdefault("extra", {})) - runtime = run_extra.setdefault("runtime", {}) - runtime_env = get_runtime_environment() - run_extra["runtime"] = {**runtime_env, **runtime} - headers = {**self._headers, "Accept": "application/json"} - self.request_with_retries( - "post", - f"{self.api_url}/runs", - request_kwargs={ - "data": json.dumps(run_create, default=_serialize_json), - "headers": headers, - "timeout": self.timeout_ms / 1000, - }, - ) - - def completion(self, data: Completion) -> CompletionResponse: - headers = {**self._headers, "Accept": "application/json"} - r = self.request_with_retries( - "post", - f"{self.api_url}/completion", - request_kwargs={ - "data": json.dumps(asdict(data), default=_serialize_json), - "headers": headers, - "timeout": self.timeout_ms / 1000, - }, - ) - return CompletionResponse(**r.json()) - - def update_run( - self, - run_id: ID_TYPE, - **kwargs: Any, - ) -> None: - """Update a run in the LangSmith API. - - Parameters - ---------- - run_id : str or UUID - The ID of the run to update. - **kwargs : Any - Additional keyword arguments. - """ - headers = {**self._headers, "Accept": "application/json"} - self.request_with_retries( - "patch", - f"{self.api_url}/runs/{run_id}", - request_kwargs={ - "data": json.dumps(kwargs, default=_serialize_json), - "headers": headers, - "timeout": self.timeout_ms / 1000, - }, - ) - - # def _load_child_runs(self, run: Run) -> Run: - # """Load child runs for a given run. - # - # Parameters - # ---------- - # run : Run - # The run to load child runs for. - # - # Returns - # ------- - # Run - # The run with loaded child runs. - # - # Raises - # ------ - # LangSmithError - # If a child run has no parent. - # """ - # child_runs = self.list_runs(id=run.child_run_ids) - # treemap: DefaultDict[UUID, List[Run]] = defaultdict(list) - # runs: Dict[UUID, Run] = {} - # for child_run in sorted(child_runs, key=lambda r: r.execution_order): - # if child_run.parent_run_id is None: - # raise PareaError(f"Child run {child_run.id} has no parent") - # treemap[child_run.parent_run_id].append(child_run) - # runs[child_run.id] = child_run - # run.child_runs = treemap.pop(run.id, []) - # for run_id, children in treemap.items(): - # runs[run_id].child_runs = children - # return run - - # - # def read_run(self, run_id: ID_TYPE, load_child_runs: bool = False) -> Run: - # """Read a run from the LangSmith API. - # - # Parameters - # ---------- - # run_id : str or UUID - # The ID of the run to read. - # load_child_runs : bool, default=False - # Whether to load nested child runs. - # - # Returns - # ------- - # Run - # The run. - # """ - # response = self._get_with_retries(f"/runs/{run_id}") - # run = Run(**response.json(), _host_url=self._host_url) - # if load_child_runs and run.child_run_ids: - # run = self._load_child_runs(run) - # return run - # - # def list_runs( - # self, - # *, - # project_id: Optional[ID_TYPE] = None, - # project_name: Optional[str] = None, - # run_type: Optional[str] = None, - # dataset_name: Optional[str] = None, - # dataset_id: Optional[ID_TYPE] = None, - # reference_example_id: Optional[ID_TYPE] = None, - # query: Optional[str] = None, - # filter: Optional[str] = None, - # execution_order: Optional[int] = None, - # parent_run_id: Optional[ID_TYPE] = None, - # start_time: Optional[datetime] = None, - # end_time: Optional[datetime] = None, - # error: Optional[bool] = None, - # run_ids: Optional[List[ID_TYPE]] = None, - # limit: Optional[int] = None, - # offset: Optional[int] = None, - # order_by: Optional[Sequence[str]] = None, - # **kwargs: Any, - # ) -> Iterator[Run]: - # """List runs from the LangSmith API. - # - # Parameters - # ---------- - # project_id : UUID or None, default=None - # The ID of the project to filter by. - # project_name : str or None, default=None - # The name of the project to filter by. - # run_type : str or None, default=None - # The type of the runs to filter by. - # dataset_name : str or None, default=None - # The name of the dataset to filter by. - # dataset_id : UUID or None, default=None - # The ID of the dataset to filter by. - # reference_example_id : UUID or None, default=None - # The ID of the reference example to filter by. - # query : str or None, default=None - # The query string to filter by. - # filter : str or None, default=None - # The filter string to filter by. - # execution_order : int or None, default=None - # The execution order to filter by. - # parent_run_id : UUID or None, default=None - # The ID of the parent run to filter by. - # start_time : datetime or None, default=None - # The start time to filter by. - # end_time : datetime or None, default=None - # The end time to filter by. - # error : bool or None, default=None - # Whether to filter by error status. - # run_ids : List[str or UUID] or None, default=None - # The IDs of the runs to filter by. - # limit : int or None, default=None - # The maximum number of runs to return. - # offset : int or None, default=None - # The number of runs to skip. - # order_by : Sequence[str] or None, default=None - # The fields to order the runs by. - # **kwargs : Any - # Additional keyword arguments. - # - # Yields - # ------ - # Run - # The runs. - # """ - # if project_name is not None: - # if project_id is not None: - # raise ValueError("Only one of project_id or project_name may be given") - # project_id = self.read_project(project_name=project_name).id - # if dataset_name is not None: - # if dataset_id is not None: - # raise ValueError("Only one of dataset_id or dataset_name may be given") - # dataset_id = self.read_dataset(dataset_name=dataset_name).id - # query_params: Dict[str, Any] = { - # "session": project_id, - # "run_type": run_type, - # **kwargs, - # } - # if reference_example_id is not None: - # query_params["reference_example"] = reference_example_id - # if dataset_id is not None: - # query_params["dataset"] = dataset_id - # if query is not None: - # query_params["query"] = query - # if filter is not None: - # query_params["filter"] = filter - # if execution_order is not None: - # query_params["execution_order"] = execution_order - # if parent_run_id is not None: - # query_params["parent_run"] = parent_run_id - # if start_time is not None: - # query_params["start_time"] = start_time.isoformat() - # if end_time is not None: - # query_params["end_time"] = end_time.isoformat() - # if error is not None: - # query_params["error"] = error - # if run_ids is not None: - # query_params["id"] = run_ids - # if limit is not None: - # query_params["limit"] = limit - # if offset is not None: - # query_params["offset"] = offset - # if order_by is not None: - # query_params["order"] = order_by - # yield from (Run(**run, _host_url=self._host_url) for run in self._get_paginated_list("/runs", params=query_params)) - # - # def delete_run(self, run_id: ID_TYPE) -> None: - # """Delete a run from the LangSmith API. - # - # Parameters - # ---------- - # run_id : str or UUID - # The ID of the run to delete. - # """ - # response = self.session.delete( - # f"{self.api_url}/runs/{run_id}", - # headers=self._headers, - # ) - # raise_for_status_with_text(response) - # - # def share_run(self, run_id: ID_TYPE, *, share_id: Optional[ID_TYPE] = None) -> str: - # """Get a share link for a run.""" - # data = { - # "run_id": str(run_id), - # "share_token": share_id or str(uuid4()), - # } - # response = self.session.put( - # f"{self.api_url}/runs/{run_id}/share", - # headers=self._headers, - # json=data, - # ) - # raise_for_status_with_text(response) - # share_token = response.json()["share_token"] - # return f"{self._host_url}/public/{share_token}/r" - # - # def unshare_run(self, run_id: ID_TYPE) -> None: - # """Delete share link for a run.""" - # response = self.session.delete( - # f"{self.api_url}/runs/{run_id}/share", - # headers=self._headers, - # ) - # raise_for_status_with_text(response) - # - # def read_run_shared_link(self, run_id: ID_TYPE) -> Optional[str]: - # response = self.session.get( - # f"{self.api_url}/runs/{run_id}/share", - # headers=self._headers, - # ) - # raise_for_status_with_text(response) - # result = response.json() - # if result is None or "share_token" not in result: - # return None - # return f"{self._host_url}/public/{result['share_token']}/r" - # - # def run_is_shared(self, run_id: ID_TYPE) -> bool: - # """Get share state for a run.""" - # link = self.read_run_shared_link(run_id) - # return link is not None - - -# import logging -# import os -# import platform -# import socket -# import weakref -# from datetime import datetime -# from enum import Enum -# from functools import lru_cache -# from typing import Any, Callable, Dict, Mapping, Optional, Tuple, Union, AsyncIterator -# from typing import ( -# TYPE_CHECKING, -# cast, -# ) -# from urllib.parse import urlsplit -# from uuid import UUID -# -# import httpx -# from attrs import asdict -# from dotenv import load_dotenv -# from httpx import HTTPStatusError -# -# from parea.schemas.models import Completion, CompletionResponse -# -# if TYPE_CHECKING: -# pass -# -# load_dotenv() -# -# logger = logging.getLogger(__name__) -# -# -# class PareaAPIError(Exception): -# """An error occurred while communicating with the Parea API.""" -# -# -# class PareaUserError(Exception): -# """An error occurred while communicating with the Parea API.""" -# -# -# class PareaError(Exception): -# """An error occurred while communicating with the Parea API.""" -# -# -# class PareaConnectionError(Exception): -# """Couldn't connect to the Parea API.""" -# -# -# def xor_args(*arg_groups: Tuple[str, ...]) -> Callable: -# """Validate specified keyword args are mutually exclusive.""" -# -# def decorator(func: Callable) -> Callable: -# def wrapper(*args: Any, **kwargs: Any) -> Callable: -# """Validate exactly one arg in each group is not None.""" -# counts = [sum(1 for arg in arg_group if kwargs.get(arg) is not None) for arg_group in arg_groups] -# invalid_groups = [i for i, count in enumerate(counts) if count != 1] -# if invalid_groups: -# invalid_group_names = [", ".join(arg_groups[i]) for i in invalid_groups] -# raise ValueError("Exactly one argument in each of the following" " groups must be defined:" f" {', '.join(invalid_group_names)}") -# return func(*args, **kwargs) -# -# return wrapper -# -# return decorator -# -# -# def raise_for_status_with_text(response: httpx.Response) -> None: -# """Raise an error with the response text.""" -# try: -# response.raise_for_status() -# except HTTPStatusError as e: -# raise ValueError(response.text) from e -# -# -# def get_enum_value(enum: Union[Enum, str]) -> str: -# """Get the value of a string enum.""" -# if isinstance(enum, Enum): -# return enum.value -# return enum -# -# -# @lru_cache -# def get_runtime_environment() -> dict: -# """Get information about the environment.""" -# # Lazy import to avoid circular imports -# from parea import version -# -# return { -# "sdk_version": version, -# "library": "langsmith", -# "platform": platform.platform(), -# "runtime": "python", -# "runtime_version": platform.python_version(), -# } -# -# def _is_localhost(url: str) -> bool: -# """Check if the URL is localhost.""" -# try: -# netloc = urlsplit(url).netloc.split(":")[0] -# ip = socket.gethostbyname(netloc) -# return ip == "127.0.0.1" or ip.startswith("0.0.0.0") or ip.startswith("::") -# except socket.gaierror: -# return False -# -# -# ID_TYPE = Union[UUID, str] -# -# -# def _serialize_json(obj: Any) -> str: -# """Serialize an object to JSON.""" -# if isinstance(obj, datetime): -# return obj.isoformat() -# else: -# return str(obj) -# -# -# async def close_session(session: httpx.AsyncClient) -> None: -# """Close the session.""" -# logger.debug("Closing Client.session") -# await session.aclose() -# -# -# def _validate_api_key_if_hosted(api_url: str, api_key: Optional[str]) -> None: -# """Verify API key is provided if url not localhost.""" -# if not _is_localhost(api_url): -# if not api_key: -# raise PareaUserError("API key must be provided when using hosted LangSmith API") -# -# -# def _get_api_key(api_key: Optional[str]) -> Optional[str]: -# api_key = api_key if api_key is not None else os.getenv("DEV_API_KEY") -# if api_key is None or not api_key.strip(): -# return None -# return api_key.strip().strip('"').strip("'") -# -# -# def _get_api_url(api_url: Optional[str], api_key: Optional[str]) -> str: -# _api_url = api_url if api_url is not None else "http://localhost:8000/api/parea/v1" -# if not _api_url.strip(): -# raise PareaUserError("Parea API URL cannot be empty") -# return _api_url.strip().strip('"').strip("'").rstrip("/") -# -# -# class Client: -# """Client for interacting with the LangSmith API.""" -# -# def __init__( -# self, -# api_url: Optional[str] = None, -# *, -# api_key: Optional[str] = None, -# ) -> None: -# """Initialize a Client instance.""" -# self.api_key = _get_api_key(api_key) -# self.api_url = _get_api_url(api_url, self.api_key) -# _validate_api_key_if_hosted(self.api_url, self.api_key) -# -# # Create a session and register a finalizer to close it -# self.session = httpx.AsyncClient() -# weakref.finalize(self, close_session, self.session) -# -# def _repr_html_(self) -> str: -# """Return an HTML representation of the instance with a link to the URL.""" -# link = self._host_url -# return f'LangSmith Client' -# -# def __repr__(self) -> str: -# """Return a string representation of the instance with a link to the URL.""" -# return f"Client (API URL: {self.api_url})" -# -# @property -# def _host_url(self) -> str: -# """The web host url.""" -# if _is_localhost(self.api_url): -# link = "http://localhost" -# elif "dev" in self.api_url.split(".", maxsplit=1)[0]: -# link = "http://localhost" -# else: -# link = "https://optimus-prompt-backend.vercel.app" -# return link -# -# @property -# def _headers(self) -> Dict[str, str]: -# """Get the headers for the API request.""" -# headers = {} -# if self.api_key: -# headers["x-api-key"] = self.api_key -# return headers -# -# async def request_with_retries( -# self, -# request_method: str, -# url: str, -# request_kwargs: Mapping, -# ) -> httpx.Response: -# """Send a request with retries.""" -# -# try: -# response = await self.session.request(request_method, url, **request_kwargs) -# raise_for_status_with_text(response) -# return response -# except HTTPStatusError as e: -# if response.status_code == 500: -# raise PareaAPIError(f"Server error caused failure to {request_method} {url} in Parea API. {e}") -# else: -# raise PareaUserError(f"Failed to {request_method} {url} in LangSmith API. {e}") -# except httpx.ConnectError as e: -# raise PareaConnectionError(f"Connection error caused failure to {request_method} {url} in Parea API. Please confirm your PAREA_ENDPOINT.") from e -# except Exception as e: -# raise PareaError(f"Failed to {request_method} {url} in Parea API. {e}") from e -# -# async def _get_with_retries(self, path: str, params: Optional[Dict[str, Any]] = None) -> httpx.Response: -# """Send a GET request with retries.""" -# return await self.request_with_retries( -# "get", -# f"{self.api_url}/{path}", -# request_kwargs={ -# "params": params, -# "headers": self._headers, -# }, -# ) -# -# async def _get_paginated_list(self, path: str, *, params: Optional[dict] = None) -> AsyncIterator[dict]: -# """Get a paginated list of items.""" -# params_ = params.copy() if params else {} -# offset = params_.get("offset", 0) -# params_["limit"] = params_.get("limit", 100) -# while True: -# params_["offset"] = offset -# response = await self._get_with_retries(path, params=params_) -# items = response.json() -# if not items: -# break -# for item in items: -# yield item -# if len(items) < params_["limit"]: -# break -# offset += len(items) -# -# async def create_run( -# self, -# name: str, -# inputs: Dict[str, Any], -# run_type: str, -# *, -# execution_order: Optional[int] = None, -# **kwargs: Any, -# ) -> None: -# """Persist a run to the LangSmith API.""" -# -# project_name = kwargs.pop( -# "project_name", -# kwargs.pop( -# "session_name", -# os.environ.get( -# "PAREA_PROJECT", -# os.environ.get("PAREA_SESSION", "default"), -# ), -# ), -# ) -# run_create = { -# **kwargs, -# "session_name": project_name, -# "name": name, -# "inputs": inputs, -# "run_type": run_type, -# "execution_order": execution_order if execution_order is not None else 1, -# } -# run_extra = cast(dict, run_create.setdefault("extra", {})) -# runtime = run_extra.setdefault("runtime", {}) -# runtime_env = get_runtime_environment() -# run_extra["runtime"] = {**runtime_env, **runtime} -# headers = {**self._headers, "Accept": "application/json"} -# await self.request_with_retries( -# "post", -# f"{self.api_url}/runs", -# request_kwargs={ -# "json": run_create, -# "headers": headers, -# }, -# ) -# -# async def completion(self, data: Completion) -> CompletionResponse: -# headers = {**self._headers, "Accept": "application/json"} -# r = await self.request_with_retries( -# "post", -# f"{self.api_url}/completion", -# request_kwargs={ -# "json": asdict(data), -# "headers": headers, -# }, -# ) -# return CompletionResponse(**r.json()) -# -# async def update_run( -# self, -# run_id: ID_TYPE, -# **kwargs: Any, -# ) -> None: -# """Update a run in the LangSmith API.""" -# headers = {**self._headers, "Accept": "application/json"} -# await self.request_with_retries( -# "patch", -# f"{self.api_url}/runs/{run_id}", -# request_kwargs={ -# "json": kwargs, -# "headers": headers, -# }, -# ) diff --git a/parea/cookbook/example2.py b/parea/cookbook/example2.py deleted file mode 100644 index b25d906d..00000000 --- a/parea/cookbook/example2.py +++ /dev/null @@ -1,307 +0,0 @@ -from typing import Dict, List - -import os - -from dotenv import load_dotenv - -from parea.client_two import Client -from parea.schemas.models import Completion, LLMInputs, Message, ModelParams, Role -from parea.trace_utils.run_helpers import traceable - -load_dotenv() - -client = Client(api_key=os.getenv("DEV_API_KEY")) - -LIMIT = 1 - - -# dump task array to string -def dump_task(task): - d = "" # init - for tasklet in task: - d += f"\n{tasklet.get('task_name','')}" - d = d.strip() - return d - - -@traceable(run_type="llm") -def open_ai_inference( - prompt: str, - model: str = "gpt-3.5-turbo", - temperature: float = 0.5, -) -> str: - return client.completion( - data=Completion( - llm_configuration=LLMInputs( - model=model, - provider="openai", - model_params=ModelParams(model=model, temp=temperature), - messages=[Message(role=Role.system, content=prompt)], - ), - ) - ).content.strip() - - -@traceable(run_type="chain") -def expound_task(main_objective: str, current_task: str) -> list[dict[str, str]]: - print(f"****Expounding based on task:**** {current_task}") - prompt = f"You are an AI who performs one task based on the following objective: {main_objective}\n" f"Your task: {current_task}\nResponse:" - response = open_ai_inference(prompt) - new_tasks = response.split("\n") if "\n" in response else [response] - return [{"task_name": task_name} for task_name in new_tasks][0:1] - - -@traceable(run_type="chain") -def generate_tasks(main_objective: str, expounded_initial_task: list[dict[str, str]]) -> list[str]: - task_expansion = dump_task(expounded_initial_task) - prompt = ( - f"You are an AI who creates tasks based on the following MAIN OBJECTIVE: {main_objective}\n" - f"Create tasks pertaining directly to your previous research here:\n" - f"{task_expansion}\nResponse:" - ) - response = open_ai_inference(prompt) - new_tasks = response.split("\n") if "\n" in response else [response] - task_list = [{"task_name": task_name} for task_name in new_tasks] - new_tasks_list: list[str] = [] - for task_item in task_list: - # print(task_item) - task_description = task_item.get("task_name") - if task_description: - # print(task_description) - task_parts = task_description.strip().split(".", 1) - # print(task_parts) - if len(task_parts) == 2: - new_task = task_parts[1].strip() - new_tasks_list.append(new_task) - - return new_tasks_list[0:1] - - -@traceable(run_type="chain") -def run_agent(main_objective: str, initial_task: str = "") -> list[dict[str, str]]: - generated_tasks = [] - expounded_initial_task = expound_task(main_objective, initial_task) - new_tasks = generate_tasks(main_objective, expounded_initial_task) - print(f"Generated {len(new_tasks)} tasks") - task_counter = 0 - for task in new_tasks: - task_counter += 1 - print(f"#### ({task_counter}) Generated Task ####") - q = expound_task(main_objective, task) - exp = dump_task(q) - generated_tasks.append({f"task_{task_counter}": exp}) - if task_counter >= LIMIT: - print(f"Stopping after {LIMIT} tasks") - break - return generated_tasks - - -if __name__ == "__main__": - main_objective = "Become a machine learning expert." # overall objective - initial_task = "Learn about tensors." # first task to research - - print("*****OBJECTIVE*****") - print(f"{main_objective}") - - # Simple version here, just generate tasks based on the initial task and objective, - # then expound with GPT against the main objective and the newly generated tasks. - result = run_agent(main_objective, initial_task) - print("*****RESULT*****") - print(result) - - -# # Create a ContextVar to store the current trace context -# _TRACE_CONTEXT = contextvars.ContextVar("_TRACE_CONTEXT", default=None) -# -# -# def get_trace_context() -> Optional[str]: -# """Get the current trace context.""" -# return _TRACE_CONTEXT.get() -# -# -# def log_decorator(func): -# @functools.wraps(func) -# def wrapper(*args, **kwargs): -# # Get the parent trace_id from the current context -# parent_trace_id = get_trace_context() -# -# # Generate a new trace_id for this function call -# trace_id = gen_trace_id() -# -# # Set the new trace_id as the current context -# _TRACE_CONTEXT.set(trace_id) -# trace_name = func.__name__ -# -# start_timestamp = time.time() -# -# # Get function arguments using inspect -# arg_names = inspect.getfullargspec(func)[0] -# print(f"arg_names: {arg_names}") -# inputs = {**dict(zip(arg_names, args)), **kwargs} -# print(f"inputs: {inputs}") -# -# try: -# partial_func = functools.partial(func, trace_id=trace_id, trace_name=trace_name, metadata={"parent_trace_id": parent_trace_id}) -# result = partial_func(*args, **kwargs) -# except Exception as e: -# # Log the error and re-raise -# end_timestamp = time.time() -# log_chain( -# trace_id=trace_id, -# trace_name=trace_name, -# llm_inputs=inputs, -# output=None, -# error=str(e), -# start_timestamp=start_timestamp, -# end_timestamp=end_timestamp, -# parent_trace_id=parent_trace_id, -# ) -# raise -# else: -# # Log the successful execution -# end_timestamp = time.time() -# log_chain( -# trace_id=trace_id, -# trace_name=trace_name, -# llm_inputs=inputs, -# output=result, -# error=None, -# start_timestamp=start_timestamp, -# end_timestamp=end_timestamp, -# parent_trace_id=parent_trace_id, -# ) -# return result -# finally: -# # Reset the trace context to the parent trace_id -# _TRACE_CONTEXT.set(parent_trace_id) -# -# return wrapper -# -# -# def to_date_and_time_string(timestamp: float) -> str: -# return datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S %Z") -# -# -# def log_chain( -# trace_id: str, -# trace_name: str, -# llm_inputs: Optional[dict], -# output: Optional[str], -# error: Optional[str], -# start_timestamp: float, -# end_timestamp: float, -# parent_trace_id: Optional[str], -# ) -> None: -# httpx.post( -# "http://localhost:8000/api/parea/v1/log", -# json={ -# "trace_id": trace_id, -# "name": trace_name, -# "error": error, -# "status": "success" if error is None else "error", -# "llm_inputs": llm_inputs, -# "output": output, -# "start_timestamp": to_date_and_time_string(start_timestamp), -# "end_timestamp": to_date_and_time_string(end_timestamp), -# "user_defined_metadata": {"parent_trace_id": parent_trace_id}, -# }, -# headers={"x-api-key": os.getenv("DEV_API_KEY")}, -# timeout=60 * 3.0, -# ) -# -# -# # dump task array to string -# def dump_task(task): -# d = "" # init -# for tasklet in task: -# d += f"\n{tasklet.get('task_name','')}" -# d = d.strip() -# return d -# -# -# def open_ai_inference( -# prompt: str, -# model: str = "gpt-3.5-turbo", -# temperature: float = 0.5, -# max_tokens: int = 1024, -# **kwargs, -# ) -> str: -# return p.completion( -# data=Completion( -# llm_configuration=LLMInputs( -# model=model, -# provider="openai", -# model_params=ModelParams(model=model, temp=temperature, max_length=max_tokens), -# messages=[Message(role=Role.system, content=prompt)], -# ), -# **kwargs, -# ) -# ).content.strip() -# -# -# @log_decorator -# def expound_task(main_objective: str, current_task: str, **kwargs) -> List[Dict[str, str]]: -# print(f"****Expounding based on task:**** {current_task}") -# prompt = f"You are an AI who performs one task based on the following objective: {main_objective}\n" f"Your task: {current_task}\nResponse:" -# response = open_ai_inference(prompt, name="expound_task", **kwargs) -# new_tasks = response.split("\n") if "\n" in response else [response] -# return [{"task_name": task_name} for task_name in new_tasks] -# -# -# @log_decorator -# def generate_tasks(main_objective: str, expounded_initial_task: List[Dict[str, str]], **kwargs) -> List[str]: -# task_expansion = dump_task(expounded_initial_task) -# prompt = ( -# f"You are an AI who creates tasks based on the following MAIN OBJECTIVE: {main_objective}\n" -# f"Create tasks pertaining directly to your previous research here:\n" -# f"{task_expansion}\nResponse:" -# ) -# response = open_ai_inference(prompt, name="generate_tasks", **kwargs) -# new_tasks = response.split("\n") if "\n" in response else [response] -# task_list = [{"task_name": task_name} for task_name in new_tasks] -# new_tasks_list: List[str] = [] -# for task_item in task_list: -# # print(task_item) -# task_description = task_item.get("task_name") -# if task_description: -# # print(task_description) -# task_parts = task_description.strip().split(".", 1) -# # print(task_parts) -# if len(task_parts) == 2: -# new_task = task_parts[1].strip() -# new_tasks_list.append(new_task) -# -# return new_tasks_list -# -# -# @log_decorator -# def run_agent(main_objective: str, initial_task: str = "", **kwargs) -> List[Dict[str, str]]: -# generated_tasks = [] -# expounded_initial_task = expound_task(main_objective, initial_task, **kwargs) -# new_tasks = generate_tasks(main_objective, expounded_initial_task, **kwargs) -# print(f"Generated {len(new_tasks)} tasks") -# task_counter = 0 -# for task in new_tasks: -# task_counter += 1 -# print(f"#### ({task_counter}) Generated Task ####") -# q = expound_task(main_objective, task, **kwargs) -# exp = dump_task(q) -# generated_tasks.append({f"task_{task_counter}": exp}) -# if task_counter >= LIMIT: -# print(f"Stopping after {LIMIT} tasks") -# break -# return generated_tasks -# -# -# if __name__ == "__main__": -# main_objective = "Become a machine learning expert." # overall objective -# initial_task = "Learn about tensors." # first task to research -# -# print("*****OBJECTIVE*****") -# print(f"{main_objective}") -# -# # Simple version here, just generate tasks based on the initial task and objective, -# # then expound with GPT against the main objective and the newly generated tasks. -# result = run_agent(main_objective, initial_task) -# print("*****RESULT*****") -# print(result) diff --git a/parea/cookbook/tracing_with_parea_sdk.py b/parea/cookbook/tracing_with_parea_sdk.py index a79d304a..66a7779d 100644 --- a/parea/cookbook/tracing_with_parea_sdk.py +++ b/parea/cookbook/tracing_with_parea_sdk.py @@ -1,13 +1,11 @@ -from typing import Optional - import os from datetime import datetime from dotenv import load_dotenv from parea import Parea -from parea.client import gen_trace_id from parea.schemas.models import Completion, CompletionResponse, FeedbackRequest +from parea.utils.trace_utils import get_current_trace_id, trace load_dotenv() @@ -15,7 +13,8 @@ # We pass the deployment_id and the required inputs to the completion function along with the trace_id -def argument_generator(query: str, additional_description: str = "", trace_id: Optional[str] = None, **kwargs) -> str: +@trace +def argument_generator(query: str, additional_description: str = "", **kwargs) -> str: return p.completion( Completion( deployment_id="p-RG8d9sssc_0cctwfpb_n6", @@ -24,24 +23,24 @@ def argument_generator(query: str, additional_description: str = "", trace_id: O "date": f"{datetime.now()}", "query": query, }, - trace_id=trace_id, **kwargs, ) ).content -def critic(argument: str, trace_id: Optional[str] = None, **kwargs) -> str: +@trace +def critic(argument: str, **kwargs) -> str: return p.completion( Completion( deployment_id="p-fXgZytVVVJjXD_71TDR4s", llm_inputs={"argument": argument}, - trace_id=trace_id, **kwargs, ) ).content -def refiner(query: str, additional_description: str, current_arg: str, criticism: str, trace_id: Optional[str] = None, **kwargs) -> str: +@trace +def refiner(query: str, additional_description: str, current_arg: str, criticism: str, **kwargs) -> str: return p.completion( Completion( deployment_id="p--G2s9okMTWWWh3d8YqLY2", @@ -52,29 +51,30 @@ def refiner(query: str, additional_description: str, current_arg: str, criticism "current_arg": current_arg, "criticism": criticism, }, - trace_id=trace_id, **kwargs, ) ).content # This is the parent function which orchestrates the chaining. We'll define our trace_id and trace_name here +@trace def argument_chain(query: str, additional_description: str = "") -> str: - trace_id, trace_name = gen_trace_id(), "argument_chain" - argument = argument_generator(query, additional_description, trace_id, trace_name=trace_name) - criticism = critic(argument, trace_id) - return refiner(query, additional_description, argument, criticism, trace_id) + argument = argument_generator(query, additional_description) + criticism = critic(argument) + return refiner(query, additional_description, argument, criticism) +@trace def argument_chain2(query: str, additional_description: str = "") -> tuple[str, str]: - trace_id, trace_name = gen_trace_id(), "argument_chain" - argument = argument_generator(query, additional_description, trace_id, trace_name=trace_name) - criticism = critic(argument, trace_id) - return refiner(query, additional_description, argument, criticism, trace_id), trace_id + trace_id = get_current_trace_id() + argument = argument_generator(query, additional_description) + criticism = critic(argument) + return refiner(query, additional_description, argument, criticism), trace_id # let's return the full CompletionResponse to see what other information is returned -def refiner2(query: str, additional_description: str, current_arg: str, criticism: str, trace_id: Optional[str] = None, **kwargs) -> CompletionResponse: +@trace +def refiner2(query: str, additional_description: str, current_arg: str, criticism: str, **kwargs) -> CompletionResponse: return p.completion( Completion( deployment_id="p--G2s9okMTvBEh3d8YqLY2", @@ -85,23 +85,29 @@ def refiner2(query: str, additional_description: str, current_arg: str, criticis "current_arg": current_arg, "criticism": criticism, }, - trace_id=trace_id, **kwargs, ) ) +@trace( + tags=["cookbook-example", "feedback_tracked"], + metadata={"source": "python-sdk"}, +) def argument_chain3(query: str, additional_description: str = "") -> CompletionResponse: - trace_id, parent_trace_name = gen_trace_id(), "argument_chain" - tags = ["tutorial"] - metadata = {"githash": "e38f04c83"} - argument = argument_generator(query, additional_description, trace_id, trace_name=parent_trace_name, tags=tags, metadata=metadata) - criticism = critic(argument, trace_id) - return refiner2(query, additional_description, argument, criticism, trace_id) + argument = argument_generator(query, additional_description) + criticism = critic(argument) + return refiner2(query, additional_description, argument, criticism) if __name__ == "__main__": - result, trace_id = argument_chain2( + result = argument_chain( + "Whether moonshine is good for you.", + additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", + ) + print(result) + + result2, trace_id = argument_chain2( "Whether moonshine is good for you.", additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", ) @@ -112,4 +118,17 @@ def argument_chain3(query: str, additional_description: str = "") -> CompletionR target="Moonshine is wonderful. End of story.", ) ) - print(result) + print(result2) + + result3 = argument_chain3( + "Whether moonshine is good for you.", + additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", + ) + p.record_feedback( + FeedbackRequest( + trace_id=result3.trace_id, + score=0.7, # 0.0 (bad) to 1.0 (good) + target="Moonshine is wonderful. End of story.", + ) + ) + print(result3) diff --git a/parea/example.py b/parea/example.py deleted file mode 100644 index 56ab786c..00000000 --- a/parea/example.py +++ /dev/null @@ -1,176 +0,0 @@ -import asyncio -import os -from datetime import datetime - -from dotenv import load_dotenv - -from parea.client import Parea -from parea.schemas.models import Completion, CompletionResponse, UseDeployedPrompt, UseDeployedPromptResponse -from parea.trace_utils.trace import trace_insert, traceable - -load_dotenv() - -p = Parea(api_key=os.getenv("DEV_API_KEY")) - - -@traceable -def main(llm_inputs, metadata): - # You will find this deployment_id in the Parea dashboard - deployment_id = os.getenv("DEV_DEPLOYMENT_ID") - - # You can easily unpack a dictionary into an attrs class - test_completion = Completion(**{"deployment_id": deployment_id, "llm_inputs": llm_inputs, "metadata": metadata}) - completion_response: CompletionResponse = p.completion(data=test_completion) - print(completion_response) - - # By passing in my inputs, in addition to the raw message with unfilled variables {{x}} and {{y}}, - # you we will also get the filled-in prompt: - # {"role": "user", "content": "Write a hello world program using Golang and the Fiber framework."} - test_get_prompt = UseDeployedPrompt(deployment_id=deployment_id, llm_inputs=llm_inputs) - deployed_prompt: UseDeployedPromptResponse = p.get_prompt(data=test_get_prompt) - print("\n\n") - return completion_response, deployed_prompt - - -# @traceable -# async def main_async(): -# completion_response: CompletionResponse = await p.acompletion(data=test_completion) -# print(completion_response) -# deployed_prompt: UseDeployedPromptResponse = await p.aget_prompt(data=test_get_prompt) -# print("\n\n") -# print(deployed_prompt) - -# -# def hello(name: str) -> str: -# return f"Hello {name}!" - - -@traceable -def run_child1(x): - return 1 + x - - -@traceable -def run_child2(y): - return run_grand_child1(y) + y - - -@traceable -def run_grand_child1(z): - # Add metadata to the trace data for this function - trace_insert({"metadata": {"internal": True, "tokens": 3}}) - return 3 * z - - -@traceable -def parent(x, y): - answer1 = run_child1(x) - answer2 = run_child2(y) - return (answer1 + answer2) / 2 - - -@traceable -def parent2(x, y): - return (x + y) / 2 - - -@traceable -async def arun_child1(x): - await asyncio.sleep(1) # simulate IO-bound operation - return 1 + x - - -@traceable -async def arun_child2(y): - res = await arun_grand_child1(y) - return res + y - - -@traceable -async def arun_grand_child1(z): - await asyncio.sleep(1) # simulate IO-bound operation - trace_insert({"metadata": {"internal": True, "tokens": 3}}) - return 3 * z - - -@traceable -async def aparent(x, y): - answer1 = await arun_child1(x) - answer2 = await arun_child2(y) - return (answer1 + answer2) / 2 - - -@traceable -async def aparent2(x, y): - return (x + y) / 2 - - -def retester_main(): - parent(6, 2) - parent(3, 4) - parent2(3, 12) - - -async def atester_main(): - await aparent(6, 2) - await aparent(3, 4) - await aparent2(3, 12) - - -@traceable -def argument_generator(query: str, additional_description: str = "") -> str: - return p.completion( - Completion( - deployment_id="p-ee6hsbh1_4WtIz6UO6rEA", - llm_inputs={ - "additional_description": additional_description, - "date": f"{datetime.now()}", - "query": query, - }, - ) - ).content - - -@traceable -def critic(argument: str) -> str: - return p.completion( - Completion( - deployment_id="p-_4w8th0eJlWAx9g8g20Ov", - llm_inputs={"argument": argument}, - end_user_identifier="user_1", - metadata={"githash": "e38f04c83"}, - tags=["tutorial"], - target="you're right, i give up", - ) - ).content - - -@traceable -def refiner(query: str, additional_description: str, current_arg: str, criticism: str) -> str: - return p.completion( - Completion( - deployment_id="p-k2Iuvik12X_Uk4y-fOFPp", - llm_inputs={ - "additional_description": additional_description, - "date": f"{datetime.now()}", - "query": query, - "current_arg": current_arg, - "criticism": criticism, - }, - ) - ).content - - -@traceable -def argument_chain(query: str, additional_description: str = "") -> str: - argument = argument_generator(query, additional_description) - criticism = critic(argument) - return refiner(query, additional_description, argument, criticism) - - -if __name__ == "__main__": - result = argument_chain( - "Whether sunshine is good for you.", - additional_description="Provide a concise, few sentence argument on why sunshine is good for you.", - ) - # retester_main() diff --git a/parea/parea_logger.py b/parea/parea_logger.py index 31c92757..2a90dc77 100644 --- a/parea/parea_logger.py +++ b/parea/parea_logger.py @@ -14,7 +14,6 @@ def set_client(self, client: HTTPClient) -> None: self._client = client def record_log(self, data: TraceLog) -> None: - print(f"Logging to database: {data}") self._client.request( "POST", LOG_ENDPOINT, diff --git a/parea/trace_utils/log_tree.py b/parea/trace_utils/log_tree.py deleted file mode 100644 index de319d8d..00000000 --- a/parea/trace_utils/log_tree.py +++ /dev/null @@ -1,52 +0,0 @@ -from typing import Dict, List - -import json -import logging - -from attrs import asdict - -from parea.schemas.models import Completion, PartialLog - -logger = logging.getLogger() - - -def build_trees(db_entries: list[PartialLog]) -> list[PartialLog]: - entries_by_id: dict[str, PartialLog] = {entry.inference_id: entry for entry in db_entries} - all_child_ids = {child_id for entry in db_entries for child_id in entry.children} - root_ids = set(entries_by_id.keys()) - all_child_ids - - def build_subtree(entry_id: str) -> PartialLog: - entry: PartialLog = entries_by_id[entry_id] - - if entry.llm_inputs: - for k, v in entry.llm_inputs.items(): - if isinstance(v, Completion): - entry.llm_inputs[k] = asdict(v) - - subtree = PartialLog( - **{ - "inference_id": entry.inference_id, - "name": entry.trace_name, - "start_timestamp": entry.start_timestamp, - "llm_inputs": entry.llm_inputs, - "output": entry.output, - "end_timestamp": entry.end_timestamp, - "children": [build_subtree(child_id) for child_id in entry.children], - "metadata": entry.metadata, - "tags": entry.tags, - "target": entry.target, - "end_user_identifier": entry.end_user_identifier, - } - ) - - return subtree - - return [build_subtree(root_id) for root_id in root_ids] - - -def output_trace_data(db_entries: list[PartialLog]): - trees: list[PartialLog] = build_trees(db_entries) - for i, tree in enumerate(trees, start=1): - print(f"Tree {i}:") - print(tree) - print(json.dumps(asdict(tree), indent=2)) diff --git a/parea/trace_utils/run_helpers.py b/parea/trace_utils/run_helpers.py deleted file mode 100644 index c005f396..00000000 --- a/parea/trace_utils/run_helpers.py +++ /dev/null @@ -1,563 +0,0 @@ -"""Decorator for creating a run tree from functions.""" -from typing import Any, Callable, Dict, List, Optional, TypedDict, Union - -import contextvars -import inspect -import logging -import os -from collections.abc import Generator, Mapping -from concurrent.futures import ThreadPoolExecutor -from contextlib import contextmanager -from functools import wraps -from uuid import uuid4 - -from parea.client_two import ID_TYPE, Client -from parea.trace_utils.run_trees import RunTree - -logger = logging.getLogger(__name__) -_PARENT_RUN_TREE = contextvars.ContextVar[Optional[RunTree]]("_PARENT_RUN_TREE", default=None) -_PROJECT_NAME = contextvars.ContextVar[Optional[str]]("_PROJECT_NAME", default=None) - - -def get_run_tree_context() -> Optional[RunTree]: - """Get the current run tree context.""" - return _PARENT_RUN_TREE.get() - - -def _get_inputs(signature: inspect.Signature, *args: Any, **kwargs: Any) -> dict[str, Any]: - """Return a dictionary of inputs from the function signature.""" - bound = signature.bind_partial(*args, **kwargs) - bound.apply_defaults() - arguments = dict(bound.arguments) - arguments.pop("self", None) - arguments.pop("cls", None) - for param_name, param in signature.parameters.items(): - if param.kind == inspect.Parameter.VAR_KEYWORD: - # Update with the **kwargs, and remove the original entry - # This is to help flatten out keyword arguments - if param_name in arguments: - arguments.update(arguments[param_name]) - arguments.pop(param_name) - - return arguments - - -class PareaExtra(TypedDict): - """Any additional info to be injected into the run dynamically.""" - - reference_example_id: Optional[ID_TYPE] - run_extra: Optional[dict] - run_tree: Optional[RunTree] - project_name: Optional[str] - metadata: Optional[dict[str, Any]] - tags: Optional[list[str]] - run_id: Optional[ID_TYPE] - - -def traceable( - run_type: str, - *, - name: Optional[str] = None, - extra: Optional[dict] = None, - executor: Optional[ThreadPoolExecutor] = None, - metadata: Optional[Mapping[str, Any]] = None, - tags: Optional[list[str]] = None, -) -> Callable: - """Decorator for creating or adding a run to a run tree.""" - extra_outer = extra or {} - - def decorator(func: Callable): - @wraps(func) - async def async_wrapper( - *args: Any, - langsmith_extra: Optional[Union[PareaExtra, dict]] = None, - **kwargs: Any, - ) -> Any: - """Async version of wrapper function""" - outer_project = _PROJECT_NAME.get() or os.environ.get("PAREA_PROJECT", os.environ.get("PAREA_PROJECT", "default")) - langsmith_extra = langsmith_extra or {} - run_tree = langsmith_extra.get("run_tree", kwargs.get("run_tree", None)) - project_name_ = langsmith_extra.get("project_name", outer_project) - run_extra = langsmith_extra.get("run_extra", None) - reference_example_id = langsmith_extra.get("reference_example_id", None) - if run_tree is None: - parent_run_ = _PARENT_RUN_TREE.get() - else: - parent_run_ = run_tree - signature = inspect.signature(func) - name_ = name or func.__name__ - docstring = func.__doc__ - if run_extra: - extra_inner = {**extra_outer, **run_extra} - else: - extra_inner = extra_outer - metadata_ = {**(metadata or {}), **(langsmith_extra.get("metadata") or {})} - if metadata_: - extra_inner["metadata"] = metadata_ - inputs = _get_inputs(signature, *args, **kwargs) - tags_ = (tags or []) + (langsmith_extra.get("tags") or []) - id_ = langsmith_extra.get("run_id", uuid4()) - if parent_run_ is not None: - new_run = parent_run_.create_child( - name=name_, - run_type=run_type, - serialized={ - "name": name, - "signature": str(signature), - "doc": docstring, - }, - inputs=inputs, - tags=tags_, - extra=extra_inner, - run_id=id_, - ) - else: - new_run = RunTree( - id=id_, - name=name_, - serialized={ - "name": name, - "signature": str(signature), - "doc": docstring, - }, - inputs=inputs, - run_type=run_type, - reference_example_id=reference_example_id, - project_name=project_name_, - extra=extra_inner, - tags=tags_, - executor=executor, - client=Client(api_key=os.getenv("DEV_API_KEY")), - ) - new_run.post() - _PROJECT_NAME.set(project_name_) - _PARENT_RUN_TREE.set(new_run) - func_accepts_parent_run = inspect.signature(func).parameters.get("run_tree", None) is not None - try: - if func_accepts_parent_run: - function_result = await func(*args, run_tree=new_run, **kwargs) - else: - function_result = await func(*args, **kwargs) - except Exception as e: - new_run.end(error=str(e)) - new_run.patch() - _PARENT_RUN_TREE.set(parent_run_) - _PROJECT_NAME.set(outer_project) - raise e - _PARENT_RUN_TREE.set(parent_run_) - _PROJECT_NAME.set(outer_project) - if isinstance(function_result, dict): - new_run.end(outputs=function_result) - else: - new_run.end(outputs={"output": function_result}) - new_run.patch() - return function_result - - @wraps(func) - def wrapper( - *args: Any, - langsmith_extra: Optional[Union[PareaExtra, dict]] = None, - **kwargs: Any, - ) -> Any: - """Create a new run or create_child() if run is passed in kwargs.""" - outer_project = _PROJECT_NAME.get() or os.environ.get("PAREA_PROJECT", os.environ.get("PAREA_PROJECT", "default")) - langsmith_extra = langsmith_extra or {} - run_tree = langsmith_extra.get("run_tree", kwargs.get("run_tree", None)) - project_name_ = langsmith_extra.get("project_name", outer_project) - run_extra = langsmith_extra.get("run_extra", None) - reference_example_id = langsmith_extra.get("reference_example_id", None) - if run_tree is None: - parent_run_ = _PARENT_RUN_TREE.get() - else: - parent_run_ = run_tree - signature = inspect.signature(func) - name_ = name or func.__name__ - docstring = func.__doc__ - if run_extra: - extra_inner = {**extra_outer, **run_extra} - else: - extra_inner = extra_outer - metadata_ = {**(metadata or {}), **(langsmith_extra.get("metadata") or {})} - if metadata_: - extra_inner["metadata"] = metadata_ - inputs = _get_inputs(signature, *args, **kwargs) - tags_ = (tags or []) + (langsmith_extra.get("tags") or []) - id_ = langsmith_extra.get("run_id", uuid4()) - if parent_run_ is not None: - new_run = parent_run_.create_child( - name=name_, - run_id=id_, - run_type=run_type, - serialized={ - "name": name, - "signature": str(signature), - "doc": docstring, - }, - inputs=inputs, - tags=tags_, - extra=extra_inner, - ) - else: - new_run = RunTree( - name=name_, - id=id_, - serialized={ - "name": name, - "signature": str(signature), - "doc": docstring, - }, - inputs=inputs, - run_type=run_type, - reference_example_id=reference_example_id, - project_name=project_name_, - extra=extra_inner, - tags=tags_, - executor=executor, - ) - new_run.post() - _PARENT_RUN_TREE.set(new_run) - _PROJECT_NAME.set(project_name_) - func_accepts_parent_run = inspect.signature(func).parameters.get("run_tree", None) is not None - try: - if func_accepts_parent_run: - function_result = func(*args, run_tree=new_run, **kwargs) - else: - function_result = func(*args, **kwargs) - except Exception as e: - new_run.end(error=str(e)) - new_run.patch() - _PARENT_RUN_TREE.set(parent_run_) - _PROJECT_NAME.set(outer_project) - raise e - _PARENT_RUN_TREE.set(parent_run_) - _PROJECT_NAME.set(outer_project) - if isinstance(function_result, dict): - new_run.end(outputs=function_result) - else: - new_run.end(outputs={"output": function_result}) - new_run.patch() - return function_result - - if inspect.iscoroutinefunction(func): - return async_wrapper - else: - return wrapper - - return decorator - - -@contextmanager -def trace( - name: str, - run_type: str, - *, - inputs: Optional[dict] = None, - extra: Optional[dict] = None, - executor: Optional[ThreadPoolExecutor] = None, - project_name: Optional[str] = None, - run_tree: Optional[RunTree] = None, - tags: Optional[list[str]] = None, - metadata: Optional[Mapping[str, Any]] = None, -) -> Generator[RunTree, None, None]: - """Context manager for creating a run tree.""" - extra_outer = extra or {} - if metadata: - extra_outer["metadata"] = metadata - parent_run_ = _PARENT_RUN_TREE.get() if run_tree is None else run_tree - outer_project = _PROJECT_NAME.get() or os.environ.get("PAREA_PROJECT", os.environ.get("PAREA_PROJECT", "default")) - project_name_ = project_name or outer_project - if parent_run_ is not None: - new_run = parent_run_.create_child( - name=name, - run_type=run_type, - extra=extra_outer, - inputs=inputs, - tags=tags, - ) - else: - new_run = RunTree( - name=name, - run_type=run_type, - extra=extra_outer, - executor=executor, - project_name=project_name_, - inputs=inputs or {}, - tags=tags, - ) - new_run.post() - _PARENT_RUN_TREE.set(new_run) - _PROJECT_NAME.set(project_name_) - try: - yield new_run - except Exception as e: - new_run.end(error=str(e)) - new_run.patch() - _PARENT_RUN_TREE.set(parent_run_) - _PROJECT_NAME.set(outer_project) - raise e - _PARENT_RUN_TREE.set(parent_run_) - _PROJECT_NAME.set(outer_project) - if new_run.end_time is None: - # User didn't call end() on the run, so we'll do it for them - new_run.end() - new_run.patch() - - -# import contextvars -# import inspect -# import logging -# import os -# from concurrent.futures import ThreadPoolExecutor -# from contextlib import contextmanager -# from datetime import datetime -# from enum import Enum -# from functools import wraps -# from typing import Any, Callable, Dict, Generator, List, Mapping, Optional, Union, TypedDict -# from uuid import uuid4 -# -# from parea.client_two import ID_TYPE, Client -# from parea.run_trees import RunTree -# -# logger = logging.getLogger(__name__) -# _PARENT_RUN_TREE = contextvars.ContextVar[Optional[RunTree]]("_PARENT_RUN_TREE", default=None) -# _PROJECT_NAME = contextvars.ContextVar[Optional[str]]("_PROJECT_NAME", default=None) -# -# -# def get_run_tree_context() -> Optional[RunTree]: -# """Get the current run tree context.""" -# return _PARENT_RUN_TREE.get() -# -# -# def _get_inputs(signature: inspect.Signature, *args: Any, **kwargs: Any) -> Dict[str, Any]: -# """Return a dictionary of inputs from the function signature.""" -# bound = signature.bind_partial(*args, **kwargs) -# bound.apply_defaults() -# arguments = dict(bound.arguments) -# arguments.pop("self", None) -# arguments.pop("cls", None) -# for param_name, param in signature.parameters.items(): -# if param.kind == inspect.Parameter.VAR_KEYWORD: -# # Update with the **kwargs, and remove the original entry -# # This is to help flatten out keyword arguments -# if param_name in arguments: -# arguments.update(arguments[param_name]) -# arguments.pop(param_name) -# -# return arguments -# -# -# class PareaExtra(TypedDict): -# """Any additional info to be injected into the run dynamically.""" -# -# reference_example_id: Optional[ID_TYPE] -# run_extra: Optional[Dict] -# run_tree: Optional[RunTree] -# project_name: Optional[str] -# metadata: Optional[Dict[str, Any]] -# tags: Optional[List[str]] -# run_id: Optional[ID_TYPE] -# -# -# class RunTypeEnum(str, Enum): -# """Enum for run types.""" -# -# tool = "tool" -# chain = "chain" -# llm = "llm" -# retriever = "retriever" -# embedding = "embedding" -# prompt = "prompt" -# parser = "parser" -# -# -# def _get_outer_project() -> Optional[str]: -# return _PROJECT_NAME.get() or os.environ.get("PAREA_PROJECT", os.environ.get("PAREA_PROJECT", "default")) -# -# -# def _get_project_name(langsmith_extra: Optional[Union[PareaExtra, Dict]], outer_project: Optional[str]) -> Optional[str]: -# return langsmith_extra.get("project_name", outer_project) if langsmith_extra else outer_project -# -# -# def _get_parent_run(run_tree: Optional[RunTree]) -> Optional[RunTree]: -# return _PARENT_RUN_TREE.get() if run_tree is None else run_tree -# -# -# def _get_run_extra(langsmith_extra: Optional[Union[PareaExtra, Dict]], extra_outer: Optional[Dict]) -> Optional[Dict]: -# run_extra = langsmith_extra.get("run_extra", None) if langsmith_extra else None -# if run_extra: -# return {**extra_outer, **run_extra} -# else: -# return extra_outer -# -# -# def _get_metadata(langsmith_extra: Optional[Union[PareaExtra, Dict]], metadata: Optional[Mapping[str, Any]]) -> Optional[Dict[str, Any]]: -# metadata_ = {**(metadata or {}), **(langsmith_extra.get("metadata") or {})} if langsmith_extra else {} -# if metadata_: -# return metadata_ -# return None -# -# -# def _get_tags(langsmith_extra: Optional[Union[PareaExtra, Dict]], tags: Optional[List[str]]) -> Optional[List[str]]: -# return (tags or []) + (langsmith_extra.get("tags") or []) if langsmith_extra else tags -# -# -# def _get_id(langsmith_extra: Optional[Union[PareaExtra, Dict]]) -> str: -# return langsmith_extra.get("run_id", uuid4()) if langsmith_extra else uuid4() -# -# -# def _get_func_accepts_parent_run(func: Callable) -> bool: -# return inspect.signature(func).parameters.get("run_tree", None) is not None -# -# -# async def _get_function_result(func: Callable, new_run: RunTree, func_accepts_parent_run: bool, *args: Any, **kwargs: Any) -> Any: -# if func_accepts_parent_run: -# return await func(*args, run_tree=new_run, **kwargs) -# else: -# return await func(*args, **kwargs) -# -# -# def _end_run(new_run: RunTree, function_result: Any) -> None: -# if isinstance(function_result, dict): -# new_run.end(outputs=function_result) -# else: -# new_run.end(outputs={"output": function_result}) -# -# -# def create_run_tree( -# run_type: RunTypeEnum, -# name: str, -# inputs: Dict[str, Any], -# extra: Optional[Dict] = None, -# tags: Optional[List[str]] = None, -# id_: Optional[str] = None, -# parent_run: Optional[RunTree] = None, -# executor: Optional[ThreadPoolExecutor] = None, -# reference_example_id: Optional[ID_TYPE] = None, -# start_time: Optional[datetime] = None, -# ) -> RunTree: -# """Helper function to create a new run tree or child run.""" -# if parent_run is not None: -# return parent_run.create_child( -# name=name, -# run_type=run_type, -# serialized={"name": name}, -# inputs=inputs, -# tags=tags, -# extra=extra, -# run_id=id_, -# ) -# else: -# return RunTree( -# name=name, -# id=id_, -# serialized={"name": name}, -# inputs=inputs, -# run_type=run_type, -# reference_example_id=reference_example_id, -# start_time=start_time or datetime.utcnow(), -# extra=extra, -# tags=tags, -# executor=executor, -# client=Client(api_key=os.getenv("DEV_API_KEY")), -# ) -# -# -# def traceable( -# run_type: RunTypeEnum, -# *, -# name: Optional[str] = None, -# extra: Optional[Dict] = None, -# executor: Optional[ThreadPoolExecutor] = None, -# metadata: Optional[Mapping[str, Any]] = None, -# tags: Optional[List[str]] = None, -# ) -> Callable: -# """Decorator for creating or adding a run to a run tree.""" -# extra_outer = extra or {} -# -# def decorator(func: Callable): -# @wraps(func) -# async def async_wrapper( -# *args: Any, -# langsmith_extra: Optional[Union[PareaExtra, Dict]] = None, -# **kwargs: Any, -# ) -> Any: -# """Async version of wrapper function""" -# outer_project = _get_outer_project() -# project_name_ = _get_project_name(langsmith_extra, outer_project) -# parent_run_ = _get_parent_run(langsmith_extra.get("run_tree", kwargs.get("run_tree", None)) if langsmith_extra else None) -# signature = inspect.signature(func) -# name_ = name or func.__name__ -# docstring = func.__doc__ -# extra_inner = _get_run_extra(langsmith_extra, extra_outer) -# metadata_ = _get_metadata(langsmith_extra, metadata) -# if metadata_: -# extra_inner["metadata"] = metadata_ -# inputs = _get_inputs(signature, *args, **kwargs) -# tags_ = _get_tags(langsmith_extra, tags) -# id_ = _get_id(langsmith_extra) -# new_run = create_run_tree(run_type, name_, inputs, extra_inner, tags_, id_, parent_run_, project_name_, executor) -# new_run.post() -# _PROJECT_NAME.set(project_name_) -# _PARENT_RUN_TREE.set(new_run) -# func_accepts_parent_run = _get_func_accepts_parent_run(func) -# try: -# function_result = await _get_function_result(func, new_run, func_accepts_parent_run, *args, **kwargs) -# except Exception as e: -# new_run.end(error=str(e)) -# new_run.patch() -# _PARENT_RUN_TREE.set(parent_run_) -# _PROJECT_NAME.set(outer_project) -# raise e -# _PARENT_RUN_TREE.set(parent_run_) -# _PROJECT_NAME.set(outer_project) -# _end_run(new_run, function_result) -# new_run.patch() -# return function_result -# -# return async_wrapper -# -# return decorator -# -# -# @contextmanager -# def trace( -# name: str, -# run_type: RunTypeEnum, -# *, -# inputs: Optional[Dict] = None, -# extra: Optional[Dict] = None, -# executor: Optional[ThreadPoolExecutor] = None, -# project_name: Optional[str] = None, -# run_tree: Optional[RunTree] = None, -# tags: Optional[List[str]] = None, -# metadata: Optional[Mapping[str, Any]] = None, -# ) -> Generator[RunTree, None, None]: -# """Context manager for creating a run tree.""" -# extra_outer = extra or {} -# outer_project = _get_outer_project() -# project_name_ = project_name or outer_project -# parent_run_ = _get_parent_run(run_tree) -# extra_inner = _get_run_extra(None, extra_outer) -# metadata_ = _get_metadata(None, metadata) -# if metadata_: -# extra_inner["metadata"] = metadata_ -# new_run = create_run_tree( -# run_type, name, inputs or {}, extra_inner, tags, str(uuid4()), parent_run_, project_name_, executor -# ) -# new_run.post() -# _PROJECT_NAME.set(project_name_) -# _PARENT_RUN_TREE.set(new_run) -# try: -# yield new_run -# except Exception as e: -# new_run.end(error=str(e)) -# new_run.patch() -# _PARENT_RUN_TREE.set(parent_run_) -# _PROJECT_NAME.set(outer_project) -# raise e -# _PARENT_RUN_TREE.set(parent_run_) -# _PROJECT_NAME.set(outer_project) -# if new_run.end_time is None: -# # User didn't call end() on the run, so we'll do it for them -# new_run.end() -# new_run.patch() diff --git a/parea/trace_utils/run_trees.py b/parea/trace_utils/run_trees.py deleted file mode 100644 index c8cbd0ec..00000000 --- a/parea/trace_utils/run_trees.py +++ /dev/null @@ -1,423 +0,0 @@ -from typing import Any, Dict, List, Optional, cast - -import logging -import os -from concurrent.futures import Future, ThreadPoolExecutor, wait -from datetime import datetime -from enum import Enum -from uuid import UUID, uuid4 - -from parea.client_two import ID_TYPE, Client, get_runtime_environment - -try: - from pydantic.v1 import BaseModel, Field, PrivateAttr, root_validator, validator # type: ignore[import] -except ImportError: - from pydantic import BaseModel, Field, PrivateAttr, StrictBool, StrictFloat, StrictInt, root_validator, validator - -logger = logging.getLogger(__name__) - - -class RunTypeEnum(str, Enum): - """(Deprecated) Enum for run types. Use string directly.""" - - tool = "tool" - chain = "chain" - llm = "llm" - retriever = "retriever" - embedding = "embedding" - prompt = "prompt" - parser = "parser" - - -class RunBase(BaseModel): - """Base Run schema.""" - - id: UUID - name: str - start_time: datetime - run_type: str - """The type of run, such as tool, chain, llm, retriever, - embedding, prompt, parser.""" - end_time: Optional[datetime] = None - extra: Optional[dict] = None - error: Optional[str] = None - serialized: Optional[dict] - events: Optional[list[dict]] = None - inputs: dict - outputs: Optional[dict] = None - reference_example_id: Optional[UUID] = None - parent_run_id: Optional[UUID] = None - tags: Optional[list[str]] = None - - -class Run(RunBase): - """Run schema when loading from the DB.""" - - execution_order: int - """The execution order of the run within a run trace.""" - session_id: Optional[UUID] = None - """The project ID this run belongs to.""" - child_run_ids: Optional[list[UUID]] = None - """The child run IDs of this run.""" - child_runs: Optional[list["Run"]] = None - """The child runs of this run, if instructed to load using the client - These are not populated by default, as it is a heavier query to make.""" - feedback_stats: Optional[dict[str, Any]] = None - """Feedback stats for this run.""" - app_path: Optional[str] = None - """Relative URL path of this run within the app.""" - _host_url: Optional[str] = PrivateAttr(default=None) - - def __init__(self, _host_url: Optional[str] = None, **kwargs: Any) -> None: - """Initialize a Run object.""" - super().__init__(**kwargs) - self._host_url = _host_url - - @property - def url(self) -> Optional[str]: - """URL of this run within the app.""" - if self._host_url and self.app_path: - return f"{self._host_url}{self.app_path}" - return None - - -def _make_thread_pool() -> ThreadPoolExecutor: - """Ensure a thread pool exists in the current context.""" - return ThreadPoolExecutor(max_workers=1) - - -class RunTree(RunBase): - """Run Schema with back-references for posting runs.""" - - name: str - id: UUID = Field(default_factory=uuid4) - start_time: datetime = Field(default_factory=datetime.utcnow) - parent_run: Optional["RunTree"] = Field(default=None, exclude=True) - child_runs: list["RunTree"] = Field( - default_factory=list, - exclude={"__all__": {"parent_run_id"}}, - ) - session_name: str = Field( - default_factory=lambda: os.environ.get( - # TODO: Deprecate PAREA_SESSION - "PAREA_PROJECT", - os.environ.get("PAREA_SESSION", "default"), - ), - alias="project_name", - ) - session_id: Optional[UUID] = Field(default=None, alias="project_id") - execution_order: int = 1 - child_execution_order: int = Field(default=1, exclude=True) - extra: dict = Field(default_factory=dict) - client: Client = Field(default_factory=Client, exclude=True) - executor: ThreadPoolExecutor = Field(default_factory=_make_thread_pool, exclude=True) - _futures: list[Future] = PrivateAttr(default_factory=list) - - class Config: - arbitrary_types_allowed = True - allow_population_by_field_name = True - - @validator("executor", pre=True) - def validate_executor(cls, v: Optional[ThreadPoolExecutor]) -> ThreadPoolExecutor: - """Ensure the executor is running.""" - if v is None: - return _make_thread_pool() - if v._shutdown: - raise ValueError("Executor has been shutdown.") - return v - - @root_validator(pre=True) - def infer_defaults(cls, values: dict) -> dict: - """Assign name to the run.""" - if "serialized" not in values: - values["serialized"] = {"name": values["name"]} - if "execution_order" not in values: - values["execution_order"] = 1 - if "child_execution_order" not in values: - values["child_execution_order"] = values["execution_order"] - if values.get("parent_run") is not None: - values["parent_run_id"] = values["parent_run"].id - extra = cast(dict, values.setdefault("extra", {})) - runtime = cast(dict, extra.setdefault("runtime", {})) - runtime.update(get_runtime_environment()) - return values - - def end( - self, - *, - outputs: Optional[dict] = None, - error: Optional[str] = None, - end_time: Optional[datetime] = None, - ) -> None: - """Set the end time of the run and all child runs.""" - self.end_time = end_time or datetime.utcnow() - if outputs is not None: - self.outputs = outputs - if error is not None: - self.error = error - if self.parent_run: - self.parent_run.child_execution_order = max( - self.parent_run.child_execution_order, - self.child_execution_order, - ) - - def create_child( - self, - name: str, - run_type: str, - *, - run_id: Optional[ID_TYPE] = None, - serialized: Optional[dict] = None, - inputs: Optional[dict] = None, - outputs: Optional[dict] = None, - error: Optional[str] = None, - reference_example_id: Optional[UUID] = None, - start_time: Optional[datetime] = None, - end_time: Optional[datetime] = None, - tags: Optional[list[str]] = None, - extra: Optional[dict] = None, - ) -> "RunTree": - """Add a child run to the run tree.""" - execution_order = self.child_execution_order + 1 - serialized_ = serialized or {"name": name} - run = RunTree( - name=name, - id=run_id or uuid4(), - serialized=serialized_, - inputs=inputs or {}, - outputs=outputs or {}, - error=error, - run_type=run_type, - reference_example_id=reference_example_id, - start_time=start_time or datetime.utcnow(), - end_time=end_time, - execution_order=execution_order, - child_execution_order=execution_order, - extra=extra or {}, - parent_run=self, - session_name=self.session_name, - client=self.client, - executor=self.executor, - tags=tags, - ) - self.child_runs.append(run) - return run - - def post(self, exclude_child_runs: bool = True) -> Future: - """Post the run tree to the API asynchronously.""" - exclude = {"child_runs"} if exclude_child_runs else None - kwargs = self.dict(exclude=exclude, exclude_none=True) - self._futures.append( - self.executor.submit( - self.client.create_run, - **kwargs, - ) - ) - return self._futures[-1] - - def patch(self) -> Future: - """Patch the run tree to the API in a background thread.""" - self._futures.append( - self.executor.submit( - self.client.update_run, - run_id=self.id, - outputs=self.outputs.copy() if self.outputs else None, - error=self.error, - parent_run_id=self.parent_run_id, - reference_example_id=self.reference_example_id, - ) - ) - return self._futures[-1] - - def wait(self) -> None: - """Wait for all _futures to complete.""" - futures = self._futures - wait(self._futures) - for future in futures: - self._futures.remove(future) - - -# import logging -# import os -# from concurrent.futures import Future, ThreadPoolExecutor, as_completed -# from dataclasses import dataclass, field -# from datetime import datetime -# from enum import Enum -# from functools import lru_cache -# from typing import Dict, List, Optional, Any -# from uuid import uuid4 -# -# from parea.client_two import Client, get_runtime_environment, ID_TYPE -# -# logger = logging.getLogger(__name__) -# -# # Using Enum for run types. It prevents invalid values and improves code readability. -# class RunTypeEnum(str, Enum): -# tool = "tool" -# chain = "chain" -# llm = "llm" -# retriever = "retriever" -# embedding = "embedding" -# prompt = "prompt" -# parser = "parser" -# -# -# @dataclass -# class RunBase: -# """Base Run schema.""" -# -# id: str -# name: str -# start_time: datetime -# run_type: RunTypeEnum -# end_time: Optional[datetime] = None -# extra: Optional[dict] = None -# error: Optional[str] = None -# serialized: Optional[dict] = None -# events: Optional[List[Dict]] = None -# inputs: dict = field(default_factory=dict) -# outputs: Optional[dict] = None -# reference_example_id: Optional[str] = None -# parent_run_id: Optional[str] = None -# tags: Optional[List[str]] = None -# -# -# @dataclass -# class Run(RunBase): -# """Run schema when loading from the DB.""" -# -# execution_order: Optional[int] = None -# session_id: Optional[str] = None -# child_run_ids: Optional[List[str]] = None -# child_runs: Optional[List["Run"]] = None -# feedback_stats: Optional[Dict[str, Any]] = None -# app_path: Optional[str] = None -# _host_url: Optional[str] = None -# -# @property -# def url(self) -> Optional[str]: -# """URL of this run within the app.""" -# if self._host_url and self.app_path: -# return f"{self._host_url}{self.app_path}" -# return None -# -# -# @lru_cache -# def _make_thread_pool() -> ThreadPoolExecutor: -# """Ensure a thread pool exists in the current context.""" -# return ThreadPoolExecutor(max_workers=1) -# -# -# @dataclass -# class RunTree(RunBase): -# """Run Schema with back-references for posting runs.""" -# -# parent_run: Optional["RunTree"] = None -# child_runs: List["RunTree"] = field(default_factory=list) -# session_name: str = field(default_factory=lambda: os.environ.get("PAREA_PROJECT", os.environ.get("PAREA_SESSION", "default"))) -# session_id: Optional[str] = None -# execution_order: int = 1 -# child_execution_order: int = 1 -# extra: Dict = field(default_factory=dict) -# client: Client = field(default_factory=Client) -# executor: ThreadPoolExecutor = field(default_factory=_make_thread_pool) -# _futures: List[Future] = field(default_factory=list) -# -# def __post_init__(self): -# """Assign name to the run.""" -# if self.serialized is None: -# self.serialized = {"name": self.name} -# if self.extra is None: -# self.extra = {} -# runtime = self.extra.setdefault("runtime", {}) -# runtime.update(get_runtime_environment()) -# -# def end( -# self, -# *, -# outputs: Optional[Dict] = None, -# error: Optional[str] = None, -# end_time: Optional[datetime] = None, -# ) -> None: -# """Set the end time of the run and all child runs.""" -# self.end_time = end_time or datetime.utcnow() -# if outputs is not None: -# self.outputs = outputs -# if error is not None: -# self.error = error -# if self.parent_run: -# self.parent_run.child_execution_order = max( -# self.parent_run.child_execution_order, -# self.child_execution_order, -# ) -# -# def create_child( -# self, -# name: str, -# run_type: RunTypeEnum, -# *, -# run_id: Optional[ID_TYPE] = None, -# serialized: Optional[Dict] = None, -# inputs: Optional[Dict] = None, -# outputs: Optional[Dict] = None, -# error: Optional[str] = None, -# reference_example_id: Optional[str] = None, -# start_time: Optional[datetime] = None, -# end_time: Optional[datetime] = None, -# tags: Optional[List[str]] = None, -# extra: Optional[Dict] = None, -# ) -> "RunTree": -# """Add a child run to the run tree.""" -# execution_order = self.child_execution_order + 1 -# serialized_ = serialized or {"name": name} -# run = RunTree( -# name=name, -# id=run_id or str(uuid4()), -# serialized=serialized_, -# inputs=inputs or {}, -# outputs=outputs or {}, -# error=error, -# run_type=run_type, -# reference_example_id=reference_example_id, -# start_time=start_time or datetime.utcnow(), -# end_time=end_time, -# execution_order=execution_order, -# child_execution_order=execution_order, -# extra=extra or {}, -# parent_run=self, -# session_name=self.session_name, -# client=self.client, -# executor=self.executor, -# tags=tags, -# ) -# self.child_runs.append(run) -# return run -# -# def post(self, exclude_child_runs: bool = True) -> Future: -# """Post the run tree to the API asynchronously.""" -# self._futures.append( -# self.executor.submit( -# self.client.create_run, -# **self.__dict__, -# ) -# ) -# return self._futures[-1] -# -# def patch(self) -> Future: -# """Patch the run tree to the API in a background thread.""" -# self._futures.append( -# self.executor.submit( -# self.client.update_run, -# run_id=self.id, -# outputs=self.outputs, -# error=self.error, -# parent_run_id=self.parent_run_id, -# reference_example_id=self.reference_example_id, -# ) -# ) -# return self._futures[-1] -# -# def wait(self) -> None: -# """Wait for all _futures to complete.""" -# for future in as_completed(self._futures): -# self._futures.remove(future) diff --git a/parea/trace_utils/__init__.py b/parea/utils/__init__.py similarity index 100% rename from parea/trace_utils/__init__.py rename to parea/utils/__init__.py diff --git a/parea/trace_utils/trace.py b/parea/utils/trace_utils.py similarity index 97% rename from parea/trace_utils/trace.py rename to parea/utils/trace_utils.py index 0b686e7d..26acfbc4 100644 --- a/parea/trace_utils/trace.py +++ b/parea/utils/trace_utils.py @@ -38,8 +38,12 @@ def merge(old, new): return new +def get_current_trace_id(): + return trace_context.get()[-1] + + def trace_insert(data: dict[str, Any]): - current_trace_id = trace_context.get()[-1] + current_trace_id = get_current_trace_id() current_trace_data: TraceLog = trace_data.get()[current_trace_id] for key, new_value in data.items(): @@ -47,7 +51,7 @@ def trace_insert(data: dict[str, Any]): current_trace_data.__setattr__(key, merge(existing_value, new_value) if existing_value else new_value) -def traceable( +def trace( name: Optional[str] = None, tags: Optional[list[str]] = None, metadata: Optional[dict[str, Any]] = None, From 7522d8fa6e04db672620432236ab40d369c4de05 Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Thu, 24 Aug 2023 14:01:31 -0700 Subject: [PATCH 05/15] cleanup --- Makefile | 2 +- poetry.lock | 224 +++++++++++++++++++++++------------------------ pyproject.toml | 1 - requirements.txt | 149 +------------------------------ 4 files changed, 116 insertions(+), 260 deletions(-) diff --git a/Makefile b/Makefile index 86f0d3b5..4c0c8c27 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ poetry-remove: install: poetry lock -n && poetry export --without-hashes > requirements.txt poetry install -n - -#poetry run mypy --install-types --non-interactive ./ + poetry run mypy --install-types --non-interactive ./ .PHONY: pre-commit-install pre-commit-install: diff --git a/poetry.lock b/poetry.lock index 1e9d6090..6e692a0b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2847,18 +2847,18 @@ files = [ [[package]] name = "pydantic" -version = "2.2.1" +version = "2.3.0" description = "Data validation using Python type hints" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-2.2.1-py3-none-any.whl", hash = "sha256:0c88bd2b63ed7a5109c75ab180d55f58f80a4b559682406812d0684d3f4b9192"}, - {file = "pydantic-2.2.1.tar.gz", hash = "sha256:31b5cada74b2320999fb2577e6df80332a200ff92e7775a52448b6b036fce24a"}, + {file = "pydantic-2.3.0-py3-none-any.whl", hash = "sha256:45b5e446c6dfaad9444819a293b921a40e1db1aa61ea08aede0522529ce90e81"}, + {file = "pydantic-2.3.0.tar.gz", hash = "sha256:1607cc106602284cd4a00882986570472f193fde9cb1259bceeaedb26aa79a6d"}, ] [package.dependencies] annotated-types = ">=0.4.0" -pydantic-core = "2.6.1" +pydantic-core = "2.6.3" typing-extensions = ">=4.6.1" [package.extras] @@ -2866,117 +2866,117 @@ email = ["email-validator (>=2.0.0)"] [[package]] name = "pydantic-core" -version = "2.6.1" +version = "2.6.3" description = "" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic_core-2.6.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:f55001a689111a297c0006c46c0589cfd559261baaa9a37bc35eff05b8cae1a6"}, - {file = "pydantic_core-2.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bb6273068e9450c5c91f58dd277fbd406b896ffa30f0ef312edc5519d07f16ae"}, - {file = "pydantic_core-2.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:043212f21c75cb6ee3a92fffbc747410e32b08e1a419ce16a9da98a16d660a7c"}, - {file = "pydantic_core-2.6.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:db0c12f1e9d3bf658634621f3423486803d749fef77a64cfb4252f9d619e1817"}, - {file = "pydantic_core-2.6.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:81424dc05c4342a19fb64323bb9d4468e7407b745c00377ccc4d3dd96d5e02fe"}, - {file = "pydantic_core-2.6.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3c8f3aebaf92f088b1dafd7101d1ccca0459ae0f5b26017411b9969667d289a9"}, - {file = "pydantic_core-2.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd9f14454b4bc89c705ce17951f9c783db82efd2b44a424487c593e2269eef61"}, - {file = "pydantic_core-2.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2effc71653247e76c5b95d15c58d4ca3f591f42f714eb3b32df9d6ec613794a5"}, - {file = "pydantic_core-2.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:56672429f8a89d2a0f4402d912f0dad68c2d05f7c278d3152c6fb4a76c2a429a"}, - {file = "pydantic_core-2.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d0bf1c2545ab253732229c7fe8294d98eb08f99aa25a388267e1bc4d2d7e0a34"}, - {file = "pydantic_core-2.6.1-cp310-none-win32.whl", hash = "sha256:c5be947ad41a7602f941dc834d03e64dd1c7fae65fa85cb4f1004a95c5d50df1"}, - {file = "pydantic_core-2.6.1-cp310-none-win_amd64.whl", hash = "sha256:3d14ae98a8d251402ef8ed017039d2fc3e29fb155f909cd3816ba259fd30fb48"}, - {file = "pydantic_core-2.6.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:4a3c20808d3ced90e29439f72a563eadf21d29560935cc818b2dab80b92c114a"}, - {file = "pydantic_core-2.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:da240bbd8191edc6009e7793d5d4d67c55f56225c4788f068d6286c20e5a2038"}, - {file = "pydantic_core-2.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de1a3e56e34264d5216c67d2a48185216ada8f5f35a7f4c96a3971847c0de897"}, - {file = "pydantic_core-2.6.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9b623e09239ed333d14c02c9fcd1a7bb350b95eca8383f6e9b0d8e373d5a14b5"}, - {file = "pydantic_core-2.6.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a12520a6d502a25f6e47319874e47056b290f1b3c2ed9391444ce81c8cc5b83"}, - {file = "pydantic_core-2.6.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1141f18414aee8865c7917ae1432e419c1983272f53625152493692ff3d6783"}, - {file = "pydantic_core-2.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7888b3ee7566865cff3e9edab5d6cdf2e7cf793df17fe53d5e7be3e57eae45ec"}, - {file = "pydantic_core-2.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3bdf293b6304bc451678b7016c2505b7d97aa85ff13dac4420027b1b69e15d3d"}, - {file = "pydantic_core-2.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7ef56a05bb60336d5e795bf166d6712b2362e6478522c77e8336cb0da8909913"}, - {file = "pydantic_core-2.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3210eb73707e3487c16ef25cfd1663660f4e7d647a181d6c2fb18bc6167985fb"}, - {file = "pydantic_core-2.6.1-cp311-none-win32.whl", hash = "sha256:707e3005e8c129bdac117285b71717c13b9ed81a81eae0b1642f4ddc60028e63"}, - {file = "pydantic_core-2.6.1-cp311-none-win_amd64.whl", hash = "sha256:2b8ccec2189d8a8b83929f79e5bc00c0656f6c2ba4345125c0c82d1b77e15a26"}, - {file = "pydantic_core-2.6.1-cp311-none-win_arm64.whl", hash = "sha256:c1e44b77442fb5b1b6fccea30e3359b14d0a2e5896801243defe54482a591500"}, - {file = "pydantic_core-2.6.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:c82fb25f965f6777032fc2f2856c86149f7709c8f7fd0c020a8631b8211f2bab"}, - {file = "pydantic_core-2.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:494b211b12b8fedd184dbba609f6ed582e23561db57c1996fd6773989dbaef9b"}, - {file = "pydantic_core-2.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1281c940f47e5c89b594ef7580045647df1f9ad687edd503bcc0485be94576f4"}, - {file = "pydantic_core-2.6.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2d41701c88d8b678c16c10562949f2d28aceacd767cbe51dac9c8c41e6e609fb"}, - {file = "pydantic_core-2.6.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6a839c95d5cc91eed053d8dafde4e200c4bc82f56fb1cf7bbfaeb03e2d907929"}, - {file = "pydantic_core-2.6.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c22e4fbfb5823d0fcb2c20ed164b39c3588554f9635f70765e8c9cff0fef67ad"}, - {file = "pydantic_core-2.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2fed4ad60ccf2698bd04e95dfc3bd84149ced9605a29fd27d624701e1da300c"}, - {file = "pydantic_core-2.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33b9343aa464d60c31937b361abde08d3af9943f3eb09d3216211b6236bd40c4"}, - {file = "pydantic_core-2.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:56e4953cd911293d6d755e2a97c651826aca76201db8f1ee298939e703721390"}, - {file = "pydantic_core-2.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cd163109047ab41ef1ea34258b35beb3ccac90af2012927ee8ab6ff122fef671"}, - {file = "pydantic_core-2.6.1-cp312-none-win32.whl", hash = "sha256:f5b51ec04743c94288c46e3759769611ab7c5ce0f941113363da96d20d345fb6"}, - {file = "pydantic_core-2.6.1-cp312-none-win_amd64.whl", hash = "sha256:ca5606bd82e255b1d704a4334e5ebf05ae966b69686fae02dcd31c057bdcb113"}, - {file = "pydantic_core-2.6.1-cp312-none-win_arm64.whl", hash = "sha256:dfc8f534a21b60b00f87e5a4fc36b8b8945160a6cc9e7b6e67db541c766c9597"}, - {file = "pydantic_core-2.6.1-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:b1aed20778092f8334c8eaf91550fa2805221d5e9b40ebdd1f46ee7efc159a48"}, - {file = "pydantic_core-2.6.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:64ff7a4b7ee2a56735af28da76c5dacbba6995801080f739d14610f4aa3de35d"}, - {file = "pydantic_core-2.6.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2d8faedb138c704957642fdf154c94f1b3d2a15cbd2472e45665f80463e85ee"}, - {file = "pydantic_core-2.6.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:55aac69d7339a63e37164f0a629c3034becc6746d68d126118a3ee4493514bed"}, - {file = "pydantic_core-2.6.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dfdb1617af455a551be4cc0471f0bf3bfb1e882db71afad0e587c821326bb749"}, - {file = "pydantic_core-2.6.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aadc84f5bd7b1421b5a6b389ceff46062dd4a58c44cfb75990e9ca2d9d8270df"}, - {file = "pydantic_core-2.6.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1a01dce87507b9a8f1b71933ade85c573a22c9bd4649590e28d8a497afb68bd"}, - {file = "pydantic_core-2.6.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cd6f05f3e237ed6b3949464e7679e55843645fe0fe8d3b33277c321386836f6a"}, - {file = "pydantic_core-2.6.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:760f8a0aeb43ceeff1e536859e071a72e91075d4d37d51470812c4f49e682702"}, - {file = "pydantic_core-2.6.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a1ad48e77935d7dbbc2d75aeb638abbfbd0df0cfacf774dbe98d52271468f00c"}, - {file = "pydantic_core-2.6.1-cp37-none-win32.whl", hash = "sha256:153a5dd24c09ab7544beda967366afbaae8350b327a4ebd5807ed45ec791baa0"}, - {file = "pydantic_core-2.6.1-cp37-none-win_amd64.whl", hash = "sha256:cc7fc3e81b4ea6bce7e0e1d9797f496e957c5e66adf483f89afdce2d81d19986"}, - {file = "pydantic_core-2.6.1-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:5482d692ae37857695feccb179022728b275b7bfcc1c85bcdf7b556e76bffcd8"}, - {file = "pydantic_core-2.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:45d248c3c5c5c23a8d048cfdebc8151ae7b32a6dc6d68fbca995521e54692207"}, - {file = "pydantic_core-2.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6dd6c9f47e26779bf1f7da4d6ccd60f66973e63b0a143438f1e20bae296c3fde"}, - {file = "pydantic_core-2.6.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:55701608e60418a423db2486b5c64d790f86eb78a11b9077efb6302c50e62564"}, - {file = "pydantic_core-2.6.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:420a76a62dd20a6ef08445abf7cf04dcd8a845a5bb15932c2e88a8e518c70d43"}, - {file = "pydantic_core-2.6.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5f253d20314e53ba0fb2b95541b6ed23f44fbcd927fe7674de341545c3327c3d"}, - {file = "pydantic_core-2.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5127b811c6a26deb85f5b17a06c26c28ce204e51e0a963b75bdf8612b22546d"}, - {file = "pydantic_core-2.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:51ffa985b874ca7d0dc199bb75c67b77907379291c91532a9e2d981f7b681527"}, - {file = "pydantic_core-2.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4902300e763a2fcc49ae14366493ef1fdbd3c7128b9acf37aef505f671aa681f"}, - {file = "pydantic_core-2.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e1c69334bb843c9bff98f52a1fa6c06420081a561fcecb03c6b9376960bd7de2"}, - {file = "pydantic_core-2.6.1-cp38-none-win32.whl", hash = "sha256:e84812b1ca989b2e9f4913d7b75ae0eece2a90154de35b4c5411ad640bfd387c"}, - {file = "pydantic_core-2.6.1-cp38-none-win_amd64.whl", hash = "sha256:775098e3629a959dfec8444667a53e0916839e9fbf6b55e07d6e2aadde006400"}, - {file = "pydantic_core-2.6.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:a32ed5a794918a61bf77b967c197eb78f31ad4e3145860193dc381bde040717e"}, - {file = "pydantic_core-2.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:66eda8ac48ac33e9e5c6541c8e30c702924b70a6f2e9732b74230d9b2dd35fb6"}, - {file = "pydantic_core-2.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb5131d75d69b0547ef9a8f46f7b94857411c9badcdd5092de61a3b4943f08c7"}, - {file = "pydantic_core-2.6.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:20e850f3242d7836a5e15453f798d8569b9754350c8e184ba32d102c515dd507"}, - {file = "pydantic_core-2.6.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f4327fa6a1ac3da62b27d43bb0f27657ed4e601b141ecbfcf8523814b6c33b6"}, - {file = "pydantic_core-2.6.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c7b89b2875b967ad5c3c980bf72773851554f80c2529796e815a10c99295d872"}, - {file = "pydantic_core-2.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78eadd8d7d5cd8c3616e363c394d721437c339feaa4c28404e2eda79add69781"}, - {file = "pydantic_core-2.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17ab25bb24e98b61d120b7248c2b49ea56ce754a050d6b348be42015fcb7aa25"}, - {file = "pydantic_core-2.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6ea8dd2854fe6cee5ea0d60304ee7877dffe487cf118f221e85029269dd1235d"}, - {file = "pydantic_core-2.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9bf3ba6b4878ee692f6e24230801f682807fd97356bc2064f630fc0a2ad2ead6"}, - {file = "pydantic_core-2.6.1-cp39-none-win32.whl", hash = "sha256:b974d65692333931b4c7f730e7a3135ff854a1e5384bc260de3327ea364c835a"}, - {file = "pydantic_core-2.6.1-cp39-none-win_amd64.whl", hash = "sha256:f34f26d8a5f1a45366189ec30a57f43b21e2172d0d3b62822638dd885cc8eaab"}, - {file = "pydantic_core-2.6.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:f7ec4c6edafa3f0eb1aa461e31ea263736cc541b2459dddfbda7085b30844801"}, - {file = "pydantic_core-2.6.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:3679b9a1f41eb1b699e9556f91281d78c416cdc59ae90d5733fbe2017f1effe9"}, - {file = "pydantic_core-2.6.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ff36f945342086ee917d4219dd0e59660a2dfcdb86a07696c2791f5d59c07d"}, - {file = "pydantic_core-2.6.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:734864605d722a6f8db3b9c96371710f7cb591fbfca40cfeaedf5b67df282438"}, - {file = "pydantic_core-2.6.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7188359b95a2b1aef5744a2ee6af2d9cfc733dd823f8840f4c896129477a172b"}, - {file = "pydantic_core-2.6.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:382d40843ae759d43ef65b67dec713390f9417135c1dd730afbf03cf2f450f45"}, - {file = "pydantic_core-2.6.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:4525b8498d362e4e324e3e175239b364768f52bd3563ac4ef9750160f5789de8"}, - {file = "pydantic_core-2.6.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e55514a022c768cccf07a675d20d07b847980dcd9250f6b516a86bab5612fc01"}, - {file = "pydantic_core-2.6.1-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:34734d486d059f0f6f5bfa9ba4a41449f666e2abbde002e9fa8b050bc50e3347"}, - {file = "pydantic_core-2.6.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a809498dceb0cd1cd1e57a2bfdc70ea82f424776e0196f4d63c4b6fcdaeb5aab"}, - {file = "pydantic_core-2.6.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:588a5ffd8bbf1b2230611ed1b45221adcf05b981037b2f853b5f20465849b5c1"}, - {file = "pydantic_core-2.6.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:26b81017aeae0d96f776fbce34a3a763d26ac575d8ad3f1202bdfdd2b935954b"}, - {file = "pydantic_core-2.6.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7ddaa2c3c66682f0ff4ebc8c85ef2d8305f32deba79416464c47c93d94ca3740"}, - {file = "pydantic_core-2.6.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d6971131de66d1a37293f2e032206b6984b0dec44f568b453dfe89a84a2de0cc"}, - {file = "pydantic_core-2.6.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:200704f6824f8014bdccb1ce57cbd328666e6de4ecd77f0b8ab472cdea9c49ce"}, - {file = "pydantic_core-2.6.1-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:6916b27072c957947919fb32551f08486562bb8616f2e3db9e4e9c1d83d36886"}, - {file = "pydantic_core-2.6.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:136de286abf53f326b90389aaaca8a8050c2570adfc74afe06ab1c35d5d242bf"}, - {file = "pydantic_core-2.6.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60a238bb4ab09a81a6b25c9a0bb12756cfab2d9f3a7a471f857a179f83da0df6"}, - {file = "pydantic_core-2.6.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2034d9b83a59b3b74b9dbf97ddb99de86c08863c1c33aabf80bc95791c7d50c3"}, - {file = "pydantic_core-2.6.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7c3a2b4d1636446dc71da1e949d2cf9ac1ee691ca63a640b77fce0360b4b75be"}, - {file = "pydantic_core-2.6.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:09e4ebd11a0b333b1fca75c1004c76dc9719f3aaf83ae38c42358754d8a76148"}, - {file = "pydantic_core-2.6.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:a4536d132a8bbd05bf368fb802a264cb9828f6c85e4029a6a3670bc98ba97323"}, - {file = "pydantic_core-2.6.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:6221c97d6d58f2370650cfe3d81408901a1951c99960e1df9f6f9f8482d73d08"}, - {file = "pydantic_core-2.6.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4223e8bdad41d846a84cda400cd538e1cdc63d98eb4d41951396bfdb88fd8ce9"}, - {file = "pydantic_core-2.6.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c07cdb2e02733e5f26b9b004a1a8b99814d175f8953fa9f59e4293de2b8e9787"}, - {file = "pydantic_core-2.6.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8714e958d01342d08e520ffec6c1acf66cdec83ce51302f9a1a6efb2f784d0b6"}, - {file = "pydantic_core-2.6.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f03541c25a77fb5445055e070b69d292c9818a9195ffbfd3962c0ad0da983e8"}, - {file = "pydantic_core-2.6.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:364c13ef48c9e2f8c2ea8ee0da5ea23db5e218f99e796cbf360a2a7cab511439"}, - {file = "pydantic_core-2.6.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:27ba58bbfd1b2b9da45bfe524e680e2bc747a1ca9738ee5aa18d8cbdcc08e5e6"}, - {file = "pydantic_core-2.6.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:92321582e59da185b76b2eca4488ea95e41800672e57107509d32ebf8ad550f8"}, - {file = "pydantic_core-2.6.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2da1d21a4f2675d5b8a749674993a65c0537e2066e7ab7b1a4a54ef0b3ac8efd"}, - {file = "pydantic_core-2.6.1.tar.gz", hash = "sha256:5b4efa68bcfa6f2b93624c6660b6cf4b7b4336d4225afb314254a0ed9c9f4153"}, + {file = "pydantic_core-2.6.3-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:1a0ddaa723c48af27d19f27f1c73bdc615c73686d763388c8683fe34ae777bad"}, + {file = "pydantic_core-2.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5cfde4fab34dd1e3a3f7f3db38182ab6c95e4ea91cf322242ee0be5c2f7e3d2f"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5493a7027bfc6b108e17c3383959485087d5942e87eb62bbac69829eae9bc1f7"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:84e87c16f582f5c753b7f39a71bd6647255512191be2d2dbf49458c4ef024588"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:522a9c4a4d1924facce7270c84b5134c5cabcb01513213662a2e89cf28c1d309"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaafc776e5edc72b3cad1ccedb5fd869cc5c9a591f1213aa9eba31a781be9ac1"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a750a83b2728299ca12e003d73d1264ad0440f60f4fc9cee54acc489249b728"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e8b374ef41ad5c461efb7a140ce4730661aadf85958b5c6a3e9cf4e040ff4bb"}, + {file = "pydantic_core-2.6.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b594b64e8568cf09ee5c9501ede37066b9fc41d83d58f55b9952e32141256acd"}, + {file = "pydantic_core-2.6.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2a20c533cb80466c1d42a43a4521669ccad7cf2967830ac62c2c2f9cece63e7e"}, + {file = "pydantic_core-2.6.3-cp310-none-win32.whl", hash = "sha256:04fe5c0a43dec39aedba0ec9579001061d4653a9b53a1366b113aca4a3c05ca7"}, + {file = "pydantic_core-2.6.3-cp310-none-win_amd64.whl", hash = "sha256:6bf7d610ac8f0065a286002a23bcce241ea8248c71988bda538edcc90e0c39ad"}, + {file = "pydantic_core-2.6.3-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:6bcc1ad776fffe25ea5c187a028991c031a00ff92d012ca1cc4714087e575973"}, + {file = "pydantic_core-2.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:df14f6332834444b4a37685810216cc8fe1fe91f447332cd56294c984ecbff1c"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0b7486d85293f7f0bbc39b34e1d8aa26210b450bbd3d245ec3d732864009819"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a892b5b1871b301ce20d40b037ffbe33d1407a39639c2b05356acfef5536d26a"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:883daa467865e5766931e07eb20f3e8152324f0adf52658f4d302242c12e2c32"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4eb77df2964b64ba190eee00b2312a1fd7a862af8918ec70fc2d6308f76ac64"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce8c84051fa292a5dc54018a40e2a1926fd17980a9422c973e3ebea017aa8da"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:22134a4453bd59b7d1e895c455fe277af9d9d9fbbcb9dc3f4a97b8693e7e2c9b"}, + {file = "pydantic_core-2.6.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:02e1c385095efbd997311d85c6021d32369675c09bcbfff3b69d84e59dc103f6"}, + {file = "pydantic_core-2.6.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d79f1f2f7ebdb9b741296b69049ff44aedd95976bfee38eb4848820628a99b50"}, + {file = "pydantic_core-2.6.3-cp311-none-win32.whl", hash = "sha256:430ddd965ffd068dd70ef4e4d74f2c489c3a313adc28e829dd7262cc0d2dd1e8"}, + {file = "pydantic_core-2.6.3-cp311-none-win_amd64.whl", hash = "sha256:84f8bb34fe76c68c9d96b77c60cef093f5e660ef8e43a6cbfcd991017d375950"}, + {file = "pydantic_core-2.6.3-cp311-none-win_arm64.whl", hash = "sha256:5a2a3c9ef904dcdadb550eedf3291ec3f229431b0084666e2c2aa8ff99a103a2"}, + {file = "pydantic_core-2.6.3-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:8421cf496e746cf8d6b677502ed9a0d1e4e956586cd8b221e1312e0841c002d5"}, + {file = "pydantic_core-2.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bb128c30cf1df0ab78166ded1ecf876620fb9aac84d2413e8ea1594b588c735d"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37a822f630712817b6ecc09ccc378192ef5ff12e2c9bae97eb5968a6cdf3b862"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:240a015102a0c0cc8114f1cba6444499a8a4d0333e178bc504a5c2196defd456"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f90e5e3afb11268628c89f378f7a1ea3f2fe502a28af4192e30a6cdea1e7d5e"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:340e96c08de1069f3d022a85c2a8c63529fd88709468373b418f4cf2c949fb0e"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1480fa4682e8202b560dcdc9eeec1005f62a15742b813c88cdc01d44e85308e5"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f14546403c2a1d11a130b537dda28f07eb6c1805a43dae4617448074fd49c282"}, + {file = "pydantic_core-2.6.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a87c54e72aa2ef30189dc74427421e074ab4561cf2bf314589f6af5b37f45e6d"}, + {file = "pydantic_core-2.6.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f93255b3e4d64785554e544c1c76cd32f4a354fa79e2eeca5d16ac2e7fdd57aa"}, + {file = "pydantic_core-2.6.3-cp312-none-win32.whl", hash = "sha256:f70dc00a91311a1aea124e5f64569ea44c011b58433981313202c46bccbec0e1"}, + {file = "pydantic_core-2.6.3-cp312-none-win_amd64.whl", hash = "sha256:23470a23614c701b37252618e7851e595060a96a23016f9a084f3f92f5ed5881"}, + {file = "pydantic_core-2.6.3-cp312-none-win_arm64.whl", hash = "sha256:1ac1750df1b4339b543531ce793b8fd5c16660a95d13aecaab26b44ce11775e9"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:a53e3195f134bde03620d87a7e2b2f2046e0e5a8195e66d0f244d6d5b2f6d31b"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:f2969e8f72c6236c51f91fbb79c33821d12a811e2a94b7aa59c65f8dbdfad34a"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:672174480a85386dd2e681cadd7d951471ad0bb028ed744c895f11f9d51b9ebe"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:002d0ea50e17ed982c2d65b480bd975fc41086a5a2f9c924ef8fc54419d1dea3"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ccc13afee44b9006a73d2046068d4df96dc5b333bf3509d9a06d1b42db6d8bf"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:439a0de139556745ae53f9cc9668c6c2053444af940d3ef3ecad95b079bc9987"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d63b7545d489422d417a0cae6f9898618669608750fc5e62156957e609e728a5"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b44c42edc07a50a081672e25dfe6022554b47f91e793066a7b601ca290f71e42"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1c721bfc575d57305dd922e6a40a8fe3f762905851d694245807a351ad255c58"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5e4a2cf8c4543f37f5dc881de6c190de08096c53986381daebb56a355be5dfe6"}, + {file = "pydantic_core-2.6.3-cp37-none-win32.whl", hash = "sha256:d9b4916b21931b08096efed090327f8fe78e09ae8f5ad44e07f5c72a7eedb51b"}, + {file = "pydantic_core-2.6.3-cp37-none-win_amd64.whl", hash = "sha256:a8acc9dedd304da161eb071cc7ff1326aa5b66aadec9622b2574ad3ffe225525"}, + {file = "pydantic_core-2.6.3-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:5e9c068f36b9f396399d43bfb6defd4cc99c36215f6ff33ac8b9c14ba15bdf6b"}, + {file = "pydantic_core-2.6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e61eae9b31799c32c5f9b7be906be3380e699e74b2db26c227c50a5fc7988698"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85463560c67fc65cd86153a4975d0b720b6d7725cf7ee0b2d291288433fc21b"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9616567800bdc83ce136e5847d41008a1d602213d024207b0ff6cab6753fe645"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e9b65a55bbabda7fccd3500192a79f6e474d8d36e78d1685496aad5f9dbd92c"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f468d520f47807d1eb5d27648393519655eadc578d5dd862d06873cce04c4d1b"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9680dd23055dd874173a3a63a44e7f5a13885a4cfd7e84814be71be24fba83db"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a718d56c4d55efcfc63f680f207c9f19c8376e5a8a67773535e6f7e80e93170"}, + {file = "pydantic_core-2.6.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8ecbac050856eb6c3046dea655b39216597e373aa8e50e134c0e202f9c47efec"}, + {file = "pydantic_core-2.6.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:788be9844a6e5c4612b74512a76b2153f1877cd845410d756841f6c3420230eb"}, + {file = "pydantic_core-2.6.3-cp38-none-win32.whl", hash = "sha256:07a1aec07333bf5adebd8264047d3dc518563d92aca6f2f5b36f505132399efc"}, + {file = "pydantic_core-2.6.3-cp38-none-win_amd64.whl", hash = "sha256:621afe25cc2b3c4ba05fff53525156d5100eb35c6e5a7cf31d66cc9e1963e378"}, + {file = "pydantic_core-2.6.3-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:813aab5bfb19c98ae370952b6f7190f1e28e565909bfc219a0909db168783465"}, + {file = "pydantic_core-2.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:50555ba3cb58f9861b7a48c493636b996a617db1a72c18da4d7f16d7b1b9952b"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19e20f8baedd7d987bd3f8005c146e6bcbda7cdeefc36fad50c66adb2dd2da48"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b0a5d7edb76c1c57b95df719af703e796fc8e796447a1da939f97bfa8a918d60"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f06e21ad0b504658a3a9edd3d8530e8cea5723f6ea5d280e8db8efc625b47e49"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea053cefa008fda40f92aab937fb9f183cf8752e41dbc7bc68917884454c6362"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:171a4718860790f66d6c2eda1d95dd1edf64f864d2e9f9115840840cf5b5713f"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ed7ceca6aba5331ece96c0e328cd52f0dcf942b8895a1ed2642de50800b79d3"}, + {file = "pydantic_core-2.6.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:acafc4368b289a9f291e204d2c4c75908557d4f36bd3ae937914d4529bf62a76"}, + {file = "pydantic_core-2.6.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1aa712ba150d5105814e53cb141412217146fedc22621e9acff9236d77d2a5ef"}, + {file = "pydantic_core-2.6.3-cp39-none-win32.whl", hash = "sha256:44b4f937b992394a2e81a5c5ce716f3dcc1237281e81b80c748b2da6dd5cf29a"}, + {file = "pydantic_core-2.6.3-cp39-none-win_amd64.whl", hash = "sha256:9b33bf9658cb29ac1a517c11e865112316d09687d767d7a0e4a63d5c640d1b17"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d7050899026e708fb185e174c63ebc2c4ee7a0c17b0a96ebc50e1f76a231c057"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:99faba727727b2e59129c59542284efebbddade4f0ae6a29c8b8d3e1f437beb7"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fa159b902d22b283b680ef52b532b29554ea2a7fc39bf354064751369e9dbd7"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:046af9cfb5384f3684eeb3f58a48698ddab8dd870b4b3f67f825353a14441418"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:930bfe73e665ebce3f0da2c6d64455098aaa67e1a00323c74dc752627879fc67"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:85cc4d105747d2aa3c5cf3e37dac50141bff779545ba59a095f4a96b0a460e70"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b25afe9d5c4f60dcbbe2b277a79be114e2e65a16598db8abee2a2dcde24f162b"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e49ce7dc9f925e1fb010fc3d555250139df61fa6e5a0a95ce356329602c11ea9"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:2dd50d6a1aef0426a1d0199190c6c43ec89812b1f409e7fe44cb0fbf6dfa733c"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6595b0d8c8711e8e1dc389d52648b923b809f68ac1c6f0baa525c6440aa0daa"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ef724a059396751aef71e847178d66ad7fc3fc969a1a40c29f5aac1aa5f8784"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3c8945a105f1589ce8a693753b908815e0748f6279959a4530f6742e1994dcb6"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c8c6660089a25d45333cb9db56bb9e347241a6d7509838dbbd1931d0e19dbc7f"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:692b4ff5c4e828a38716cfa92667661a39886e71136c97b7dac26edef18767f7"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:f1a5d8f18877474c80b7711d870db0eeef9442691fcdb00adabfc97e183ee0b0"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:3796a6152c545339d3b1652183e786df648ecdf7c4f9347e1d30e6750907f5bb"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b962700962f6e7a6bd77e5f37320cabac24b4c0f76afeac05e9f93cf0c620014"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56ea80269077003eaa59723bac1d8bacd2cd15ae30456f2890811efc1e3d4413"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75c0ebbebae71ed1e385f7dfd9b74c1cff09fed24a6df43d326dd7f12339ec34"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:252851b38bad3bfda47b104ffd077d4f9604a10cb06fe09d020016a25107bf98"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:6656a0ae383d8cd7cc94e91de4e526407b3726049ce8d7939049cbfa426518c8"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d9140ded382a5b04a1c030b593ed9bf3088243a0a8b7fa9f071a5736498c5483"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d38bbcef58220f9c81e42c255ef0bf99735d8f11edef69ab0b499da77105158a"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c9d469204abcca28926cbc28ce98f28e50e488767b084fb3fbdf21af11d3de26"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:48c1ed8b02ffea4d5c9c220eda27af02b8149fe58526359b3c07eb391cb353a2"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b2b1bfed698fa410ab81982f681f5b1996d3d994ae8073286515ac4d165c2e7"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf9d42a71a4d7a7c1f14f629e5c30eac451a6fc81827d2beefd57d014c006c4a"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4292ca56751aebbe63a84bbfc3b5717abb09b14d4b4442cc43fd7c49a1529efd"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7dc2ce039c7290b4ef64334ec7e6ca6494de6eecc81e21cb4f73b9b39991408c"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:615a31b1629e12445c0e9fc8339b41aaa6cc60bd53bf802d5fe3d2c0cda2ae8d"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1fa1f6312fb84e8c281f32b39affe81984ccd484da6e9d65b3d18c202c666149"}, + {file = "pydantic_core-2.6.3.tar.gz", hash = "sha256:1508f37ba9e3ddc0189e6ff4e2228bd2d3c3a4641cbe8c07177162f76ed696c7"}, ] [package.dependencies] @@ -4501,4 +4501,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "6b26260643c21e6a64a1bbb0609ebcd42ac75e7b45d6fe6131209275613b205b" +content-hash = "0553beb077e2839046c1f156be1c65f2b1a28c591084b45c8a0e54db00c57cb7" diff --git a/pyproject.toml b/pyproject.toml index e5367935..dd031588 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,6 @@ python-dotenv = "^1.0.0" poetry-plugin-dotenv = "^0.5.1" pyupgrade = "^3.9.0" jupyter = "^1.0.0" -pydantic = "^2.2.1" [tool.poetry.dev-dependencies] bandit = "^1.7.1" diff --git a/requirements.txt b/requirements.txt index 23ae643f..bcad6b87 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,146 +1,3 @@ -This package has been deprecated and is no longer maintained, `poetry-dotenv` has moved to `poetry-plugin-dotenv` (https://pypi.org/project/poetry-plugin-dotenv) -annotated-types==0.5.0 ; python_version >= "3.9" and python_version < "4.0" -anyio==3.7.1 ; python_version >= "3.9" and python_version < "4.0" -appnope==0.1.3 ; python_version >= "3.9" and python_version < "4.0" and (platform_system == "Darwin" or sys_platform == "darwin") -argon2-cffi-bindings==21.2.0 ; python_version >= "3.9" and python_version < "4.0" -argon2-cffi==23.1.0 ; python_version >= "3.9" and python_version < "4.0" -arrow==1.2.3 ; python_version >= "3.9" and python_version < "4.0" -asttokens==2.2.1 ; python_version >= "3.9" and python_version < "4.0" -async-lru==2.0.4 ; python_version >= "3.9" and python_version < "4.0" -attrs==23.1.0 ; python_version >= "3.9" and python_version < "4.0" -babel==2.12.1 ; python_version >= "3.9" and python_version < "4.0" -backcall==0.2.0 ; python_version >= "3.9" and python_version < "4.0" -beautifulsoup4==4.12.2 ; python_version >= "3.9" and python_version < "4.0" -bleach==6.0.0 ; python_version >= "3.9" and python_version < "4.0" -build==0.10.0 ; python_version >= "3.9" and python_version < "4.0" -cachecontrol[filecache]==0.12.14 ; python_version >= "3.9" and python_version < "4.0" -certifi==2023.7.22 ; python_version >= "3.9" and python_version < "4.0" -cffi==1.15.1 ; python_version >= "3.9" and python_version < "4.0" -charset-normalizer==3.2.0 ; python_version >= "3.9" and python_version < "4.0" -cleo==2.0.1 ; python_version >= "3.9" and python_version < "4.0" -colorama==0.4.6 ; python_version >= "3.9" and python_version < "4.0" and (os_name == "nt" or sys_platform == "win32") -comm==0.1.4 ; python_version >= "3.9" and python_version < "4.0" -crashtest==0.4.1 ; python_version >= "3.9" and python_version < "4.0" -cryptography==41.0.3 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "linux" -debugpy==1.6.7.post1 ; python_version >= "3.9" and python_version < "4.0" -decorator==5.1.1 ; python_version >= "3.9" and python_version < "4.0" -defusedxml==0.7.1 ; python_version >= "3.9" and python_version < "4.0" -distlib==0.3.7 ; python_version >= "3.9" and python_version < "4.0" -dulwich==0.21.5 ; python_version >= "3.9" and python_version < "4.0" -exceptiongroup==1.1.3 ; python_version >= "3.9" and python_version < "3.11" -executing==1.2.0 ; python_version >= "3.9" and python_version < "4.0" -fastjsonschema==2.18.0 ; python_version >= "3.9" and python_version < "4.0" -filelock==3.12.2 ; python_version >= "3.9" and python_version < "4.0" -fqdn==1.5.1 ; python_version >= "3.9" and python_version < "4" -h11==0.14.0 ; python_version >= "3.9" and python_version < "4.0" -html5lib==1.1 ; python_version >= "3.9" and python_version < "4.0" -httpcore==0.17.3 ; python_version >= "3.9" and python_version < "4.0" -httpx==0.24.1 ; python_version >= "3.9" and python_version < "4.0" -idna==3.4 ; python_version >= "3.9" and python_version < "4.0" -importlib-metadata==6.8.0 ; python_version >= "3.9" and python_version < "3.12" -installer==0.7.0 ; python_version >= "3.9" and python_version < "4.0" -ipykernel==6.25.1 ; python_version >= "3.9" and python_version < "4.0" -ipython-genutils==0.2.0 ; python_version >= "3.9" and python_version < "4.0" -ipython==8.14.0 ; python_version >= "3.9" and python_version < "4.0" -ipywidgets==8.1.0 ; python_version >= "3.9" and python_version < "4.0" -isoduration==20.11.0 ; python_version >= "3.9" and python_version < "4.0" -jaraco-classes==3.3.0 ; python_version >= "3.9" and python_version < "4.0" -jedi==0.19.0 ; python_version >= "3.9" and python_version < "4.0" -jeepney==0.8.0 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "linux" -jinja2==3.1.2 ; python_version >= "3.9" and python_version < "4.0" -json5==0.9.14 ; python_version >= "3.9" and python_version < "4.0" -jsonpointer==2.4 ; python_version >= "3.9" and python_version < "4.0" -jsonschema-specifications==2023.7.1 ; python_version >= "3.9" and python_version < "4.0" -jsonschema==4.19.0 ; python_version >= "3.9" and python_version < "4.0" -jsonschema[format-nongpl]==4.19.0 ; python_version >= "3.9" and python_version < "4.0" -jupyter-client==8.3.0 ; python_version >= "3.9" and python_version < "4.0" -jupyter-console==6.6.3 ; python_version >= "3.9" and python_version < "4.0" -jupyter-core==5.3.1 ; python_version >= "3.9" and python_version < "4.0" -jupyter-events==0.7.0 ; python_version >= "3.9" and python_version < "4.0" -jupyter-lsp==2.2.0 ; python_version >= "3.9" and python_version < "4.0" -jupyter-server-terminals==0.4.4 ; python_version >= "3.9" and python_version < "4.0" -jupyter-server==2.7.2 ; python_version >= "3.9" and python_version < "4.0" -jupyter==1.0.0 ; python_version >= "3.9" and python_version < "4.0" -jupyterlab-pygments==0.2.2 ; python_version >= "3.9" and python_version < "4.0" -jupyterlab-server==2.24.0 ; python_version >= "3.9" and python_version < "4.0" -jupyterlab-widgets==3.0.8 ; python_version >= "3.9" and python_version < "4.0" -jupyterlab==4.0.5 ; python_version >= "3.9" and python_version < "4.0" -keyring==23.13.1 ; python_version >= "3.9" and python_version < "4.0" -lockfile==0.12.2 ; python_version >= "3.9" and python_version < "4.0" -markupsafe==2.1.3 ; python_version >= "3.9" and python_version < "4.0" -matplotlib-inline==0.1.6 ; python_version >= "3.9" and python_version < "4.0" -mistune==3.0.1 ; python_version >= "3.9" and python_version < "4.0" -more-itertools==10.1.0 ; python_version >= "3.9" and python_version < "4.0" -msgpack==1.0.5 ; python_version >= "3.9" and python_version < "4.0" -nbclient==0.8.0 ; python_version >= "3.9" and python_version < "4.0" -nbconvert==7.7.4 ; python_version >= "3.9" and python_version < "4.0" -nbformat==5.9.2 ; python_version >= "3.9" and python_version < "4.0" -nest-asyncio==1.5.7 ; python_version >= "3.9" and python_version < "4.0" -notebook-shim==0.2.3 ; python_version >= "3.9" and python_version < "4.0" -notebook==7.0.2 ; python_version >= "3.9" and python_version < "4.0" -overrides==7.4.0 ; python_version >= "3.9" and python_version < "4.0" -packaging==23.0 ; python_version >= "3.9" and python_version < "4.0" -pandocfilters==1.5.0 ; python_version >= "3.9" and python_version < "4.0" -parso==0.8.3 ; python_version >= "3.9" and python_version < "4.0" -pexpect==4.8.0 ; python_version >= "3.9" and python_version < "4.0" -pickleshare==0.7.5 ; python_version >= "3.9" and python_version < "4.0" -pkginfo==1.9.6 ; python_version >= "3.9" and python_version < "4.0" -platformdirs==3.10.0 ; python_version >= "3.9" and python_version < "4.0" -poetry-core==1.6.1 ; python_version >= "3.9" and python_version < "4.0" -poetry-plugin-dotenv==0.5.2 ; python_version >= "3.9" and python_version < "4.0" -poetry-plugin-export==1.4.0 ; python_version >= "3.9" and python_version < "4.0" -poetry==1.5.1 ; python_version >= "3.9" and python_version < "4.0" -prometheus-client==0.17.1 ; python_version >= "3.9" and python_version < "4.0" -prompt-toolkit==3.0.39 ; python_version >= "3.9" and python_version < "4.0" -psutil==5.9.5 ; python_version >= "3.9" and python_version < "4.0" -ptyprocess==0.7.0 ; python_version >= "3.9" and python_version < "4.0" -pure-eval==0.2.2 ; python_version >= "3.9" and python_version < "4.0" -pycparser==2.21 ; python_version >= "3.9" and python_version < "4.0" -pydantic-core==2.6.1 ; python_version >= "3.9" and python_version < "4.0" -pydantic==2.2.1 ; python_version >= "3.9" and python_version < "4.0" -pygments==2.16.1 ; python_version >= "3.9" and python_version < "4.0" -pyproject-hooks==1.0.0 ; python_version >= "3.9" and python_version < "4.0" -python-dateutil==2.8.2 ; python_version >= "3.9" and python_version < "4.0" -python-dotenv==1.0.0 ; python_version >= "3.9" and python_version < "4.0" -python-json-logger==2.0.7 ; python_version >= "3.9" and python_version < "4.0" -pyupgrade==3.10.1 ; python_version >= "3.9" and python_version < "4.0" -pywin32-ctypes==0.2.2 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "win32" -pywin32==306 ; sys_platform == "win32" and platform_python_implementation != "PyPy" and python_version >= "3.9" and python_version < "4.0" -pywinpty==2.0.11 ; python_version >= "3.9" and python_version < "4.0" and os_name == "nt" -pyyaml==6.0.1 ; python_version >= "3.9" and python_version < "4.0" -pyzmq==25.1.1 ; python_version >= "3.9" and python_version < "4.0" -qtconsole==5.4.3 ; python_version >= "3.9" and python_version < "4.0" -qtpy==2.3.1 ; python_version >= "3.9" and python_version < "4.0" -rapidfuzz==2.15.1 ; python_version >= "3.9" and python_version < "4.0" -referencing==0.30.2 ; python_version >= "3.9" and python_version < "4.0" -requests-toolbelt==1.0.0 ; python_version >= "3.9" and python_version < "4.0" -requests==2.31.0 ; python_version >= "3.9" and python_version < "4.0" -rfc3339-validator==0.1.4 ; python_version >= "3.9" and python_version < "4.0" -rfc3986-validator==0.1.1 ; python_version >= "3.9" and python_version < "4.0" -rpds-py==0.9.2 ; python_version >= "3.9" and python_version < "4.0" -secretstorage==3.3.3 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "linux" -send2trash==1.8.2 ; python_version >= "3.9" and python_version < "4.0" -shellingham==1.5.3 ; python_version >= "3.9" and python_version < "4.0" -six==1.16.0 ; python_version >= "3.9" and python_version < "4.0" -sniffio==1.3.0 ; python_version >= "3.9" and python_version < "4.0" -soupsieve==2.4.1 ; python_version >= "3.9" and python_version < "4.0" -stack-data==0.6.2 ; python_version >= "3.9" and python_version < "4.0" -terminado==0.17.1 ; python_version >= "3.9" and python_version < "4.0" -tinycss2==1.2.1 ; python_version >= "3.9" and python_version < "4.0" -tokenize-rt==5.2.0 ; python_version >= "3.9" and python_version < "4.0" -tomli==2.0.1 ; python_version >= "3.9" and python_version < "3.11" -tomlkit==0.12.1 ; python_version >= "3.9" and python_version < "4.0" -tornado==6.3.3 ; python_version >= "3.9" and python_version < "4.0" -traitlets==5.9.0 ; python_version >= "3.9" and python_version < "4.0" -trove-classifiers==2023.8.7 ; python_version >= "3.9" and python_version < "4.0" -typing-extensions==4.7.1 ; python_version >= "3.9" and python_version < "4.0" -uri-template==1.3.0 ; python_version >= "3.9" and python_version < "4.0" -urllib3==1.26.16 ; python_version >= "3.9" and python_version < "4.0" -virtualenv==20.24.3 ; python_version >= "3.9" and python_version < "4.0" -wcwidth==0.2.6 ; python_version >= "3.9" and python_version < "4.0" -webcolors==1.13 ; python_version >= "3.9" and python_version < "4.0" -webencodings==0.5.1 ; python_version >= "3.9" and python_version < "4.0" -websocket-client==1.6.1 ; python_version >= "3.9" and python_version < "4.0" -widgetsnbextension==4.0.8 ; python_version >= "3.9" and python_version < "4.0" -xattr==0.10.1 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "darwin" -zipp==3.16.2 ; python_version >= "3.9" and python_version < "3.12" +attrs +httpx +python-dotenv From 4b2a8fd38f61b9fc835eb76ff806a4c8e1480323 Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Thu, 24 Aug 2023 14:07:49 -0700 Subject: [PATCH 06/15] cleanup --- poetry.lock | 751 +++++++------------------------------------------ pyproject.toml | 1 - 2 files changed, 100 insertions(+), 652 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6e692a0b..b542c736 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,127 +1,5 @@ # This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. -[[package]] -name = "aiohttp" -version = "3.8.5" -description = "Async http client/server framework (asyncio)" -optional = false -python-versions = ">=3.6" -files = [ - {file = "aiohttp-3.8.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a94159871304770da4dd371f4291b20cac04e8c94f11bdea1c3478e557fbe0d8"}, - {file = "aiohttp-3.8.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:13bf85afc99ce6f9ee3567b04501f18f9f8dbbb2ea11ed1a2e079670403a7c84"}, - {file = "aiohttp-3.8.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ce2ac5708501afc4847221a521f7e4b245abf5178cf5ddae9d5b3856ddb2f3a"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96943e5dcc37a6529d18766597c491798b7eb7a61d48878611298afc1fca946c"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ad5c3c4590bb3cc28b4382f031f3783f25ec223557124c68754a2231d989e2b"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c413c633d0512df4dc7fd2373ec06cc6a815b7b6d6c2f208ada7e9e93a5061d"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df72ac063b97837a80d80dec8d54c241af059cc9bb42c4de68bd5b61ceb37caa"}, - {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c48c5c0271149cfe467c0ff8eb941279fd6e3f65c9a388c984e0e6cf57538e14"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:368a42363c4d70ab52c2c6420a57f190ed3dfaca6a1b19afda8165ee16416a82"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7607ec3ce4993464368505888af5beb446845a014bc676d349efec0e05085905"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0d21c684808288a98914e5aaf2a7c6a3179d4df11d249799c32d1808e79503b5"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:312fcfbacc7880a8da0ae8b6abc6cc7d752e9caa0051a53d217a650b25e9a691"}, - {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ad093e823df03bb3fd37e7dec9d4670c34f9e24aeace76808fc20a507cace825"}, - {file = "aiohttp-3.8.5-cp310-cp310-win32.whl", hash = "sha256:33279701c04351a2914e1100b62b2a7fdb9a25995c4a104259f9a5ead7ed4802"}, - {file = "aiohttp-3.8.5-cp310-cp310-win_amd64.whl", hash = "sha256:6e4a280e4b975a2e7745573e3fc9c9ba0d1194a3738ce1cbaa80626cc9b4f4df"}, - {file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae871a964e1987a943d83d6709d20ec6103ca1eaf52f7e0d36ee1b5bebb8b9b9"}, - {file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:461908b2578955045efde733719d62f2b649c404189a09a632d245b445c9c975"}, - {file = "aiohttp-3.8.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:72a860c215e26192379f57cae5ab12b168b75db8271f111019509a1196dfc780"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc14be025665dba6202b6a71cfcdb53210cc498e50068bc088076624471f8bb9"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8af740fc2711ad85f1a5c034a435782fbd5b5f8314c9a3ef071424a8158d7f6b"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:841cd8233cbd2111a0ef0a522ce016357c5e3aff8a8ce92bcfa14cef890d698f"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed1c46fb119f1b59304b5ec89f834f07124cd23ae5b74288e364477641060ff"}, - {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84f8ae3e09a34f35c18fa57f015cc394bd1389bce02503fb30c394d04ee6b938"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62360cb771707cb70a6fd114b9871d20d7dd2163a0feafe43fd115cfe4fe845e"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:23fb25a9f0a1ca1f24c0a371523546366bb642397c94ab45ad3aedf2941cec6a"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0ba0d15164eae3d878260d4c4df859bbdc6466e9e6689c344a13334f988bb53"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5d20003b635fc6ae3f96d7260281dfaf1894fc3aa24d1888a9b2628e97c241e5"}, - {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0175d745d9e85c40dcc51c8f88c74bfbaef9e7afeeeb9d03c37977270303064c"}, - {file = "aiohttp-3.8.5-cp311-cp311-win32.whl", hash = "sha256:2e1b1e51b0774408f091d268648e3d57f7260c1682e7d3a63cb00d22d71bb945"}, - {file = "aiohttp-3.8.5-cp311-cp311-win_amd64.whl", hash = "sha256:043d2299f6dfdc92f0ac5e995dfc56668e1587cea7f9aa9d8a78a1b6554e5755"}, - {file = "aiohttp-3.8.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cae533195e8122584ec87531d6df000ad07737eaa3c81209e85c928854d2195c"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f21e83f355643c345177a5d1d8079f9f28b5133bcd154193b799d380331d5d3"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a75ef35f2df54ad55dbf4b73fe1da96f370e51b10c91f08b19603c64004acc"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e2e9839e14dd5308ee773c97115f1e0a1cb1d75cbeeee9f33824fa5144c7634"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44e65da1de4403d0576473e2344828ef9c4c6244d65cf4b75549bb46d40b8dd"}, - {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d847e4cde6ecc19125ccbc9bfac4a7ab37c234dd88fbb3c5c524e8e14da543"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:c7a815258e5895d8900aec4454f38dca9aed71085f227537208057853f9d13f2"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:8b929b9bd7cd7c3939f8bcfffa92fae7480bd1aa425279d51a89327d600c704d"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:5db3a5b833764280ed7618393832e0853e40f3d3e9aa128ac0ba0f8278d08649"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:a0215ce6041d501f3155dc219712bc41252d0ab76474615b9700d63d4d9292af"}, - {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:fd1ed388ea7fbed22c4968dd64bab0198de60750a25fe8c0c9d4bef5abe13824"}, - {file = "aiohttp-3.8.5-cp36-cp36m-win32.whl", hash = "sha256:6e6783bcc45f397fdebc118d772103d751b54cddf5b60fbcc958382d7dd64f3e"}, - {file = "aiohttp-3.8.5-cp36-cp36m-win_amd64.whl", hash = "sha256:b5411d82cddd212644cf9360879eb5080f0d5f7d809d03262c50dad02f01421a"}, - {file = "aiohttp-3.8.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:01d4c0c874aa4ddfb8098e85d10b5e875a70adc63db91f1ae65a4b04d3344cda"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5980a746d547a6ba173fd5ee85ce9077e72d118758db05d229044b469d9029a"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a482e6da906d5e6e653be079b29bc173a48e381600161c9932d89dfae5942ef"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80bd372b8d0715c66c974cf57fe363621a02f359f1ec81cba97366948c7fc873"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1161b345c0a444ebcf46bf0a740ba5dcf50612fd3d0528883fdc0eff578006a"}, - {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd56db019015b6acfaaf92e1ac40eb8434847d9bf88b4be4efe5bfd260aee692"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:153c2549f6c004d2754cc60603d4668899c9895b8a89397444a9c4efa282aaf4"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4a01951fabc4ce26ab791da5f3f24dca6d9a6f24121746eb19756416ff2d881b"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bfb9162dcf01f615462b995a516ba03e769de0789de1cadc0f916265c257e5d8"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:7dde0009408969a43b04c16cbbe252c4f5ef4574ac226bc8815cd7342d2028b6"}, - {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4149d34c32f9638f38f544b3977a4c24052042affa895352d3636fa8bffd030a"}, - {file = "aiohttp-3.8.5-cp37-cp37m-win32.whl", hash = "sha256:68c5a82c8779bdfc6367c967a4a1b2aa52cd3595388bf5961a62158ee8a59e22"}, - {file = "aiohttp-3.8.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2cf57fb50be5f52bda004b8893e63b48530ed9f0d6c96c84620dc92fe3cd9b9d"}, - {file = "aiohttp-3.8.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:eca4bf3734c541dc4f374ad6010a68ff6c6748f00451707f39857f429ca36ced"}, - {file = "aiohttp-3.8.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1274477e4c71ce8cfe6c1ec2f806d57c015ebf84d83373676036e256bc55d690"}, - {file = "aiohttp-3.8.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28c543e54710d6158fc6f439296c7865b29e0b616629767e685a7185fab4a6b9"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:910bec0c49637d213f5d9877105d26e0c4a4de2f8b1b29405ff37e9fc0ad52b8"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5443910d662db951b2e58eb70b0fbe6b6e2ae613477129a5805d0b66c54b6cb7"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e460be6978fc24e3df83193dc0cc4de46c9909ed92dd47d349a452ef49325b7"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb1558def481d84f03b45888473fc5a1f35747b5f334ef4e7a571bc0dfcb11f8"}, - {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34dd0c107799dcbbf7d48b53be761a013c0adf5571bf50c4ecad5643fe9cfcd0"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aa1990247f02a54185dc0dff92a6904521172a22664c863a03ff64c42f9b5410"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0e584a10f204a617d71d359fe383406305a4b595b333721fa50b867b4a0a1548"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:a3cf433f127efa43fee6b90ea4c6edf6c4a17109d1d037d1a52abec84d8f2e42"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c11f5b099adafb18e65c2c997d57108b5bbeaa9eeee64a84302c0978b1ec948b"}, - {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:84de26ddf621d7ac4c975dbea4c945860e08cccde492269db4e1538a6a6f3c35"}, - {file = "aiohttp-3.8.5-cp38-cp38-win32.whl", hash = "sha256:ab88bafedc57dd0aab55fa728ea10c1911f7e4d8b43e1d838a1739f33712921c"}, - {file = "aiohttp-3.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:5798a9aad1879f626589f3df0f8b79b3608a92e9beab10e5fda02c8a2c60db2e"}, - {file = "aiohttp-3.8.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a6ce61195c6a19c785df04e71a4537e29eaa2c50fe745b732aa937c0c77169f3"}, - {file = "aiohttp-3.8.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:773dd01706d4db536335fcfae6ea2440a70ceb03dd3e7378f3e815b03c97ab51"}, - {file = "aiohttp-3.8.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f83a552443a526ea38d064588613aca983d0ee0038801bc93c0c916428310c28"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f7372f7341fcc16f57b2caded43e81ddd18df53320b6f9f042acad41f8e049a"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea353162f249c8097ea63c2169dd1aa55de1e8fecbe63412a9bc50816e87b761"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d47ae48db0b2dcf70bc8a3bc72b3de86e2a590fc299fdbbb15af320d2659de"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d827176898a2b0b09694fbd1088c7a31836d1a505c243811c87ae53a3f6273c1"}, - {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3562b06567c06439d8b447037bb655ef69786c590b1de86c7ab81efe1c9c15d8"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4e874cbf8caf8959d2adf572a78bba17cb0e9d7e51bb83d86a3697b686a0ab4d"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6809a00deaf3810e38c628e9a33271892f815b853605a936e2e9e5129762356c"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:33776e945d89b29251b33a7e7d006ce86447b2cfd66db5e5ded4e5cd0340585c"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eaeed7abfb5d64c539e2db173f63631455f1196c37d9d8d873fc316470dfbacd"}, - {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e91d635961bec2d8f19dfeb41a539eb94bd073f075ca6dae6c8dc0ee89ad6f91"}, - {file = "aiohttp-3.8.5-cp39-cp39-win32.whl", hash = "sha256:00ad4b6f185ec67f3e6562e8a1d2b69660be43070bd0ef6fcec5211154c7df67"}, - {file = "aiohttp-3.8.5-cp39-cp39-win_amd64.whl", hash = "sha256:c0a9034379a37ae42dea7ac1e048352d96286626251862e448933c0f59cbd79c"}, - {file = "aiohttp-3.8.5.tar.gz", hash = "sha256:b9552ec52cc147dbf1944ac7ac98af7602e51ea2dcd076ed194ca3c0d1c7d0bc"}, -] - -[package.dependencies] -aiosignal = ">=1.1.2" -async-timeout = ">=4.0.0a3,<5.0" -attrs = ">=17.3.0" -charset-normalizer = ">=2.0,<4.0" -frozenlist = ">=1.1.1" -multidict = ">=4.5,<7.0" -yarl = ">=1.0,<2.0" - -[package.extras] -speedups = ["Brotli", "aiodns", "cchardet"] - -[[package]] -name = "aiosignal" -version = "1.3.1" -description = "aiosignal: a list of registered asynchronous callbacks" -optional = false -python-versions = ">=3.7" -files = [ - {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, - {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, -] - -[package.dependencies] -frozenlist = ">=1.1.0" - [[package]] name = "annotated-types" version = "0.5.0" @@ -286,17 +164,6 @@ files = [ [package.dependencies] typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} -[[package]] -name = "async-timeout" -version = "4.0.3" -description = "Timeout context manager for asyncio programs" -optional = false -python-versions = ">=3.7" -files = [ - {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, - {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, -] - [[package]] name = "attrs" version = "23.1.0" @@ -467,22 +334,23 @@ virtualenv = ["virtualenv (>=20.0.35)"] [[package]] name = "cachecontrol" -version = "0.12.14" +version = "0.13.1" description = "httplib2 caching for requests" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "CacheControl-0.12.14-py2.py3-none-any.whl", hash = "sha256:1c2939be362a70c4e5f02c6249462b3b7a24441e4f1ced5e9ef028172edf356a"}, - {file = "CacheControl-0.12.14.tar.gz", hash = "sha256:d1087f45781c0e00616479bfd282c78504371ca71da017b49df9f5365a95feba"}, + {file = "cachecontrol-0.13.1-py3-none-any.whl", hash = "sha256:95dedbec849f46dda3137866dc28b9d133fc9af55f5b805ab1291833e4457aa4"}, + {file = "cachecontrol-0.13.1.tar.gz", hash = "sha256:f012366b79d2243a6118309ce73151bf52a38d4a5dac8ea57f09bd29087e506b"}, ] [package.dependencies] -lockfile = {version = ">=0.9", optional = true, markers = "extra == \"filecache\""} +filelock = {version = ">=3.8.0", optional = true, markers = "extra == \"filecache\""} msgpack = ">=0.5.2" -requests = "*" +requests = ">=2.16.0" [package.extras] -filecache = ["lockfile (>=0.9)"] +dev = ["CacheControl[filecache,redis]", "black", "build", "cherrypy", "mypy", "pytest", "pytest-cov", "sphinx", "tox", "types-redis", "types-requests"] +filecache = ["filelock (>=3.8.0)"] redis = ["redis (>=2.10.5)"] [[package]] @@ -1109,76 +977,6 @@ files = [ {file = "fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f"}, ] -[[package]] -name = "frozenlist" -version = "1.4.0" -description = "A list-like structure which implements collections.abc.MutableSequence" -optional = false -python-versions = ">=3.8" -files = [ - {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab"}, - {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559"}, - {file = "frozenlist-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62"}, - {file = "frozenlist-1.4.0-cp310-cp310-win32.whl", hash = "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0"}, - {file = "frozenlist-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb"}, - {file = "frozenlist-1.4.0-cp311-cp311-win32.whl", hash = "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431"}, - {file = "frozenlist-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8"}, - {file = "frozenlist-1.4.0-cp38-cp38-win32.whl", hash = "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc"}, - {file = "frozenlist-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3"}, - {file = "frozenlist-1.4.0-cp39-cp39-win32.whl", hash = "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f"}, - {file = "frozenlist-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167"}, - {file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"}, -] - [[package]] name = "gitdb" version = "4.0.10" @@ -1218,27 +1016,6 @@ files = [ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, ] -[[package]] -name = "html5lib" -version = "1.1" -description = "HTML parser based on the WHATWG HTML specification" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d"}, - {file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"}, -] - -[package.dependencies] -six = ">=1.9" -webencodings = "*" - -[package.extras] -all = ["chardet (>=2.2)", "genshi", "lxml"] -chardet = ["chardet (>=2.2)"] -genshi = ["genshi"] -lxml = ["lxml"] - [[package]] name = "httpcore" version = "0.17.3" @@ -1285,13 +1062,13 @@ socks = ["socksio (==1.*)"] [[package]] name = "identify" -version = "2.5.26" +version = "2.5.27" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.26-py2.py3-none-any.whl", hash = "sha256:c22a8ead0d4ca11f1edd6c9418c3220669b3b7533ada0a0ffa6cc0ef85cf9b54"}, - {file = "identify-2.5.26.tar.gz", hash = "sha256:7243800bce2f58404ed41b7c002e53d4d22bcf3ae1b7900c2d7aefd95394bf7f"}, + {file = "identify-2.5.27-py2.py3-none-any.whl", hash = "sha256:fdb527b2dfe24602809b2201e033c2a113d7bdf716db3ca8e3243f735dcecaba"}, + {file = "identify-2.5.27.tar.gz", hash = "sha256:287b75b04a0e22d727bc9a41f0d4f3c1bcada97490fa6eabb5b28f0e9097e733"}, ] [package.extras] @@ -1583,26 +1360,24 @@ files = [ [[package]] name = "jsonschema" -version = "4.19.0" +version = "4.17.3" description = "An implementation of JSON Schema validation for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "jsonschema-4.19.0-py3-none-any.whl", hash = "sha256:043dc26a3845ff09d20e4420d6012a9c91c9aa8999fa184e7efcfeccb41e32cb"}, - {file = "jsonschema-4.19.0.tar.gz", hash = "sha256:6e1e7569ac13be8139b2dd2c21a55d350066ee3f80df06c608b398cdc6f30e8f"}, + {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, + {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, ] [package.dependencies] -attrs = ">=22.2.0" +attrs = ">=17.4.0" fqdn = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} idna = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} isoduration = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format-nongpl\""} -jsonschema-specifications = ">=2023.03.6" -referencing = ">=0.28.4" +pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} -rpds-py = ">=0.7.1" uri-template = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} webcolors = {version = ">=1.11", optional = true, markers = "extra == \"format-nongpl\""} @@ -1610,20 +1385,6 @@ webcolors = {version = ">=1.11", optional = true, markers = "extra == \"format-n format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] -[[package]] -name = "jsonschema-specifications" -version = "2023.7.1" -description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jsonschema_specifications-2023.7.1-py3-none-any.whl", hash = "sha256:05adf340b659828a004220a9613be00fa3f223f2b82002e273dee62fd50524b1"}, - {file = "jsonschema_specifications-2023.7.1.tar.gz", hash = "sha256:c91a50404e88a1f6ba40636778e2ee08f6e24c5613fe4c53ac24578a5a7f72bb"}, -] - -[package.dependencies] -referencing = ">=0.28.0" - [[package]] name = "jupyter" version = "1.0.0" @@ -1713,20 +1474,19 @@ test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] [[package]] name = "jupyter-events" -version = "0.7.0" +version = "0.6.3" description = "Jupyter Event System library" optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "jupyter_events-0.7.0-py3-none-any.whl", hash = "sha256:4753da434c13a37c3f3c89b500afa0c0a6241633441421f6adafe2fb2e2b924e"}, - {file = "jupyter_events-0.7.0.tar.gz", hash = "sha256:7be27f54b8388c03eefea123a4f79247c5b9381c49fb1cd48615ee191eb12615"}, + {file = "jupyter_events-0.6.3-py3-none-any.whl", hash = "sha256:57a2749f87ba387cd1bfd9b22a0875b889237dbf2edc2121ebb22bde47036c17"}, + {file = "jupyter_events-0.6.3.tar.gz", hash = "sha256:9a6e9995f75d1b7146b436ea24d696ce3a35bfa8bfe45e0c33c334c79464d0b3"}, ] [package.dependencies] -jsonschema = {version = ">=4.18.0", extras = ["format-nongpl"]} +jsonschema = {version = ">=3.2.0", extras = ["format-nongpl"]} python-json-logger = ">=2.0.4" pyyaml = ">=5.3" -referencing = "*" rfc3339-validator = "*" rfc3986-validator = ">=0.1.1" traitlets = ">=5.3" @@ -1734,7 +1494,7 @@ traitlets = ">=5.3" [package.extras] cli = ["click", "rich"] docs = ["jupyterlite-sphinx", "myst-parser", "pydata-sphinx-theme", "sphinxcontrib-spelling"] -test = ["click", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "pytest-console-scripts", "rich"] +test = ["click", "coverage", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "pytest-console-scripts", "pytest-cov", "rich"] [[package]] name = "jupyter-lsp" @@ -1888,13 +1648,13 @@ files = [ [[package]] name = "keyring" -version = "23.13.1" +version = "24.2.0" description = "Store and access your passwords safely." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "keyring-23.13.1-py3-none-any.whl", hash = "sha256:771ed2a91909389ed6148631de678f82ddc73737d85a927f382a8a1b157898cd"}, - {file = "keyring-23.13.1.tar.gz", hash = "sha256:ba2e15a9b35e21908d0aaf4e0a47acc52d6ae33444df0da2b49d41a46ef6d678"}, + {file = "keyring-24.2.0-py3-none-any.whl", hash = "sha256:4901caaf597bfd3bbd78c9a0c7c4c29fcd8310dab2cffefe749e916b6527acd6"}, + {file = "keyring-24.2.0.tar.gz", hash = "sha256:ca0746a19ec421219f4d713f848fa297a661a8a8c1504867e55bfb5e09091509"}, ] [package.dependencies] @@ -1906,8 +1666,8 @@ SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""} [package.extras] completion = ["shtab"] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] -testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [[package]] name = "lazy-object-proxy" @@ -1954,17 +1714,6 @@ files = [ {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, ] -[[package]] -name = "lockfile" -version = "0.12.2" -description = "Platform-independent file locking module" -optional = false -python-versions = "*" -files = [ - {file = "lockfile-0.12.2-py2.py3-none-any.whl", hash = "sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa"}, - {file = "lockfile-0.12.2.tar.gz", hash = "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799"}, -] - [[package]] name = "markdown-it-py" version = "3.0.0" @@ -2198,89 +1947,6 @@ files = [ {file = "msgpack-1.0.5.tar.gz", hash = "sha256:c075544284eadc5cddc70f4757331d99dcbc16b2bbd4849d15f8aae4cf36d31c"}, ] -[[package]] -name = "multidict" -version = "6.0.4" -description = "multidict implementation" -optional = false -python-versions = ">=3.7" -files = [ - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, - {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, - {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, - {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, - {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, - {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, - {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, - {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, - {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, - {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, - {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, - {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, - {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, -] - [[package]] name = "mypy" version = "1.5.1" @@ -2484,28 +2150,6 @@ jupyter-server = ">=1.8,<3" [package.extras] test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync"] -[[package]] -name = "openai" -version = "0.27.8" -description = "Python client library for the OpenAI API" -optional = false -python-versions = ">=3.7.1" -files = [ - {file = "openai-0.27.8-py3-none-any.whl", hash = "sha256:e0a7c2f7da26bdbe5354b03c6d4b82a2f34bd4458c7a17ae1a7092c3e397e03c"}, - {file = "openai-0.27.8.tar.gz", hash = "sha256:2483095c7db1eee274cebac79e315a986c4e55207bb4fa7b82d185b3a2ed9536"}, -] - -[package.dependencies] -aiohttp = "*" -requests = ">=2.20" -tqdm = "*" - -[package.extras] -datalib = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] -dev = ["black (>=21.6b0,<22.0)", "pytest (==6.*)", "pytest-asyncio", "pytest-mock"] -embeddings = ["matplotlib", "numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "plotly", "scikit-learn (>=1.0.2)", "scipy", "tenacity (>=8.0.1)"] -wandb = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "wandb"] - [[package]] name = "overrides" version = "7.4.0" @@ -2647,65 +2291,61 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "poetry" -version = "1.5.1" +version = "1.6.1" description = "Python dependency management and packaging made easy." optional = false -python-versions = ">=3.7,<4.0" +python-versions = ">=3.8,<4.0" files = [ - {file = "poetry-1.5.1-py3-none-any.whl", hash = "sha256:dfc7ce3a38ae216c0465694e2e674bef6eb1a2ba81aa47a26f9dc03362fe2f5f"}, - {file = "poetry-1.5.1.tar.gz", hash = "sha256:cc7ea4524d1a11558006224bfe8ba8ed071417d4eb5ef6c89decc6a37d437eeb"}, + {file = "poetry-1.6.1-py3-none-any.whl", hash = "sha256:9b4cb6079c08cc0d91e8cba18a6bd4d4f7d7830263a7fb18ecb3faa77937c988"}, + {file = "poetry-1.6.1.tar.gz", hash = "sha256:0ab9b1a592731cc8b252b8d6aaeea19c72cc0a109d7468b829ad57e6c48039d2"}, ] [package.dependencies] build = ">=0.10.0,<0.11.0" -cachecontrol = {version = ">=0.12.9,<0.13.0", extras = ["filecache"]} +cachecontrol = {version = ">=0.13.0,<0.14.0", extras = ["filecache"]} cleo = ">=2.0.0,<3.0.0" crashtest = ">=0.4.1,<0.5.0" dulwich = ">=0.21.2,<0.22.0" -filelock = ">=3.8.0,<4.0.0" -html5lib = ">=1.0,<2.0" importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} installer = ">=0.7.0,<0.8.0" -jsonschema = ">=4.10.0,<5.0.0" -keyring = ">=23.9.0,<24.0.0" -lockfile = ">=0.12.2,<0.13.0" +jsonschema = ">=4.10.0,<4.18.0" +keyring = ">=24.0.0,<25.0.0" packaging = ">=20.4" pexpect = ">=4.7.0,<5.0.0" pkginfo = ">=1.9.4,<2.0.0" platformdirs = ">=3.0.0,<4.0.0" -poetry-core = "1.6.1" -poetry-plugin-export = ">=1.4.0,<2.0.0" +poetry-core = "1.7.0" +poetry-plugin-export = ">=1.5.0,<2.0.0" pyproject-hooks = ">=1.0.0,<2.0.0" -requests = ">=2.18,<3.0" +requests = ">=2.26,<3.0" requests-toolbelt = ">=0.9.1,<2" shellingham = ">=1.5,<2.0" tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version < \"3.11\""} tomlkit = ">=0.11.4,<1.0.0" trove-classifiers = ">=2022.5.19" -urllib3 = ">=1.26.0,<2.0.0" virtualenv = ">=20.22.0,<21.0.0" xattr = {version = ">=0.10.0,<0.11.0", markers = "sys_platform == \"darwin\""} [[package]] name = "poetry-core" -version = "1.6.1" +version = "1.7.0" description = "Poetry PEP 517 Build Backend" optional = false -python-versions = ">=3.7,<4.0" +python-versions = ">=3.8,<4.0" files = [ - {file = "poetry_core-1.6.1-py3-none-any.whl", hash = "sha256:70707340447dee0e7f334f9495ae652481c67b32d8d218f296a376ac2ed73573"}, - {file = "poetry_core-1.6.1.tar.gz", hash = "sha256:0f9b0de39665f36d6594657e7d57b6f463cc10f30c28e6d1c3b9ff54c26c9ac3"}, + {file = "poetry_core-1.7.0-py3-none-any.whl", hash = "sha256:38e174cdb00a84ee4a1cab66a378b435747f72414f5573bc18cfc3850a94df38"}, + {file = "poetry_core-1.7.0.tar.gz", hash = "sha256:8f679b83bd9c820082637beca1204124d5d2a786e4818da47ec8acefd0353b74"}, ] [[package]] name = "poetry-plugin-dotenv" -version = "0.5.2" +version = "0.5.3" description = "poetry-plugin-dotenv - is the plugin that automatically loads environment variables from a dotenv file into the environment before poetry commands are run." optional = false python-versions = ">=3.8.1,<4.0" files = [ - {file = "poetry_plugin_dotenv-0.5.2-py3-none-any.whl", hash = "sha256:99ebe5bf73ad2ed9ea7eccd31f1128f1b517bfb6cdb46cdd6cf781987ff6f384"}, - {file = "poetry_plugin_dotenv-0.5.2.tar.gz", hash = "sha256:f705719efd0903eb1400a93883b5c266c77eef17a62f04b0013c375a6a9ed2de"}, + {file = "poetry_plugin_dotenv-0.5.3-py3-none-any.whl", hash = "sha256:a8e03a7c4dbb9f3d43f73f4742cf9d24b40f98a8566a146ba13de45e78024b17"}, + {file = "poetry_plugin_dotenv-0.5.3.tar.gz", hash = "sha256:abb74e0c01172440979275ba95c4b0c78c5450d971df03eb9ba61da4713d92ff"}, ] [package.dependencies] @@ -2713,13 +2353,13 @@ poetry = ">=1.5.1,<2.0.0" [[package]] name = "poetry-plugin-export" -version = "1.4.0" +version = "1.5.0" description = "Poetry plugin to export the dependencies to various formats" optional = false -python-versions = ">=3.7,<4.0" +python-versions = ">=3.8,<4.0" files = [ - {file = "poetry_plugin_export-1.4.0-py3-none-any.whl", hash = "sha256:5d9186d6f77cf2bf35fc96bd11fe650cc7656e515b17d99cb65018d50ba22589"}, - {file = "poetry_plugin_export-1.4.0.tar.gz", hash = "sha256:f16974cd9f222d4ef640fa97a8d661b04d4fb339e51da93973f1bc9d578e183f"}, + {file = "poetry_plugin_export-1.5.0-py3-none-any.whl", hash = "sha256:cd8267597970375ca29868daec5e7718bad500c7584663af3eeb0ed16f24e2bd"}, + {file = "poetry_plugin_export-1.5.0.tar.gz", hash = "sha256:ecc8738da0c81c3758e36b4e72e04ae59648a547492af2ffe6245af3594bb00f"}, ] [package.dependencies] @@ -3056,6 +2696,42 @@ files = [ [package.dependencies] tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +[[package]] +name = "pyrsistent" +version = "0.19.3" +description = "Persistent/Functional/Immutable data structures" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyrsistent-0.19.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:20460ac0ea439a3e79caa1dbd560344b64ed75e85d8703943e0b66c2a6150e4a"}, + {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c18264cb84b5e68e7085a43723f9e4c1fd1d935ab240ce02c0324a8e01ccb64"}, + {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b774f9288dda8d425adb6544e5903f1fb6c273ab3128a355c6b972b7df39dcf"}, + {file = "pyrsistent-0.19.3-cp310-cp310-win32.whl", hash = "sha256:5a474fb80f5e0d6c9394d8db0fc19e90fa540b82ee52dba7d246a7791712f74a"}, + {file = "pyrsistent-0.19.3-cp310-cp310-win_amd64.whl", hash = "sha256:49c32f216c17148695ca0e02a5c521e28a4ee6c5089f97e34fe24163113722da"}, + {file = "pyrsistent-0.19.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9"}, + {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab2204234c0ecd8b9368dbd6a53e83c3d4f3cab10ecaf6d0e772f456c442393"}, + {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e42296a09e83028b3476f7073fcb69ffebac0e66dbbfd1bd847d61f74db30f19"}, + {file = "pyrsistent-0.19.3-cp311-cp311-win32.whl", hash = "sha256:64220c429e42a7150f4bfd280f6f4bb2850f95956bde93c6fda1b70507af6ef3"}, + {file = "pyrsistent-0.19.3-cp311-cp311-win_amd64.whl", hash = "sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4db1bd596fefd66b296a3d5d943c94f4fac5bcd13e99bffe2ba6a759d959a28"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeda827381f5e5d65cced3024126529ddc4289d944f75e090572c77ceb19adbf"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42ac0b2f44607eb92ae88609eda931a4f0dfa03038c44c772e07f43e738bcac9"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-win32.whl", hash = "sha256:e8f2b814a3dc6225964fa03d8582c6e0b6650d68a232df41e3cc1b66a5d2f8d1"}, + {file = "pyrsistent-0.19.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9bb60a40a0ab9aba40a59f68214eed5a29c6274c83b2cc206a359c4a89fa41b"}, + {file = "pyrsistent-0.19.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a2471f3f8693101975b1ff85ffd19bb7ca7dd7c38f8a81701f67d6b4f97b87d8"}, + {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc5d149f31706762c1f8bda2e8c4f8fead6e80312e3692619a75301d3dbb819a"}, + {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3311cb4237a341aa52ab8448c27e3a9931e2ee09561ad150ba94e4cfd3fc888c"}, + {file = "pyrsistent-0.19.3-cp38-cp38-win32.whl", hash = "sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c"}, + {file = "pyrsistent-0.19.3-cp38-cp38-win_amd64.whl", hash = "sha256:c147257a92374fde8498491f53ffa8f4822cd70c0d85037e09028e478cababb7"}, + {file = "pyrsistent-0.19.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b735e538f74ec31378f5a1e3886a26d2ca6351106b4dfde376a26fc32a044edc"}, + {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99abb85579e2165bd8522f0c0138864da97847875ecbd45f3e7e2af569bfc6f2"}, + {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a8cb235fa6d3fd7aae6a4f1429bbb1fec1577d978098da1252f0489937786f3"}, + {file = "pyrsistent-0.19.3-cp39-cp39-win32.whl", hash = "sha256:c74bed51f9b41c48366a286395c67f4e894374306b197e62810e0fdaf2364da2"}, + {file = "pyrsistent-0.19.3-cp39-cp39-win_amd64.whl", hash = "sha256:878433581fc23e906d947a6814336eee031a00e6defba224234169ae3d3d6a98"}, + {file = "pyrsistent-0.19.3-py3-none-any.whl", hash = "sha256:ccf0d6bd208f8111179f0c26fdf84ed7c3891982f2edaeae7422575f47e66b64"}, + {file = "pyrsistent-0.19.3.tar.gz", hash = "sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440"}, +] + [[package]] name = "pytest" version = "7.4.0" @@ -3531,21 +3207,6 @@ files = [ [package.extras] full = ["numpy"] -[[package]] -name = "referencing" -version = "0.30.2" -description = "JSON Referencing + Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "referencing-0.30.2-py3-none-any.whl", hash = "sha256:449b6669b6121a9e96a7f9e410b245d471e8d48964c67113ce9afe50c8dd7bdf"}, - {file = "referencing-0.30.2.tar.gz", hash = "sha256:794ad8003c65938edcdbc027f1933215e0d0ccc0291e3ce20a4d87432b59efc0"}, -] - -[package.dependencies] -attrs = ">=22.2.0" -rpds-py = ">=0.7.0" - [[package]] name = "requests" version = "2.31.0" @@ -3624,112 +3285,6 @@ pygments = ">=2.13.0,<3.0.0" [package.extras] jupyter = ["ipywidgets (>=7.5.1,<9)"] -[[package]] -name = "rpds-py" -version = "0.9.2" -description = "Python bindings to Rust's persistent data structures (rpds)" -optional = false -python-versions = ">=3.8" -files = [ - {file = "rpds_py-0.9.2-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:ab6919a09c055c9b092798ce18c6c4adf49d24d4d9e43a92b257e3f2548231e7"}, - {file = "rpds_py-0.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d55777a80f78dd09410bd84ff8c95ee05519f41113b2df90a69622f5540c4f8b"}, - {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a216b26e5af0a8e265d4efd65d3bcec5fba6b26909014effe20cd302fd1138fa"}, - {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29cd8bfb2d716366a035913ced99188a79b623a3512292963d84d3e06e63b496"}, - {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44659b1f326214950a8204a248ca6199535e73a694be8d3e0e869f820767f12f"}, - {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:745f5a43fdd7d6d25a53ab1a99979e7f8ea419dfefebcab0a5a1e9095490ee5e"}, - {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a987578ac5214f18b99d1f2a3851cba5b09f4a689818a106c23dbad0dfeb760f"}, - {file = "rpds_py-0.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bf4151acb541b6e895354f6ff9ac06995ad9e4175cbc6d30aaed08856558201f"}, - {file = "rpds_py-0.9.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:03421628f0dc10a4119d714a17f646e2837126a25ac7a256bdf7c3943400f67f"}, - {file = "rpds_py-0.9.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:13b602dc3e8dff3063734f02dcf05111e887f301fdda74151a93dbbc249930fe"}, - {file = "rpds_py-0.9.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fae5cb554b604b3f9e2c608241b5d8d303e410d7dfb6d397c335f983495ce7f6"}, - {file = "rpds_py-0.9.2-cp310-none-win32.whl", hash = "sha256:47c5f58a8e0c2c920cc7783113df2fc4ff12bf3a411d985012f145e9242a2764"}, - {file = "rpds_py-0.9.2-cp310-none-win_amd64.whl", hash = "sha256:4ea6b73c22d8182dff91155af018b11aac9ff7eca085750455c5990cb1cfae6e"}, - {file = "rpds_py-0.9.2-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:e564d2238512c5ef5e9d79338ab77f1cbbda6c2d541ad41b2af445fb200385e3"}, - {file = "rpds_py-0.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f411330a6376fb50e5b7a3e66894e4a39e60ca2e17dce258d53768fea06a37bd"}, - {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e7521f5af0233e89939ad626b15278c71b69dc1dfccaa7b97bd4cdf96536bb7"}, - {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8d3335c03100a073883857e91db9f2e0ef8a1cf42dc0369cbb9151c149dbbc1b"}, - {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d25b1c1096ef0447355f7293fbe9ad740f7c47ae032c2884113f8e87660d8f6e"}, - {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a5d3fbd02efd9cf6a8ffc2f17b53a33542f6b154e88dd7b42ef4a4c0700fdad"}, - {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5934e2833afeaf36bd1eadb57256239785f5af0220ed8d21c2896ec4d3a765f"}, - {file = "rpds_py-0.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:095b460e117685867d45548fbd8598a8d9999227e9061ee7f012d9d264e6048d"}, - {file = "rpds_py-0.9.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:91378d9f4151adc223d584489591dbb79f78814c0734a7c3bfa9c9e09978121c"}, - {file = "rpds_py-0.9.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:24a81c177379300220e907e9b864107614b144f6c2a15ed5c3450e19cf536fae"}, - {file = "rpds_py-0.9.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:de0b6eceb46141984671802d412568d22c6bacc9b230174f9e55fc72ef4f57de"}, - {file = "rpds_py-0.9.2-cp311-none-win32.whl", hash = "sha256:700375326ed641f3d9d32060a91513ad668bcb7e2cffb18415c399acb25de2ab"}, - {file = "rpds_py-0.9.2-cp311-none-win_amd64.whl", hash = "sha256:0766babfcf941db8607bdaf82569ec38107dbb03c7f0b72604a0b346b6eb3298"}, - {file = "rpds_py-0.9.2-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:b1440c291db3f98a914e1afd9d6541e8fc60b4c3aab1a9008d03da4651e67386"}, - {file = "rpds_py-0.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0f2996fbac8e0b77fd67102becb9229986396e051f33dbceada3debaacc7033f"}, - {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f30d205755566a25f2ae0382944fcae2f350500ae4df4e795efa9e850821d82"}, - {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:159fba751a1e6b1c69244e23ba6c28f879a8758a3e992ed056d86d74a194a0f3"}, - {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1f044792e1adcea82468a72310c66a7f08728d72a244730d14880cd1dabe36b"}, - {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9251eb8aa82e6cf88510530b29eef4fac825a2b709baf5b94a6094894f252387"}, - {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01899794b654e616c8625b194ddd1e5b51ef5b60ed61baa7a2d9c2ad7b2a4238"}, - {file = "rpds_py-0.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0c43f8ae8f6be1d605b0465671124aa8d6a0e40f1fb81dcea28b7e3d87ca1e1"}, - {file = "rpds_py-0.9.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:207f57c402d1f8712618f737356e4b6f35253b6d20a324d9a47cb9f38ee43a6b"}, - {file = "rpds_py-0.9.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b52e7c5ae35b00566d244ffefba0f46bb6bec749a50412acf42b1c3f402e2c90"}, - {file = "rpds_py-0.9.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:978fa96dbb005d599ec4fd9ed301b1cc45f1a8f7982d4793faf20b404b56677d"}, - {file = "rpds_py-0.9.2-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:6aa8326a4a608e1c28da191edd7c924dff445251b94653988efb059b16577a4d"}, - {file = "rpds_py-0.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aad51239bee6bff6823bbbdc8ad85136c6125542bbc609e035ab98ca1e32a192"}, - {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bd4dc3602370679c2dfb818d9c97b1137d4dd412230cfecd3c66a1bf388a196"}, - {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dd9da77c6ec1f258387957b754f0df60766ac23ed698b61941ba9acccd3284d1"}, - {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:190ca6f55042ea4649ed19c9093a9be9d63cd8a97880106747d7147f88a49d18"}, - {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:876bf9ed62323bc7dcfc261dbc5572c996ef26fe6406b0ff985cbcf460fc8a4c"}, - {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa2818759aba55df50592ecbc95ebcdc99917fa7b55cc6796235b04193eb3c55"}, - {file = "rpds_py-0.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9ea4d00850ef1e917815e59b078ecb338f6a8efda23369677c54a5825dbebb55"}, - {file = "rpds_py-0.9.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:5855c85eb8b8a968a74dc7fb014c9166a05e7e7a8377fb91d78512900aadd13d"}, - {file = "rpds_py-0.9.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:14c408e9d1a80dcb45c05a5149e5961aadb912fff42ca1dd9b68c0044904eb32"}, - {file = "rpds_py-0.9.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:65a0583c43d9f22cb2130c7b110e695fff834fd5e832a776a107197e59a1898e"}, - {file = "rpds_py-0.9.2-cp38-none-win32.whl", hash = "sha256:71f2f7715935a61fa3e4ae91d91b67e571aeb5cb5d10331ab681256bda2ad920"}, - {file = "rpds_py-0.9.2-cp38-none-win_amd64.whl", hash = "sha256:674c704605092e3ebbbd13687b09c9f78c362a4bc710343efe37a91457123044"}, - {file = "rpds_py-0.9.2-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:07e2c54bef6838fa44c48dfbc8234e8e2466d851124b551fc4e07a1cfeb37260"}, - {file = "rpds_py-0.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f7fdf55283ad38c33e35e2855565361f4bf0abd02470b8ab28d499c663bc5d7c"}, - {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:890ba852c16ace6ed9f90e8670f2c1c178d96510a21b06d2fa12d8783a905193"}, - {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:50025635ba8b629a86d9d5474e650da304cb46bbb4d18690532dd79341467846"}, - {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:517cbf6e67ae3623c5127206489d69eb2bdb27239a3c3cc559350ef52a3bbf0b"}, - {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0836d71ca19071090d524739420a61580f3f894618d10b666cf3d9a1688355b1"}, - {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c439fd54b2b9053717cca3de9583be6584b384d88d045f97d409f0ca867d80f"}, - {file = "rpds_py-0.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f68996a3b3dc9335037f82754f9cdbe3a95db42bde571d8c3be26cc6245f2324"}, - {file = "rpds_py-0.9.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7d68dc8acded354c972116f59b5eb2e5864432948e098c19fe6994926d8e15c3"}, - {file = "rpds_py-0.9.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f963c6b1218b96db85fc37a9f0851eaf8b9040aa46dec112611697a7023da535"}, - {file = "rpds_py-0.9.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5a46859d7f947061b4010e554ccd1791467d1b1759f2dc2ec9055fa239f1bc26"}, - {file = "rpds_py-0.9.2-cp39-none-win32.whl", hash = "sha256:e07e5dbf8a83c66783a9fe2d4566968ea8c161199680e8ad38d53e075df5f0d0"}, - {file = "rpds_py-0.9.2-cp39-none-win_amd64.whl", hash = "sha256:682726178138ea45a0766907957b60f3a1bf3acdf212436be9733f28b6c5af3c"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:196cb208825a8b9c8fc360dc0f87993b8b260038615230242bf18ec84447c08d"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:c7671d45530fcb6d5e22fd40c97e1e1e01965fc298cbda523bb640f3d923b387"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83b32f0940adec65099f3b1c215ef7f1d025d13ff947975a055989cb7fd019a4"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f67da97f5b9eac838b6980fc6da268622e91f8960e083a34533ca710bec8611"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03975db5f103997904c37e804e5f340c8fdabbb5883f26ee50a255d664eed58c"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:987b06d1cdb28f88a42e4fb8a87f094e43f3c435ed8e486533aea0bf2e53d931"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c861a7e4aef15ff91233751619ce3a3d2b9e5877e0fcd76f9ea4f6847183aa16"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:02938432352359805b6da099c9c95c8a0547fe4b274ce8f1a91677401bb9a45f"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:ef1f08f2a924837e112cba2953e15aacfccbbfcd773b4b9b4723f8f2ddded08e"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:35da5cc5cb37c04c4ee03128ad59b8c3941a1e5cd398d78c37f716f32a9b7f67"}, - {file = "rpds_py-0.9.2-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:141acb9d4ccc04e704e5992d35472f78c35af047fa0cfae2923835d153f091be"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:79f594919d2c1a0cc17d1988a6adaf9a2f000d2e1048f71f298b056b1018e872"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:a06418fe1155e72e16dddc68bb3780ae44cebb2912fbd8bb6ff9161de56e1798"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b2eb034c94b0b96d5eddb290b7b5198460e2d5d0c421751713953a9c4e47d10"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b08605d248b974eb02f40bdcd1a35d3924c83a2a5e8f5d0fa5af852c4d960af"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a0805911caedfe2736935250be5008b261f10a729a303f676d3d5fea6900c96a"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab2299e3f92aa5417d5e16bb45bb4586171c1327568f638e8453c9f8d9e0f020"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c8d7594e38cf98d8a7df25b440f684b510cf4627fe038c297a87496d10a174f"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8b9ec12ad5f0a4625db34db7e0005be2632c1013b253a4a60e8302ad4d462afd"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1fcdee18fea97238ed17ab6478c66b2095e4ae7177e35fb71fbe561a27adf620"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:933a7d5cd4b84f959aedeb84f2030f0a01d63ae6cf256629af3081cf3e3426e8"}, - {file = "rpds_py-0.9.2-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:686ba516e02db6d6f8c279d1641f7067ebb5dc58b1d0536c4aaebb7bf01cdc5d"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:0173c0444bec0a3d7d848eaeca2d8bd32a1b43f3d3fde6617aac3731fa4be05f"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:d576c3ef8c7b2d560e301eb33891d1944d965a4d7a2eacb6332eee8a71827db6"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed89861ee8c8c47d6beb742a602f912b1bb64f598b1e2f3d758948721d44d468"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1054a08e818f8e18910f1bee731583fe8f899b0a0a5044c6e680ceea34f93876"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99e7c4bb27ff1aab90dcc3e9d37ee5af0231ed98d99cb6f5250de28889a3d502"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c545d9d14d47be716495076b659db179206e3fd997769bc01e2d550eeb685596"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9039a11bca3c41be5a58282ed81ae422fa680409022b996032a43badef2a3752"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fb39aca7a64ad0c9490adfa719dbeeb87d13be137ca189d2564e596f8ba32c07"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2d8b3b3a2ce0eaa00c5bbbb60b6713e94e7e0becab7b3db6c5c77f979e8ed1f1"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:99b1c16f732b3a9971406fbfe18468592c5a3529585a45a35adbc1389a529a03"}, - {file = "rpds_py-0.9.2-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c27ee01a6c3223025f4badd533bea5e87c988cb0ba2811b690395dfe16088cfe"}, - {file = "rpds_py-0.9.2.tar.gz", hash = "sha256:8d70e8f14900f2657c249ea4def963bed86a29b81f81f5b76b5a9215680de945"}, -] - [[package]] name = "ruamel-yaml" version = "0.17.32" @@ -4057,26 +3612,6 @@ files = [ {file = "tornado-6.3.3.tar.gz", hash = "sha256:e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe"}, ] -[[package]] -name = "tqdm" -version = "4.66.1" -description = "Fast, Extensible Progress Meter" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"}, - {file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[package.extras] -dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] -notebook = ["ipywidgets (>=6)"] -slack = ["slack-sdk"] -telegram = ["requests"] - [[package]] name = "traitlets" version = "5.9.0" @@ -4130,19 +3665,20 @@ dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake [[package]] name = "urllib3" -version = "1.26.16" +version = "2.0.4" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.7" files = [ - {file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"}, - {file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"}, + {file = "urllib3-2.0.4-py3-none-any.whl", hash = "sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"}, + {file = "urllib3-2.0.4.tar.gz", hash = "sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" @@ -4203,17 +3739,17 @@ files = [ [[package]] name = "websocket-client" -version = "1.6.1" +version = "1.6.2" description = "WebSocket client for Python with low level API options" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "websocket-client-1.6.1.tar.gz", hash = "sha256:c951af98631d24f8df89ab1019fc365f2227c0892f12fd150e935607c79dd0dd"}, - {file = "websocket_client-1.6.1-py3-none-any.whl", hash = "sha256:f1f9f2ad5291f0225a49efad77abf9e700b6fef553900623060dad6e26503b9d"}, + {file = "websocket-client-1.6.2.tar.gz", hash = "sha256:53e95c826bf800c4c465f50093a8c4ff091c7327023b10bfaff40cf1ef170eaa"}, + {file = "websocket_client-1.6.2-py3-none-any.whl", hash = "sha256:ce54f419dfae71f4bdba69ebe65bf7f0a93fe71bc009ad3a010aacc3eebad537"}, ] [package.extras] -docs = ["Sphinx (>=3.4)", "sphinx-rtd-theme (>=0.5)"] +docs = ["Sphinx (>=6.0)", "sphinx-rtd-theme (>=1.1.0)"] optional = ["python-socks", "wsaccel"] test = ["websockets"] @@ -4396,93 +3932,6 @@ files = [ [package.dependencies] cffi = ">=1.0" -[[package]] -name = "yarl" -version = "1.9.2" -description = "Yet another URL library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, - {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, - {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, - {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, - {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, - {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, - {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, - {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, - {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, - {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, - {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, - {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, - {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, - {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, - {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, -] - -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" - [[package]] name = "zipp" version = "3.16.2" @@ -4501,4 +3950,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "0553beb077e2839046c1f156be1c65f2b1a28c591084b45c8a0e54db00c57cb7" +content-hash = "981fc2dd02bbbd417df85c66ee96dc6cc52ae2383a0b81614fa82bda9df9a1bc" diff --git a/pyproject.toml b/pyproject.toml index dd031588..7270e577 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,7 +58,6 @@ coverage-badge = "^1.1.0" pytest-html = "^3.1.1" pytest-cov = "^4.1.0" pydantic = "^2.2.1" -openai = "^0.27.8" [tool.black] # https://github.com/psf/black From dbd3e5336d4b371bbe68d7b2f1fee26af669800f Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Thu, 24 Aug 2023 14:09:22 -0700 Subject: [PATCH 07/15] cleanup --- poetry.lock | 150 +------------------------------------------------ pyproject.toml | 1 - 2 files changed, 1 insertion(+), 150 deletions(-) diff --git a/poetry.lock b/poetry.lock index b542c736..9ac3e5b9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,16 +1,5 @@ # This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. -[[package]] -name = "annotated-types" -version = "0.5.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.7" -files = [ - {file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"}, - {file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"}, -] - [[package]] name = "anyio" version = "3.7.1" @@ -2485,143 +2474,6 @@ files = [ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] -[[package]] -name = "pydantic" -version = "2.3.0" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pydantic-2.3.0-py3-none-any.whl", hash = "sha256:45b5e446c6dfaad9444819a293b921a40e1db1aa61ea08aede0522529ce90e81"}, - {file = "pydantic-2.3.0.tar.gz", hash = "sha256:1607cc106602284cd4a00882986570472f193fde9cb1259bceeaedb26aa79a6d"}, -] - -[package.dependencies] -annotated-types = ">=0.4.0" -pydantic-core = "2.6.3" -typing-extensions = ">=4.6.1" - -[package.extras] -email = ["email-validator (>=2.0.0)"] - -[[package]] -name = "pydantic-core" -version = "2.6.3" -description = "" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pydantic_core-2.6.3-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:1a0ddaa723c48af27d19f27f1c73bdc615c73686d763388c8683fe34ae777bad"}, - {file = "pydantic_core-2.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5cfde4fab34dd1e3a3f7f3db38182ab6c95e4ea91cf322242ee0be5c2f7e3d2f"}, - {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5493a7027bfc6b108e17c3383959485087d5942e87eb62bbac69829eae9bc1f7"}, - {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:84e87c16f582f5c753b7f39a71bd6647255512191be2d2dbf49458c4ef024588"}, - {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:522a9c4a4d1924facce7270c84b5134c5cabcb01513213662a2e89cf28c1d309"}, - {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaafc776e5edc72b3cad1ccedb5fd869cc5c9a591f1213aa9eba31a781be9ac1"}, - {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a750a83b2728299ca12e003d73d1264ad0440f60f4fc9cee54acc489249b728"}, - {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e8b374ef41ad5c461efb7a140ce4730661aadf85958b5c6a3e9cf4e040ff4bb"}, - {file = "pydantic_core-2.6.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b594b64e8568cf09ee5c9501ede37066b9fc41d83d58f55b9952e32141256acd"}, - {file = "pydantic_core-2.6.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2a20c533cb80466c1d42a43a4521669ccad7cf2967830ac62c2c2f9cece63e7e"}, - {file = "pydantic_core-2.6.3-cp310-none-win32.whl", hash = "sha256:04fe5c0a43dec39aedba0ec9579001061d4653a9b53a1366b113aca4a3c05ca7"}, - {file = "pydantic_core-2.6.3-cp310-none-win_amd64.whl", hash = "sha256:6bf7d610ac8f0065a286002a23bcce241ea8248c71988bda538edcc90e0c39ad"}, - {file = "pydantic_core-2.6.3-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:6bcc1ad776fffe25ea5c187a028991c031a00ff92d012ca1cc4714087e575973"}, - {file = "pydantic_core-2.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:df14f6332834444b4a37685810216cc8fe1fe91f447332cd56294c984ecbff1c"}, - {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0b7486d85293f7f0bbc39b34e1d8aa26210b450bbd3d245ec3d732864009819"}, - {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a892b5b1871b301ce20d40b037ffbe33d1407a39639c2b05356acfef5536d26a"}, - {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:883daa467865e5766931e07eb20f3e8152324f0adf52658f4d302242c12e2c32"}, - {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4eb77df2964b64ba190eee00b2312a1fd7a862af8918ec70fc2d6308f76ac64"}, - {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce8c84051fa292a5dc54018a40e2a1926fd17980a9422c973e3ebea017aa8da"}, - {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:22134a4453bd59b7d1e895c455fe277af9d9d9fbbcb9dc3f4a97b8693e7e2c9b"}, - {file = "pydantic_core-2.6.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:02e1c385095efbd997311d85c6021d32369675c09bcbfff3b69d84e59dc103f6"}, - {file = "pydantic_core-2.6.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d79f1f2f7ebdb9b741296b69049ff44aedd95976bfee38eb4848820628a99b50"}, - {file = "pydantic_core-2.6.3-cp311-none-win32.whl", hash = "sha256:430ddd965ffd068dd70ef4e4d74f2c489c3a313adc28e829dd7262cc0d2dd1e8"}, - {file = "pydantic_core-2.6.3-cp311-none-win_amd64.whl", hash = "sha256:84f8bb34fe76c68c9d96b77c60cef093f5e660ef8e43a6cbfcd991017d375950"}, - {file = "pydantic_core-2.6.3-cp311-none-win_arm64.whl", hash = "sha256:5a2a3c9ef904dcdadb550eedf3291ec3f229431b0084666e2c2aa8ff99a103a2"}, - {file = "pydantic_core-2.6.3-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:8421cf496e746cf8d6b677502ed9a0d1e4e956586cd8b221e1312e0841c002d5"}, - {file = "pydantic_core-2.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bb128c30cf1df0ab78166ded1ecf876620fb9aac84d2413e8ea1594b588c735d"}, - {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37a822f630712817b6ecc09ccc378192ef5ff12e2c9bae97eb5968a6cdf3b862"}, - {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:240a015102a0c0cc8114f1cba6444499a8a4d0333e178bc504a5c2196defd456"}, - {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f90e5e3afb11268628c89f378f7a1ea3f2fe502a28af4192e30a6cdea1e7d5e"}, - {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:340e96c08de1069f3d022a85c2a8c63529fd88709468373b418f4cf2c949fb0e"}, - {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1480fa4682e8202b560dcdc9eeec1005f62a15742b813c88cdc01d44e85308e5"}, - {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f14546403c2a1d11a130b537dda28f07eb6c1805a43dae4617448074fd49c282"}, - {file = "pydantic_core-2.6.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a87c54e72aa2ef30189dc74427421e074ab4561cf2bf314589f6af5b37f45e6d"}, - {file = "pydantic_core-2.6.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f93255b3e4d64785554e544c1c76cd32f4a354fa79e2eeca5d16ac2e7fdd57aa"}, - {file = "pydantic_core-2.6.3-cp312-none-win32.whl", hash = "sha256:f70dc00a91311a1aea124e5f64569ea44c011b58433981313202c46bccbec0e1"}, - {file = "pydantic_core-2.6.3-cp312-none-win_amd64.whl", hash = "sha256:23470a23614c701b37252618e7851e595060a96a23016f9a084f3f92f5ed5881"}, - {file = "pydantic_core-2.6.3-cp312-none-win_arm64.whl", hash = "sha256:1ac1750df1b4339b543531ce793b8fd5c16660a95d13aecaab26b44ce11775e9"}, - {file = "pydantic_core-2.6.3-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:a53e3195f134bde03620d87a7e2b2f2046e0e5a8195e66d0f244d6d5b2f6d31b"}, - {file = "pydantic_core-2.6.3-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:f2969e8f72c6236c51f91fbb79c33821d12a811e2a94b7aa59c65f8dbdfad34a"}, - {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:672174480a85386dd2e681cadd7d951471ad0bb028ed744c895f11f9d51b9ebe"}, - {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:002d0ea50e17ed982c2d65b480bd975fc41086a5a2f9c924ef8fc54419d1dea3"}, - {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ccc13afee44b9006a73d2046068d4df96dc5b333bf3509d9a06d1b42db6d8bf"}, - {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:439a0de139556745ae53f9cc9668c6c2053444af940d3ef3ecad95b079bc9987"}, - {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d63b7545d489422d417a0cae6f9898618669608750fc5e62156957e609e728a5"}, - {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b44c42edc07a50a081672e25dfe6022554b47f91e793066a7b601ca290f71e42"}, - {file = "pydantic_core-2.6.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1c721bfc575d57305dd922e6a40a8fe3f762905851d694245807a351ad255c58"}, - {file = "pydantic_core-2.6.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5e4a2cf8c4543f37f5dc881de6c190de08096c53986381daebb56a355be5dfe6"}, - {file = "pydantic_core-2.6.3-cp37-none-win32.whl", hash = "sha256:d9b4916b21931b08096efed090327f8fe78e09ae8f5ad44e07f5c72a7eedb51b"}, - {file = "pydantic_core-2.6.3-cp37-none-win_amd64.whl", hash = "sha256:a8acc9dedd304da161eb071cc7ff1326aa5b66aadec9622b2574ad3ffe225525"}, - {file = "pydantic_core-2.6.3-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:5e9c068f36b9f396399d43bfb6defd4cc99c36215f6ff33ac8b9c14ba15bdf6b"}, - {file = "pydantic_core-2.6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e61eae9b31799c32c5f9b7be906be3380e699e74b2db26c227c50a5fc7988698"}, - {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85463560c67fc65cd86153a4975d0b720b6d7725cf7ee0b2d291288433fc21b"}, - {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9616567800bdc83ce136e5847d41008a1d602213d024207b0ff6cab6753fe645"}, - {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e9b65a55bbabda7fccd3500192a79f6e474d8d36e78d1685496aad5f9dbd92c"}, - {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f468d520f47807d1eb5d27648393519655eadc578d5dd862d06873cce04c4d1b"}, - {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9680dd23055dd874173a3a63a44e7f5a13885a4cfd7e84814be71be24fba83db"}, - {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a718d56c4d55efcfc63f680f207c9f19c8376e5a8a67773535e6f7e80e93170"}, - {file = "pydantic_core-2.6.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8ecbac050856eb6c3046dea655b39216597e373aa8e50e134c0e202f9c47efec"}, - {file = "pydantic_core-2.6.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:788be9844a6e5c4612b74512a76b2153f1877cd845410d756841f6c3420230eb"}, - {file = "pydantic_core-2.6.3-cp38-none-win32.whl", hash = "sha256:07a1aec07333bf5adebd8264047d3dc518563d92aca6f2f5b36f505132399efc"}, - {file = "pydantic_core-2.6.3-cp38-none-win_amd64.whl", hash = "sha256:621afe25cc2b3c4ba05fff53525156d5100eb35c6e5a7cf31d66cc9e1963e378"}, - {file = "pydantic_core-2.6.3-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:813aab5bfb19c98ae370952b6f7190f1e28e565909bfc219a0909db168783465"}, - {file = "pydantic_core-2.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:50555ba3cb58f9861b7a48c493636b996a617db1a72c18da4d7f16d7b1b9952b"}, - {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19e20f8baedd7d987bd3f8005c146e6bcbda7cdeefc36fad50c66adb2dd2da48"}, - {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b0a5d7edb76c1c57b95df719af703e796fc8e796447a1da939f97bfa8a918d60"}, - {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f06e21ad0b504658a3a9edd3d8530e8cea5723f6ea5d280e8db8efc625b47e49"}, - {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea053cefa008fda40f92aab937fb9f183cf8752e41dbc7bc68917884454c6362"}, - {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:171a4718860790f66d6c2eda1d95dd1edf64f864d2e9f9115840840cf5b5713f"}, - {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ed7ceca6aba5331ece96c0e328cd52f0dcf942b8895a1ed2642de50800b79d3"}, - {file = "pydantic_core-2.6.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:acafc4368b289a9f291e204d2c4c75908557d4f36bd3ae937914d4529bf62a76"}, - {file = "pydantic_core-2.6.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1aa712ba150d5105814e53cb141412217146fedc22621e9acff9236d77d2a5ef"}, - {file = "pydantic_core-2.6.3-cp39-none-win32.whl", hash = "sha256:44b4f937b992394a2e81a5c5ce716f3dcc1237281e81b80c748b2da6dd5cf29a"}, - {file = "pydantic_core-2.6.3-cp39-none-win_amd64.whl", hash = "sha256:9b33bf9658cb29ac1a517c11e865112316d09687d767d7a0e4a63d5c640d1b17"}, - {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d7050899026e708fb185e174c63ebc2c4ee7a0c17b0a96ebc50e1f76a231c057"}, - {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:99faba727727b2e59129c59542284efebbddade4f0ae6a29c8b8d3e1f437beb7"}, - {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fa159b902d22b283b680ef52b532b29554ea2a7fc39bf354064751369e9dbd7"}, - {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:046af9cfb5384f3684eeb3f58a48698ddab8dd870b4b3f67f825353a14441418"}, - {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:930bfe73e665ebce3f0da2c6d64455098aaa67e1a00323c74dc752627879fc67"}, - {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:85cc4d105747d2aa3c5cf3e37dac50141bff779545ba59a095f4a96b0a460e70"}, - {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b25afe9d5c4f60dcbbe2b277a79be114e2e65a16598db8abee2a2dcde24f162b"}, - {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e49ce7dc9f925e1fb010fc3d555250139df61fa6e5a0a95ce356329602c11ea9"}, - {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:2dd50d6a1aef0426a1d0199190c6c43ec89812b1f409e7fe44cb0fbf6dfa733c"}, - {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6595b0d8c8711e8e1dc389d52648b923b809f68ac1c6f0baa525c6440aa0daa"}, - {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ef724a059396751aef71e847178d66ad7fc3fc969a1a40c29f5aac1aa5f8784"}, - {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3c8945a105f1589ce8a693753b908815e0748f6279959a4530f6742e1994dcb6"}, - {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c8c6660089a25d45333cb9db56bb9e347241a6d7509838dbbd1931d0e19dbc7f"}, - {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:692b4ff5c4e828a38716cfa92667661a39886e71136c97b7dac26edef18767f7"}, - {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:f1a5d8f18877474c80b7711d870db0eeef9442691fcdb00adabfc97e183ee0b0"}, - {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:3796a6152c545339d3b1652183e786df648ecdf7c4f9347e1d30e6750907f5bb"}, - {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b962700962f6e7a6bd77e5f37320cabac24b4c0f76afeac05e9f93cf0c620014"}, - {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56ea80269077003eaa59723bac1d8bacd2cd15ae30456f2890811efc1e3d4413"}, - {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75c0ebbebae71ed1e385f7dfd9b74c1cff09fed24a6df43d326dd7f12339ec34"}, - {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:252851b38bad3bfda47b104ffd077d4f9604a10cb06fe09d020016a25107bf98"}, - {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:6656a0ae383d8cd7cc94e91de4e526407b3726049ce8d7939049cbfa426518c8"}, - {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d9140ded382a5b04a1c030b593ed9bf3088243a0a8b7fa9f071a5736498c5483"}, - {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d38bbcef58220f9c81e42c255ef0bf99735d8f11edef69ab0b499da77105158a"}, - {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c9d469204abcca28926cbc28ce98f28e50e488767b084fb3fbdf21af11d3de26"}, - {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:48c1ed8b02ffea4d5c9c220eda27af02b8149fe58526359b3c07eb391cb353a2"}, - {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b2b1bfed698fa410ab81982f681f5b1996d3d994ae8073286515ac4d165c2e7"}, - {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf9d42a71a4d7a7c1f14f629e5c30eac451a6fc81827d2beefd57d014c006c4a"}, - {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4292ca56751aebbe63a84bbfc3b5717abb09b14d4b4442cc43fd7c49a1529efd"}, - {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7dc2ce039c7290b4ef64334ec7e6ca6494de6eecc81e21cb4f73b9b39991408c"}, - {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:615a31b1629e12445c0e9fc8339b41aaa6cc60bd53bf802d5fe3d2c0cda2ae8d"}, - {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1fa1f6312fb84e8c281f32b39affe81984ccd484da6e9d65b3d18c202c666149"}, - {file = "pydantic_core-2.6.3.tar.gz", hash = "sha256:1508f37ba9e3ddc0189e6ff4e2228bd2d3c3a4641cbe8c07177162f76ed696c7"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - [[package]] name = "pydocstyle" version = "6.3.0" @@ -3950,4 +3802,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "981fc2dd02bbbd417df85c66ee96dc6cc52ae2383a0b81614fa82bda9df9a1bc" +content-hash = "d43b7ecf531579cf4bb4802196642b89655fcada52235c4c318147d0c6b03ec7" diff --git a/pyproject.toml b/pyproject.toml index 7270e577..6ce621b8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,7 +57,6 @@ coverage = "^7.2.7" coverage-badge = "^1.1.0" pytest-html = "^3.1.1" pytest-cov = "^4.1.0" -pydantic = "^2.2.1" [tool.black] # https://github.com/psf/black From 5b514c5e426b251999af1b93872145eb924e549a Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Thu, 24 Aug 2023 14:11:06 -0700 Subject: [PATCH 08/15] cleanup --- parea/cookbook/tracing_with_Parea_sdk.ipynb | 157 ++++++++++---------- 1 file changed, 77 insertions(+), 80 deletions(-) diff --git a/parea/cookbook/tracing_with_Parea_sdk.ipynb b/parea/cookbook/tracing_with_Parea_sdk.ipynb index b94f5796..9a28d626 100644 --- a/parea/cookbook/tracing_with_Parea_sdk.ipynb +++ b/parea/cookbook/tracing_with_Parea_sdk.ipynb @@ -113,55 +113,54 @@ "\n", "# We pass the deployment_id and the required inputs to the completion function along with the trace_id\n", "def argument_generator(query: str, additional_description: str = \"\", trace_id: Optional[str] = None, **kwargs) -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-RG8d9sssc_0cctwfpb_n6\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " },\n", - " trace_id=trace_id,\n", - " **kwargs,\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-RG8d9sssc_0cctwfpb_n6\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " },\n", + " trace_id=trace_id,\n", + " **kwargs,\n", + " )\n", + " ).content\n", "\n", "\n", "def critic(argument: str, trace_id: Optional[str] = None, **kwargs) -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-fXgZytVVVJjXD_71TDR4s\",\n", - " llm_inputs={\"argument\": argument},\n", - " trace_id=trace_id,\n", - " **kwargs,\n", - " )\n", - " ).content\n", - "\n", - "\n", - "def refiner(query: str, additional_description: str, current_arg: str, criticism: str, trace_id: Optional[str] = None,\n", - " **kwargs) -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p--G2s9okMTWWWh3d8YqLY2\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " \"current_arg\": current_arg,\n", - " \"criticism\": criticism,\n", - " },\n", - " trace_id=trace_id,\n", - " **kwargs,\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-fXgZytVVVJjXD_71TDR4s\",\n", + " llm_inputs={\"argument\": argument},\n", + " trace_id=trace_id,\n", + " **kwargs,\n", + " )\n", + " ).content\n", + "\n", + "\n", + "def refiner(query: str, additional_description: str, current_arg: str, criticism: str, trace_id: Optional[str] = None, **kwargs) -> str:\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p--G2s9okMTWWWh3d8YqLY2\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " \"current_arg\": current_arg,\n", + " \"criticism\": criticism,\n", + " },\n", + " trace_id=trace_id,\n", + " **kwargs,\n", + " )\n", + " ).content\n", "\n", "\n", "# This is the parent function which orchestrates the chaining. We'll define our trace_id and trace_name here\n", "def argument_chain(query: str, additional_description: str = \"\") -> str:\n", - " trace_id, trace_name = gen_trace_id(), \"argument_chain\"\n", - " argument = argument_generator(query, additional_description, trace_id, trace_name=trace_name)\n", - " criticism = critic(argument, trace_id)\n", - " return refiner(query, additional_description, argument, criticism, trace_id)" + " trace_id, trace_name = gen_trace_id(), \"argument_chain\"\n", + " argument = argument_generator(query, additional_description, trace_id, trace_name=trace_name)\n", + " criticism = critic(argument, trace_id)\n", + " return refiner(query, additional_description, argument, criticism, trace_id)" ] }, { @@ -189,8 +188,8 @@ "outputs": [], "source": [ "result = argument_chain(\n", - " \"Whether moonshine is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why moonshine is good for you.\",\n", + " \"Whether moonshine is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why moonshine is good for you.\",\n", ")\n", "print(result)" ] @@ -223,10 +222,10 @@ "outputs": [], "source": [ "def argument_chain2(query: str, additional_description: str = \"\") -> Tuple[str, str]:\n", - " trace_id, trace_name = gen_trace_id(), \"argument_chain\"\n", - " argument = argument_generator(query, additional_description, trace_id, trace_name=trace_name)\n", - " criticism = critic(argument, trace_id)\n", - " return refiner(query, additional_description, argument, criticism, trace_id), trace_id" + " trace_id, trace_name = gen_trace_id(), \"argument_chain\"\n", + " argument = argument_generator(query, additional_description, trace_id, trace_name=trace_name)\n", + " criticism = critic(argument, trace_id)\n", + " return refiner(query, additional_description, argument, criticism, trace_id), trace_id" ] }, { @@ -240,8 +239,8 @@ "outputs": [], "source": [ "result, trace_id = argument_chain2(\n", - " \"Whether moonshine is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why moonshine is good for you.\",\n", + " \"Whether moonshine is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why moonshine is good for you.\",\n", ")\n", "print(result)" ] @@ -307,22 +306,21 @@ "\n", "\n", "# let's return the full CompletionResponse to see what other information is returned\n", - "def refiner2(query: str, additional_description: str, current_arg: str, criticism: str, trace_id: Optional[str] = None,\n", - " **kwargs) -> CompletionResponse:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p--G2s9okMTvBEhXXXYqLY2\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " \"current_arg\": current_arg,\n", - " \"criticism\": criticism,\n", - " },\n", - " trace_id=trace_id,\n", - " **kwargs,\n", - " )\n", - " )" + "def refiner2(query: str, additional_description: str, current_arg: str, criticism: str, trace_id: Optional[str] = None, **kwargs) -> CompletionResponse:\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p--G2s9okMTvBEhXXXYqLY2\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " \"current_arg\": current_arg,\n", + " \"criticism\": criticism,\n", + " },\n", + " trace_id=trace_id,\n", + " **kwargs,\n", + " )\n", + " )" ], "metadata": { "id": "cXUHZpZbegIn", @@ -350,13 +348,12 @@ "outputs": [], "source": [ "def argument_chain_3(query: str, additional_description: str = \"\") -> CompletionResponse:\n", - " trace_id, parent_trace_name = gen_trace_id(), \"argument_chain\"\n", - " tags = [\"tutorial\"]\n", - " metadata = {\"githash\": \"e38f04c83\"}\n", - " argument = argument_generator(query, additional_description, trace_id, trace_name=parent_trace_name, tags=tags,\n", - " metadata=metadata)\n", - " criticism = critic(argument, trace_id)\n", - " return refiner2(query, additional_description, argument, criticism, trace_id)" + " trace_id, parent_trace_name = gen_trace_id(), \"argument_chain\"\n", + " tags = [\"tutorial\"]\n", + " metadata = {\"githash\": \"e38f04c83\"}\n", + " argument = argument_generator(query, additional_description, trace_id, trace_name=parent_trace_name, tags=tags, metadata=metadata)\n", + " criticism = critic(argument, trace_id)\n", + " return refiner2(query, additional_description, argument, criticism, trace_id)" ] }, { @@ -365,16 +362,16 @@ "import json, attrs\n", "\n", "result = argument_chain_3(\n", - " \"Whether moonshine is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why sunshine is good for you.\",\n", + " \"Whether moonshine is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why sunshine is good for you.\",\n", ")\n", "\n", "p.record_feedback(\n", - " FeedbackRequest(\n", - " trace_id=result.trace_id,\n", - " score=0.5,\n", - " target=\"Moonshine is nice. Full stop.\",\n", - " )\n", + " FeedbackRequest(\n", + " trace_id=result.trace_id,\n", + " score=0.5,\n", + " target=\"Moonshine is nice. Full stop.\",\n", + " )\n", ")\n", "print(json.dumps(attrs.asdict(result), indent=4))" ], From 389ebcf4542915121f270b471093f54b3d4f5b55 Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Thu, 24 Aug 2023 14:14:51 -0700 Subject: [PATCH 09/15] cleanup --- parea/example.py | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 parea/example.py diff --git a/parea/example.py b/parea/example.py new file mode 100644 index 00000000..37c1ed1f --- /dev/null +++ b/parea/example.py @@ -0,0 +1,2 @@ +def hello(name: str) -> str: + return f"Hello {name}!" From 962ed1b99a6006edaa1f73ecb90bb2714592f188 Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Thu, 24 Aug 2023 22:28:30 -0700 Subject: [PATCH 10/15] wip capture error --- parea/api_client.py | 7 +- parea/cookbook/tracing_with_parea_sdk.py | 235 ++++++++++++++++------- parea/utils/trace_utils.py | 22 ++- 3 files changed, 189 insertions(+), 75 deletions(-) diff --git a/parea/api_client.py b/parea/api_client.py index 1546a5e2..538b5b83 100644 --- a/parea/api_client.py +++ b/parea/api_client.py @@ -1,11 +1,16 @@ from typing import Any, Optional +import os + import httpx +from dotenv import load_dotenv + +load_dotenv() class HTTPClient: _instance = None - base_url = "https://optimus-prompt-backend.vercel.app/api/parea/v1" + base_url = os.getenv("DEV_HOST") # "https://optimus-prompt-backend.vercel.app/api/parea/v1" api_key = None def __new__(cls, *args, **kwargs): diff --git a/parea/cookbook/tracing_with_parea_sdk.py b/parea/cookbook/tracing_with_parea_sdk.py index 66a7779d..565e9c74 100644 --- a/parea/cookbook/tracing_with_parea_sdk.py +++ b/parea/cookbook/tracing_with_parea_sdk.py @@ -1,62 +1,87 @@ +from typing import Dict, List + import os +import time from datetime import datetime from dotenv import load_dotenv from parea import Parea -from parea.schemas.models import Completion, CompletionResponse, FeedbackRequest +from parea.schemas.models import Completion, CompletionResponse, FeedbackRequest, LLMInputs, Message, ModelParams from parea.utils.trace_utils import get_current_trace_id, trace load_dotenv() -p = Parea(api_key=os.getenv("PAREA_API_KEY")) +p = Parea(api_key=os.getenv("DEV_API_KEY")) -# We pass the deployment_id and the required inputs to the completion function along with the trace_id @trace -def argument_generator(query: str, additional_description: str = "", **kwargs) -> str: +def call_openai( + data: list[dict], + model: str = "gpt-3.5-turbo", + temperature: float = 0.0, + metadata: dict = None, +) -> CompletionResponse: return p.completion( - Completion( - deployment_id="p-RG8d9sssc_0cctwfpb_n6", - llm_inputs={ - "additional_description": additional_description, - "date": f"{datetime.now()}", - "query": query, - }, - **kwargs, + data=Completion( + llm_configuration=LLMInputs( + model=model, + provider="openai", + model_params=ModelParams(temp=temperature), + messages=[Message(**d) for d in data], + ), + metadata=metadata, ) + ) + + +@trace +def argument_generator(query: str, additional_description: str = "") -> str: + return call_openai( + [ + { + "role": "system", + "content": f"You are a debater making an argument on a topic." f"{additional_description}" f" The current time is {datetime.now()}", + }, + {"role": "user", "content": f"The discussion topic is {query}"}, + ] ).content @trace -def critic(argument: str, **kwargs) -> str: - return p.completion( - Completion( - deployment_id="p-fXgZytVVVJjXD_71TDR4s", - llm_inputs={"argument": argument}, - **kwargs, - ) +def critic(argument: str) -> str: + return call_openai( + [ + { + "role": "system", + "content": f"You are a critic." + "\nWhat unresolved questions or criticism do you have after reading the following argument?" + "Provide a concise summary of your feedback.", + }, + {"role": "system", "content": argument}, + ] ).content @trace -def refiner(query: str, additional_description: str, current_arg: str, criticism: str, **kwargs) -> str: - return p.completion( - Completion( - deployment_id="p--G2s9okMTWWWh3d8YqLY2", - llm_inputs={ - "additional_description": additional_description, - "date": f"{datetime.now()}", - "query": query, - "current_arg": current_arg, - "criticism": criticism, +def refiner(query: str, additional_description: str, current_arg: str, criticism: str) -> str: + return call_openai( + [ + { + "role": "system", + "content": f"You are a debater making an argument on a topic." f"{additional_description}" f" The current time is {datetime.now()}", }, - **kwargs, - ) + {"role": "user", "content": f"The discussion topic is {query}"}, + {"role": "assistant", "content": current_arg}, + {"role": "user", "content": criticism}, + { + "role": "system", + "content": "Please generate a new argument that incorporates the feedback from the user.", + }, + ] ).content -# This is the parent function which orchestrates the chaining. We'll define our trace_id and trace_name here @trace def argument_chain(query: str, additional_description: str = "") -> str: argument = argument_generator(query, additional_description) @@ -72,21 +97,22 @@ def argument_chain2(query: str, additional_description: str = "") -> tuple[str, return refiner(query, additional_description, argument, criticism), trace_id -# let's return the full CompletionResponse to see what other information is returned @trace -def refiner2(query: str, additional_description: str, current_arg: str, criticism: str, **kwargs) -> CompletionResponse: - return p.completion( - Completion( - deployment_id="p--G2s9okMTvBEh3d8YqLY2", - llm_inputs={ - "additional_description": additional_description, - "date": f"{datetime.now()}", - "query": query, - "current_arg": current_arg, - "criticism": criticism, +def refiner2(query: str, additional_description: str, current_arg: str, criticism: str) -> CompletionResponse: + return call_openai( + [ + { + "role": "system", + "content": f"You are a debater making an argument on a topic." f"{additional_description}" f" The current time is {datetime.now()}", }, - **kwargs, - ) + {"role": "user", "content": f"The discussion topic is {query}"}, + {"role": "assistant", "content": current_arg}, + {"role": "user", "content": criticism}, + { + "role": "system", + "content": "Please generate a new argument that incorporates the feedback from the user.", + }, + ] ) @@ -100,35 +126,108 @@ def argument_chain3(query: str, additional_description: str = "") -> CompletionR return refiner2(query, additional_description, argument, criticism) -if __name__ == "__main__": - result = argument_chain( - "Whether moonshine is good for you.", - additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", - ) - print(result) +LIMIT = 10 + +def dump_task(task): + d = "" # init + for tasklet in task: + d += f"\n{tasklet.get('task_name','')}" + d = d.strip() + return d + + +@trace +def expound_task(main_objective: str, current_task: str) -> list[dict[str, str]]: + prompt = [ + { + "role": "system", + "content": (f"You are an AI who performs one task based on the following objective: {main_objective}\n" f"Your task: {current_task}\nResponse:",), + }, + ] + response = call_openai(prompt).content + new_tasks = response.split("\n") if "\n" in response else [response] + return [{"task_name": task_name} for task_name in new_tasks] + + +@trace +def generate_tasks(main_objective: str, expounded_initial_task: list[dict[str, str]]) -> list[str]: + task_expansion = dump_task(expounded_initial_task) + prompt = [ + { + "role": "system", + "content": ( + f"You are an AI who creates tasks based on the following MAIN OBJECTIVE: {main_objective}\n" + f"Create tasks pertaining directly to your previous research here:\n" + f"{task_expansion}\nResponse:" + ), + }, + ] + response = call_openai(prompt).content + new_tasks = response.split("\n") if "\n" in response else [response] + task_list = [{"task_name": task_name} for task_name in new_tasks] + new_tasks_list: list[str] = [] + for task_item in task_list: + task_description = task_item.get("task_name") + if task_description: + task_parts = task_description.strip().split(".", 1) + if len(task_parts) == 2: + new_task = task_parts[1].strip() + new_tasks_list.append(new_task) + + return new_tasks_list + + +@trace +def run_agent(main_objective: str, initial_task: str = "") -> list[dict[str, str]]: + generated_tasks = [] + expounded_initial_task = expound_task(main_objective, initial_task) + new_tasks = generate_tasks(main_objective, expounded_initial_task) + task_counter = 0 + for task in new_tasks: + task_counter += 1 + q = expound_task(main_objective, task) + exp = dump_task(q) + generated_tasks.append({f"task_{task_counter}": exp}) + if task_counter >= LIMIT: + break + return generated_tasks + + +if __name__ == "__main__": + # result = argument_chain( + # "Whether moonshine is good for you.", + # additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", + # ) + # print(result) + # result2, trace_id = argument_chain2( - "Whether moonshine is good for you.", - additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", + "Whether chocolate is good for you.", + additional_description="Provide a concise, few sentence argument on why chocolate is good for you.", ) + time.sleep(3) p.record_feedback( FeedbackRequest( trace_id=trace_id, - score=0.7, # 0.0 (bad) to 1.0 (good) - target="Moonshine is wonderful. End of story.", + score=0.0, # 0.0 (bad) to 1.0 (good) + target="Moonshine is wonderful.", ) ) print(result2) - - result3 = argument_chain3( - "Whether moonshine is good for you.", - additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", - ) - p.record_feedback( - FeedbackRequest( - trace_id=result3.trace_id, - score=0.7, # 0.0 (bad) to 1.0 (good) - target="Moonshine is wonderful. End of story.", - ) - ) - print(result3) + # + # result3 = argument_chain3( + # "Whether moonshine is good for you.", + # additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", + # ) + # time.sleep(3) + # p.record_feedback( + # FeedbackRequest( + # trace_id=result3.inference_id, + # score=0.7, # 0.0 (bad) to 1.0 (good) + # target="Moonshine is wonderful. End of story.", + # ) + # ) + # print(result3.content) + # + # result4 = run_agent("Become a machine learning expert.", "Learn about tensors.") + # print(result4) diff --git a/parea/utils/trace_utils.py b/parea/utils/trace_utils.py index 26acfbc4..a655f6c0 100644 --- a/parea/utils/trace_utils.py +++ b/parea/utils/trace_utils.py @@ -97,32 +97,42 @@ def decorator(func): @wraps(func) async def async_wrapper(*args, **kwargs): trace_id = init_trace(func.__name__, args, kwargs, func) + result = None try: result = await func(*args, **kwargs) - end_time = time.time() - trace_data.get()[trace_id].end_timestamp = to_date_and_time_string(end_time) + # end_time = time.time() + # trace_data.get()[trace_id].end_timestamp = to_date_and_time_string(end_time) output = asdict(result) if isinstance(result, CompletionResponse) else result trace_data.get()[trace_id].output = json.dumps(output) except Exception as e: logger.exception(f"Error occurred in function {func.__name__}") - raise e + trace_data.get()[trace_id].error = str(e) + # trace_data.get()[trace_id].status = "error" + # raise e finally: + end_time = time.time() + trace_data.get()[trace_id].end_timestamp = to_date_and_time_string(end_time) cleanup_trace(trace_id) return result @wraps(func) def wrapper(*args, **kwargs): trace_id = init_trace(func.__name__, args, kwargs, func) + result = None try: result = func(*args, **kwargs) - end_time = time.time() - trace_data.get()[trace_id].end_timestamp = to_date_and_time_string(end_time) + # end_time = time.time() + # trace_data.get()[trace_id].end_timestamp = to_date_and_time_string(end_time) output = asdict(result) if isinstance(result, CompletionResponse) else result trace_data.get()[trace_id].output = json.dumps(output) except Exception as e: logger.exception(f"Error occurred in function {func.__name__}") - raise e + trace_data.get()[trace_id].error = str(e) + # trace_data.get()[trace_id].status = "error" + # raise e finally: + end_time = time.time() + trace_data.get()[trace_id].end_timestamp = to_date_and_time_string(end_time) cleanup_trace(trace_id) return result From f515d5d7b1b9b75783c94749929bb033456c5159 Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Fri, 25 Aug 2023 11:15:25 -0700 Subject: [PATCH 11/15] catch errors --- parea/cookbook/tracing_with_parea_sdk.py | 84 +++++++++++------------- parea/utils/trace_utils.py | 20 ++---- poetry.lock | 68 ++++++++++++++++++- pyproject.toml | 1 + requirements.txt | 7 +- 5 files changed, 118 insertions(+), 62 deletions(-) diff --git a/parea/cookbook/tracing_with_parea_sdk.py b/parea/cookbook/tracing_with_parea_sdk.py index 565e9c74..14bd5014 100644 --- a/parea/cookbook/tracing_with_parea_sdk.py +++ b/parea/cookbook/tracing_with_parea_sdk.py @@ -1,5 +1,3 @@ -from typing import Dict, List - import os import time from datetime import datetime @@ -15,12 +13,22 @@ p = Parea(api_key=os.getenv("DEV_API_KEY")) +LIMIT = 10 + + +def dump_task(task): + d = "" + for tasklet in task: + d += f"\n{tasklet.get('task_name','')}" + d = d.strip() + return d + + @trace def call_openai( data: list[dict], model: str = "gpt-3.5-turbo", temperature: float = 0.0, - metadata: dict = None, ) -> CompletionResponse: return p.completion( data=Completion( @@ -29,8 +37,7 @@ def call_openai( provider="openai", model_params=ModelParams(temp=temperature), messages=[Message(**d) for d in data], - ), - metadata=metadata, + ) ) ) @@ -69,7 +76,7 @@ def refiner(query: str, additional_description: str, current_arg: str, criticism [ { "role": "system", - "content": f"You are a debater making an argument on a topic." f"{additional_description}" f" The current time is {datetime.now()}", + "content": f"You are a debater making an argument on a topic. {additional_description}. " f"The current time is {datetime.now()}", }, {"role": "user", "content": f"The discussion topic is {query}"}, {"role": "assistant", "content": current_arg}, @@ -103,7 +110,7 @@ def refiner2(query: str, additional_description: str, current_arg: str, criticis [ { "role": "system", - "content": f"You are a debater making an argument on a topic." f"{additional_description}" f" The current time is {datetime.now()}", + "content": f"You are a debater making an argument on a topic. {additional_description}. The current time is {datetime.now()}", }, {"role": "user", "content": f"The discussion topic is {query}"}, {"role": "assistant", "content": current_arg}, @@ -126,23 +133,12 @@ def argument_chain3(query: str, additional_description: str = "") -> CompletionR return refiner2(query, additional_description, argument, criticism) -LIMIT = 10 - - -def dump_task(task): - d = "" # init - for tasklet in task: - d += f"\n{tasklet.get('task_name','')}" - d = d.strip() - return d - - @trace def expound_task(main_objective: str, current_task: str) -> list[dict[str, str]]: prompt = [ { "role": "system", - "content": (f"You are an AI who performs one task based on the following objective: {main_objective}\n" f"Your task: {current_task}\nResponse:",), + "content": f"You are an AI who performs one task based on the following objective: {main_objective}\n" f"Your task: {current_task}\nResponse:", }, ] response = call_openai(prompt).content @@ -195,15 +191,15 @@ def run_agent(main_objective: str, initial_task: str = "") -> list[dict[str, str if __name__ == "__main__": - # result = argument_chain( - # "Whether moonshine is good for you.", - # additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", - # ) - # print(result) - # + result = argument_chain( + "Whether coffee is good for you.", + additional_description="Provide a concise, few sentence argument on why coffee is good for you.", + ) + print(result) + result2, trace_id = argument_chain2( - "Whether chocolate is good for you.", - additional_description="Provide a concise, few sentence argument on why chocolate is good for you.", + "Whether wine is good for you.", + additional_description="Provide a concise, few sentence argument on why wine is good for you.", ) time.sleep(3) p.record_feedback( @@ -214,20 +210,20 @@ def run_agent(main_objective: str, initial_task: str = "") -> list[dict[str, str ) ) print(result2) - # - # result3 = argument_chain3( - # "Whether moonshine is good for you.", - # additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", - # ) - # time.sleep(3) - # p.record_feedback( - # FeedbackRequest( - # trace_id=result3.inference_id, - # score=0.7, # 0.0 (bad) to 1.0 (good) - # target="Moonshine is wonderful. End of story.", - # ) - # ) - # print(result3.content) - # - # result4 = run_agent("Become a machine learning expert.", "Learn about tensors.") - # print(result4) + + result3 = argument_chain3( + "Whether moonshine is good for you.", + additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", + ) + time.sleep(3) + p.record_feedback( + FeedbackRequest( + trace_id=result3.inference_id, + score=0.7, # 0.0 (bad) to 1.0 (good) + target="Moonshine is wonderful. End of story.", + ) + ) + print(result3.content) + + result4 = run_agent("Become a machine learning expert.", "Learn about tensors.") + print(result4) diff --git a/parea/utils/trace_utils.py b/parea/utils/trace_utils.py index a655f6c0..ec6dfb60 100644 --- a/parea/utils/trace_utils.py +++ b/parea/utils/trace_utils.py @@ -86,6 +86,8 @@ def init_trace(func_name, args, kwargs, func): return trace_id def cleanup_trace(trace_id): + end_time = time.time() + trace_data.get()[trace_id].end_timestamp = to_date_and_time_string(end_time) logging_thread = threading.Thread( target=parea_logger.record_log, kwargs={"data": trace_data.get()[trace_id]}, @@ -100,18 +102,13 @@ async def async_wrapper(*args, **kwargs): result = None try: result = await func(*args, **kwargs) - # end_time = time.time() - # trace_data.get()[trace_id].end_timestamp = to_date_and_time_string(end_time) output = asdict(result) if isinstance(result, CompletionResponse) else result trace_data.get()[trace_id].output = json.dumps(output) except Exception as e: - logger.exception(f"Error occurred in function {func.__name__}") + logger.exception(f"Error occurred in function {func.__name__}, {e}") trace_data.get()[trace_id].error = str(e) - # trace_data.get()[trace_id].status = "error" - # raise e + trace_data.get()[trace_id].status = "error" finally: - end_time = time.time() - trace_data.get()[trace_id].end_timestamp = to_date_and_time_string(end_time) cleanup_trace(trace_id) return result @@ -121,18 +118,13 @@ def wrapper(*args, **kwargs): result = None try: result = func(*args, **kwargs) - # end_time = time.time() - # trace_data.get()[trace_id].end_timestamp = to_date_and_time_string(end_time) output = asdict(result) if isinstance(result, CompletionResponse) else result trace_data.get()[trace_id].output = json.dumps(output) except Exception as e: - logger.exception(f"Error occurred in function {func.__name__}") + logger.exception(f"Error occurred in function {func.__name__}, {e}") trace_data.get()[trace_id].error = str(e) - # trace_data.get()[trace_id].status = "error" - # raise e + trace_data.get()[trace_id].status = "error" finally: - end_time = time.time() - trace_data.get()[trace_id].end_timestamp = to_date_and_time_string(end_time) cleanup_trace(trace_id) return result diff --git a/poetry.lock b/poetry.lock index 9ac3e5b9..e805402a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -583,6 +583,19 @@ lint = ["black (>=22.6.0)", "mdformat (>0.7)", "mdformat-gfm (>=0.3.5)", "ruff ( test = ["pytest"] typing = ["mypy (>=0.990)"] +[[package]] +name = "contextvars" +version = "2.4" +description = "PEP 567 Backport" +optional = false +python-versions = "*" +files = [ + {file = "contextvars-2.4.tar.gz", hash = "sha256:f38c908aaa59c14335eeea12abea5f443646216c4e29380d7bf34d2018e2c39e"}, +] + +[package.dependencies] +immutables = ">=0.9" + [[package]] name = "coverage" version = "7.3.0" @@ -1074,6 +1087,59 @@ files = [ {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, ] +[[package]] +name = "immutables" +version = "0.20" +description = "Immutable Collections" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "immutables-0.20-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dea0ae4d7f31b145c18c16badeebc2f039d09411be4a8febb86e1244cf7f1ce0"}, + {file = "immutables-0.20-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2dd0dcef2f8d4523d34dbe1d2b7804b3d2a51fddbd104aad13f506a838a2ea15"}, + {file = "immutables-0.20-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:393dde58ffd6b4c089ffdf4cef5fe73dad37ce4681acffade5f5d5935ec23c93"}, + {file = "immutables-0.20-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1214b5a175df783662b7de94b4a82db55cc0ee206dd072fa9e279fb8895d8df"}, + {file = "immutables-0.20-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2761e3dc2a6406943ce77b3505e9b3c1187846de65d7247548dc7edaa202fcba"}, + {file = "immutables-0.20-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2bcea81e7516bd823b4ed16f4f794531097888675be13e833b1cc946370d5237"}, + {file = "immutables-0.20-cp310-cp310-win32.whl", hash = "sha256:d828e7580f1fa203ddeab0b5e91f44bf95706e7f283ca9fbbcf0ae08f63d3084"}, + {file = "immutables-0.20-cp310-cp310-win_amd64.whl", hash = "sha256:380e2957ba3d63422b2f3fbbff0547c7bbe6479d611d3635c6411005a4264525"}, + {file = "immutables-0.20-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:532be32c7a25dae6cade28825c76d3004cf4d166a0bfacf04bda16056d59ba26"}, + {file = "immutables-0.20-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5302ce9c7827f8300f3dc34a695abb71e4a32bab09e65e5ad6e454785383347f"}, + {file = "immutables-0.20-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b51aec54b571ae466113509d4dc79a2808dc2ae9263b71fd6b37778cb49eb292"}, + {file = "immutables-0.20-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47f56aea56e597ecf6631f24a4e26007b6a5f4fe30278b96eb90bc1f60506164"}, + {file = "immutables-0.20-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:085ac48ee3eef7baf070f181cae574489bbf65930a83ec5bbd65c9940d625db3"}, + {file = "immutables-0.20-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f063f53b5c0e8f541ae381f1d828f3d05bbed766a2d6c817f9218b8b37a4cb66"}, + {file = "immutables-0.20-cp311-cp311-win32.whl", hash = "sha256:b0436cc831b47e26bef637bcf143cf0273e49946cfb7c28c44486d70513a3080"}, + {file = "immutables-0.20-cp311-cp311-win_amd64.whl", hash = "sha256:5bb32aee1ea16fbb90f58f8bd96016bca87aba0a8e574e5fa218d0d83b142851"}, + {file = "immutables-0.20-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4ba726b7a3a696b9d4b122fa2c956bc68e866f3df1b92765060c88c64410ff82"}, + {file = "immutables-0.20-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5a88adf1dcc9d8ab07dba5e74deefcd5b5e38bc677815cbf9365dc43b69f1f08"}, + {file = "immutables-0.20-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1009a4e00e2e69a9b40c2f1272795f5a06ad72c9bf4638594d518e9cbd7a721a"}, + {file = "immutables-0.20-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96899994842c37cf4b9d6d2bedf685aae7810bd73f1538f8cba5426e2d65cb85"}, + {file = "immutables-0.20-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a606410b2ccb6ae339c3f26cccc9a92bcb16dc06f935d51edfd8ca68cf687e50"}, + {file = "immutables-0.20-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e8e82754f72823085643a2c0e6a4c489b806613e94af205825fa81df2ba147a0"}, + {file = "immutables-0.20-cp312-cp312-win32.whl", hash = "sha256:525fb361bd7edc8a891633928d549713af8090c79c25af5cc06eb90b48cb3c64"}, + {file = "immutables-0.20-cp312-cp312-win_amd64.whl", hash = "sha256:a82afc3945e9ceb9bcd416dc4ed9b72f92760c42787e26de50610a8b81d48120"}, + {file = "immutables-0.20-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f17f25f21e82a1c349a61191cfb13e442a348b880b74cb01b00e0d1e848b63f4"}, + {file = "immutables-0.20-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:65954eb861c61af48debb1507518d45ae7d594b4fba7282785a70b48c5f51f9b"}, + {file = "immutables-0.20-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62f8a7a22939278127b7a206d05679b268b9cf665437125625348e902617cbad"}, + {file = "immutables-0.20-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac86f4372f4cfaa00206c12472fd3a78753092279e0552b7e1880944d71b04fe"}, + {file = "immutables-0.20-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e771198edc11a9e02ffa693911b3918c6cde0b64ad2e6672b076dbe005557ad8"}, + {file = "immutables-0.20-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fc739fc07cff5df2e4f31addbd48660b5ac0da56e9f719f8bb45da8ddd632c63"}, + {file = "immutables-0.20-cp38-cp38-win32.whl", hash = "sha256:c086ccb44d9d3824b9bf816365d10b1b82837efc7119f8bab56bd7a27ed805a9"}, + {file = "immutables-0.20-cp38-cp38-win_amd64.whl", hash = "sha256:9cd2ee9c10bf00be3c94eb51854bc0b761326bd0a7ea0dad4272a3f182269ae6"}, + {file = "immutables-0.20-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d4f78cb748261f852953620ed991de74972446fd484ec69377a41e2f1a1beb75"}, + {file = "immutables-0.20-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d6449186ea91b7c17ec8e7bd9bf059858298b1db5c053f5d27de8eba077578ce"}, + {file = "immutables-0.20-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85dd9765b068f7beb297553fddfcf7f904bd58a184c520830a106a58f0c9bfb4"}, + {file = "immutables-0.20-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f349a7e0327b92dcefb863e49ace086f2f26e6689a4e022c98720c6e9696e763"}, + {file = "immutables-0.20-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e3a5462f6d3549bbf7d02ce929fb0cb6df9539445f0589105de4e8b99b906e69"}, + {file = "immutables-0.20-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cc51a01a64a6d2cd7db210a49ad010c2ac2e9e026745f23fd31e0784096dcfff"}, + {file = "immutables-0.20-cp39-cp39-win32.whl", hash = "sha256:83794712f0507416f2818edc63f84305358b8656a93e5b9e2ab056d9803c7507"}, + {file = "immutables-0.20-cp39-cp39-win_amd64.whl", hash = "sha256:2837b1078abc66d9f009bee9085cf62515d5516af9a5c9ea2751847e16efd236"}, + {file = "immutables-0.20.tar.gz", hash = "sha256:1d2f83e6a6a8455466cd97b9a90e2b4f7864648616dfa6b19d18f49badac3876"}, +] + +[package.extras] +test = ["flake8 (>=5.0,<6.0)", "mypy (>=1.4,<2.0)", "pycodestyle (>=2.9,<3.0)", "pytest (>=7.4,<8.0)"] + [[package]] name = "importlib-metadata" version = "6.8.0" @@ -3802,4 +3868,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "d43b7ecf531579cf4bb4802196642b89655fcada52235c4c318147d0c6b03ec7" +content-hash = "e050362ab2ff998091752d1595d22f08609e2d5e8bd285b75f9d62ffe71f531c" diff --git a/pyproject.toml b/pyproject.toml index 6ce621b8..233ed200 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,7 @@ python-dotenv = "^1.0.0" poetry-plugin-dotenv = "^0.5.1" pyupgrade = "^3.9.0" jupyter = "^1.0.0" +contextvars = "^2.4" [tool.poetry.dev-dependencies] bandit = "^1.7.1" diff --git a/requirements.txt b/requirements.txt index bcad6b87..b93ae436 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ -attrs -httpx -python-dotenv +attrs~=23.1.0 +httpx~=0.24.1 +python-dotenv~=1.0.0 +contextvars~=2.4.0 From e27948137df55363e1d2c9d78dfb38ccda509971 Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Fri, 25 Aug 2023 11:17:31 -0700 Subject: [PATCH 12/15] catch errors --- parea/api_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parea/api_client.py b/parea/api_client.py index 538b5b83..4909662b 100644 --- a/parea/api_client.py +++ b/parea/api_client.py @@ -10,7 +10,7 @@ class HTTPClient: _instance = None - base_url = os.getenv("DEV_HOST") # "https://optimus-prompt-backend.vercel.app/api/parea/v1" + base_url = os.getenv("DEV_HOST") or "https://optimus-prompt-backend.vercel.app/api/parea/v1" api_key = None def __new__(cls, *args, **kwargs): From a04bc9cb813d628f972e998b2ac3040f0e78c7e3 Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Fri, 25 Aug 2023 19:18:27 -0700 Subject: [PATCH 13/15] sort and cache --- parea/cookbook/tracing_with_parea_sdk.py | 115 +++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/parea/cookbook/tracing_with_parea_sdk.py b/parea/cookbook/tracing_with_parea_sdk.py index 14bd5014..42d5df45 100644 --- a/parea/cookbook/tracing_with_parea_sdk.py +++ b/parea/cookbook/tracing_with_parea_sdk.py @@ -89,6 +89,46 @@ def refiner(query: str, additional_description: str, current_arg: str, criticism ).content +@trace +def deployed_argument_generator(query: str, additional_description: str = "") -> str: + return p.completion( + Completion( + deployment_id="p-Ar-Oi14-nBxHUiradyql9", + llm_inputs={ + "additional_description": additional_description, + "date": f"{datetime.now()}", + "query": query, + }, + ) + ).content + + +@trace +def deployed_critic(argument: str) -> str: + return p.completion( + Completion( + deployment_id="p-W2yPy93tAczYrxkipjli6", + llm_inputs={"argument": argument}, + ) + ).content + + +@trace +def deployed_refiner(query: str, additional_description: str, current_arg: str, criticism: str) -> str: + return p.completion( + Completion( + deployment_id="p-8Er1Xo0GDGF2xtpmMOpbn", + llm_inputs={ + "additional_description": additional_description, + "date": f"{datetime.now()}", + "query": query, + "current_arg": current_arg, + "criticism": criticism, + }, + ) + ).content + + @trace def argument_chain(query: str, additional_description: str = "") -> str: argument = argument_generator(query, additional_description) @@ -123,6 +163,22 @@ def refiner2(query: str, additional_description: str, current_arg: str, criticis ) +@trace +def deployed_refiner2(query: str, additional_description: str, current_arg: str, criticism: str) -> CompletionResponse: + return p.completion( + Completion( + deployment_id="p-8Er1Xo0GDGF2xtpmMOpbn", + llm_inputs={ + "additional_description": additional_description, + "date": f"{datetime.now()}", + "query": query, + "current_arg": current_arg, + "criticism": criticism, + }, + ) + ) + + @trace( tags=["cookbook-example", "feedback_tracked"], metadata={"source": "python-sdk"}, @@ -133,6 +189,31 @@ def argument_chain3(query: str, additional_description: str = "") -> CompletionR return refiner2(query, additional_description, argument, criticism) +@trace +def deployed_argument_chain(query: str, additional_description: str = "") -> str: + argument = deployed_argument_generator(query, additional_description) + criticism = deployed_critic(argument) + return deployed_refiner(query, additional_description, argument, criticism) + + +@trace +def deployed_argument_chain2(query: str, additional_description: str = "") -> tuple[str, str]: + trace_id = get_current_trace_id() + argument = deployed_argument_generator(query, additional_description) + criticism = deployed_critic(argument) + return deployed_refiner(query, additional_description, argument, criticism), trace_id + + +@trace( + tags=["cookbook-example-deployed", "feedback_tracked-deployed"], + metadata={"source": "python-sdk", "deployed": True}, +) +def deployed_argument_chain3(query: str, additional_description: str = "") -> CompletionResponse: + argument = deployed_argument_generator(query, additional_description) + criticism = deployed_critic(argument) + return deployed_refiner2(query, additional_description, argument, criticism) + + @trace def expound_task(main_objective: str, current_task: str) -> list[dict[str, str]]: prompt = [ @@ -227,3 +308,37 @@ def run_agent(main_objective: str, initial_task: str = "") -> list[dict[str, str result4 = run_agent("Become a machine learning expert.", "Learn about tensors.") print(result4) + + result5 = deployed_argument_chain( + "Whether coffee is good for you.", + additional_description="Provide a concise, few sentence argument on why coffee is good for you.", + ) + print(result5) + + result6, trace_id2 = deployed_argument_chain2( + "Whether wine is good for you.", + additional_description="Provide a concise, few sentence argument on why wine is good for you.", + ) + time.sleep(3) + p.record_feedback( + FeedbackRequest( + trace_id=trace_id2, + score=0.0, # 0.0 (bad) to 1.0 (good) + target="Moonshine is wonderful.", + ) + ) + print(result6) + + result7 = deployed_argument_chain3( + "Whether moonshine is good for you.", + additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", + ) + time.sleep(3) + p.record_feedback( + FeedbackRequest( + trace_id=result7.inference_id, + score=0.7, # 0.0 (bad) to 1.0 (good) + target="Moonshine is wonderful. End of story.", + ) + ) + print(result7.error or result7.content) From 40e04b87993625ca09e72a022989a76132c13403 Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Sat, 26 Aug 2023 16:37:24 -0700 Subject: [PATCH 14/15] ready --- parea/cookbook/tracing_with_parea_sdk.py | 145 ++++++++++++----------- 1 file changed, 78 insertions(+), 67 deletions(-) diff --git a/parea/cookbook/tracing_with_parea_sdk.py b/parea/cookbook/tracing_with_parea_sdk.py index 42d5df45..d5312d73 100644 --- a/parea/cookbook/tracing_with_parea_sdk.py +++ b/parea/cookbook/tracing_with_parea_sdk.py @@ -1,3 +1,5 @@ +from typing import Tuple + import os import time from datetime import datetime @@ -256,89 +258,98 @@ def generate_tasks(main_objective: str, expounded_initial_task: list[dict[str, s @trace -def run_agent(main_objective: str, initial_task: str = "") -> list[dict[str, str]]: +def run_agent(main_objective: str, initial_task: str = "") -> tuple[list[dict[str, str]], str]: + trace_id = get_current_trace_id() generated_tasks = [] expounded_initial_task = expound_task(main_objective, initial_task) new_tasks = generate_tasks(main_objective, expounded_initial_task) task_counter = 0 - for task in new_tasks: + for task in new_tasks or []: task_counter += 1 q = expound_task(main_objective, task) exp = dump_task(q) generated_tasks.append({f"task_{task_counter}": exp}) if task_counter >= LIMIT: break - return generated_tasks + return generated_tasks, trace_id if __name__ == "__main__": - result = argument_chain( - "Whether coffee is good for you.", - additional_description="Provide a concise, few sentence argument on why coffee is good for you.", - ) - print(result) - - result2, trace_id = argument_chain2( - "Whether wine is good for you.", - additional_description="Provide a concise, few sentence argument on why wine is good for you.", - ) - time.sleep(3) - p.record_feedback( - FeedbackRequest( - trace_id=trace_id, - score=0.0, # 0.0 (bad) to 1.0 (good) - target="Moonshine is wonderful.", - ) - ) - print(result2) - - result3 = argument_chain3( - "Whether moonshine is good for you.", - additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", - ) - time.sleep(3) - p.record_feedback( - FeedbackRequest( - trace_id=result3.inference_id, - score=0.7, # 0.0 (bad) to 1.0 (good) - target="Moonshine is wonderful. End of story.", - ) - ) - print(result3.content) - - result4 = run_agent("Become a machine learning expert.", "Learn about tensors.") - print(result4) - - result5 = deployed_argument_chain( - "Whether coffee is good for you.", - additional_description="Provide a concise, few sentence argument on why coffee is good for you.", - ) - print(result5) - - result6, trace_id2 = deployed_argument_chain2( - "Whether wine is good for you.", - additional_description="Provide a concise, few sentence argument on why wine is good for you.", - ) + # result = argument_chain( + # "Whether coffee is good for you.", + # additional_description="Provide a concise, few sentence argument on why coffee is good for you.", + # ) + # print(result) + # + # result2, trace_id = argument_chain2( + # "Whether wine is good for you.", + # additional_description="Provide a concise, few sentence argument on why wine is good for you.", + # ) + # time.sleep(3) + # p.record_feedback( + # FeedbackRequest( + # trace_id=trace_id, + # score=0.0, # 0.0 (bad) to 1.0 (good) + # target="Moonshine is wonderful.", + # ) + # ) + # print(result2) + # + # result3 = argument_chain3( + # "Whether moonshine is good for you.", + # additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", + # ) + # time.sleep(3) + # p.record_feedback( + # FeedbackRequest( + # trace_id=result3.inference_id, + # score=0.7, # 0.0 (bad) to 1.0 (good) + # target="Moonshine is wonderful. End of story.", + # ) + # ) + # print(result3.content) + + result4, trace_id2 = run_agent("Become a machine learning expert.", "Learn about tensors.") time.sleep(3) p.record_feedback( FeedbackRequest( trace_id=trace_id2, - score=0.0, # 0.0 (bad) to 1.0 (good) - target="Moonshine is wonderful.", + score=0.642, # 0.0 (bad) to 1.0 (good) + target="Do both!.", ) ) - print(result6) - - result7 = deployed_argument_chain3( - "Whether moonshine is good for you.", - additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", - ) - time.sleep(3) - p.record_feedback( - FeedbackRequest( - trace_id=result7.inference_id, - score=0.7, # 0.0 (bad) to 1.0 (good) - target="Moonshine is wonderful. End of story.", - ) - ) - print(result7.error or result7.content) + print(result4) + # + # result5 = deployed_argument_chain( + # "Whether coffee is good for you.", + # additional_description="Provide a concise, few sentence argument on why coffee is good for you.", + # ) + # print(result5) + # + # result6, trace_id3 = deployed_argument_chain2( + # "Whether wine is good for you.", + # additional_description="Provide a concise, few sentence argument on why wine is good for you.", + # ) + # time.sleep(3) + # p.record_feedback( + # FeedbackRequest( + # trace_id=trace_id3, + # score=0.0, # 0.0 (bad) to 1.0 (good) + # target="Moonshine is wonderful.", + # ) + # ) + # print(result6) + # + # result7 = deployed_argument_chain3( + # "Whether moonshine is good for you.", + # additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", + # ) + # time.sleep(3) + # p.record_feedback( + # FeedbackRequest( + # trace_id=result7.inference_id, + # score=0.7, # 0.0 (bad) to 1.0 (good) + # target="Moonshine is wonderful. End of story.", + # ) + # ) + # print(result7.error or result7.content) From da4767b44d658aca8e53e9a6b83790312433b1bd Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Sat, 26 Aug 2023 17:08:06 -0700 Subject: [PATCH 15/15] ready --- parea/cookbook/tracing_with_parea_sdk.py | 136 +++++++++++------------ pyproject.toml | 2 +- 2 files changed, 68 insertions(+), 70 deletions(-) diff --git a/parea/cookbook/tracing_with_parea_sdk.py b/parea/cookbook/tracing_with_parea_sdk.py index d5312d73..a3e71b16 100644 --- a/parea/cookbook/tracing_with_parea_sdk.py +++ b/parea/cookbook/tracing_with_parea_sdk.py @@ -1,5 +1,3 @@ -from typing import Tuple - import os import time from datetime import datetime @@ -275,39 +273,39 @@ def run_agent(main_objective: str, initial_task: str = "") -> tuple[list[dict[st if __name__ == "__main__": - # result = argument_chain( - # "Whether coffee is good for you.", - # additional_description="Provide a concise, few sentence argument on why coffee is good for you.", - # ) - # print(result) - # - # result2, trace_id = argument_chain2( - # "Whether wine is good for you.", - # additional_description="Provide a concise, few sentence argument on why wine is good for you.", - # ) - # time.sleep(3) - # p.record_feedback( - # FeedbackRequest( - # trace_id=trace_id, - # score=0.0, # 0.0 (bad) to 1.0 (good) - # target="Moonshine is wonderful.", - # ) - # ) - # print(result2) - # - # result3 = argument_chain3( - # "Whether moonshine is good for you.", - # additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", - # ) - # time.sleep(3) - # p.record_feedback( - # FeedbackRequest( - # trace_id=result3.inference_id, - # score=0.7, # 0.0 (bad) to 1.0 (good) - # target="Moonshine is wonderful. End of story.", - # ) - # ) - # print(result3.content) + result = argument_chain( + "Whether coffee is good for you.", + additional_description="Provide a concise, few sentence argument on why coffee is good for you.", + ) + print(result) + + result2, trace_id = argument_chain2( + "Whether wine is good for you.", + additional_description="Provide a concise, few sentence argument on why wine is good for you.", + ) + time.sleep(3) + p.record_feedback( + FeedbackRequest( + trace_id=trace_id, + score=0.0, # 0.0 (bad) to 1.0 (good) + target="Moonshine is wonderful.", + ) + ) + print(result2) + + result3 = argument_chain3( + "Whether moonshine is good for you.", + additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", + ) + time.sleep(3) + p.record_feedback( + FeedbackRequest( + trace_id=result3.inference_id, + score=0.7, # 0.0 (bad) to 1.0 (good) + target="Moonshine is wonderful. End of story.", + ) + ) + print(result3.content) result4, trace_id2 = run_agent("Become a machine learning expert.", "Learn about tensors.") time.sleep(3) @@ -319,37 +317,37 @@ def run_agent(main_objective: str, initial_task: str = "") -> tuple[list[dict[st ) ) print(result4) - # - # result5 = deployed_argument_chain( - # "Whether coffee is good for you.", - # additional_description="Provide a concise, few sentence argument on why coffee is good for you.", - # ) - # print(result5) - # - # result6, trace_id3 = deployed_argument_chain2( - # "Whether wine is good for you.", - # additional_description="Provide a concise, few sentence argument on why wine is good for you.", - # ) - # time.sleep(3) - # p.record_feedback( - # FeedbackRequest( - # trace_id=trace_id3, - # score=0.0, # 0.0 (bad) to 1.0 (good) - # target="Moonshine is wonderful.", - # ) - # ) - # print(result6) - # - # result7 = deployed_argument_chain3( - # "Whether moonshine is good for you.", - # additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", - # ) - # time.sleep(3) - # p.record_feedback( - # FeedbackRequest( - # trace_id=result7.inference_id, - # score=0.7, # 0.0 (bad) to 1.0 (good) - # target="Moonshine is wonderful. End of story.", - # ) - # ) - # print(result7.error or result7.content) + + result5 = deployed_argument_chain( + "Whether coffee is good for you.", + additional_description="Provide a concise, few sentence argument on why coffee is good for you.", + ) + print(result5) + + result6, trace_id3 = deployed_argument_chain2( + "Whether wine is good for you.", + additional_description="Provide a concise, few sentence argument on why wine is good for you.", + ) + time.sleep(3) + p.record_feedback( + FeedbackRequest( + trace_id=trace_id3, + score=0.0, # 0.0 (bad) to 1.0 (good) + target="Moonshine is wonderful.", + ) + ) + print(result6) + + result7 = deployed_argument_chain3( + "Whether moonshine is good for you.", + additional_description="Provide a concise, few sentence argument on why moonshine is good for you.", + ) + time.sleep(3) + p.record_feedback( + FeedbackRequest( + trace_id=result7.inference_id, + score=0.7, # 0.0 (bad) to 1.0 (good) + target="Moonshine is wonderful. End of story.", + ) + ) + print(result7.error or result7.content) diff --git a/pyproject.toml b/pyproject.toml index 233ed200..ea63679a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "parea-ai" packages = [{ include = "parea" }] -version = "0.1.4" +version = "0.2.0" description = "Parea python sdk" readme = "README.md" authors = ["joel-parea-ai "]