diff --git a/agenta-backend/agenta_backend/migrations/v0_12_0_to_v0_15_0/20240509122536_evaluation_scenario_correct_answer.py b/agenta-backend/agenta_backend/migrations/v0_12_0_to_v0_15_0/20240509122536_evaluation_scenario_correct_answer.py new file mode 100644 index 0000000000..fba396e27b --- /dev/null +++ b/agenta-backend/agenta_backend/migrations/v0_12_0_to_v0_15_0/20240509122536_evaluation_scenario_correct_answer.py @@ -0,0 +1,345 @@ +from datetime import datetime, timezone +from typing import Any, Dict, List, Optional + +from pydantic import BaseModel, Field +from beanie import Document, Link, PydanticObjectId, iterative_migration + + +class UserDB(Document): + uid: str = Field(default="0", unique=True, index=True) + username: str = Field(default="agenta") + email: str = Field(default="demo@agenta.ai", unique=True) + created_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + updated_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + + class Settings: + name = "users" + + +class ImageDB(Document): + """Defines the info needed to get an image and connect it to the app variant""" + + type: Optional[str] = Field(default="image") + template_uri: Optional[str] + docker_id: Optional[str] = Field(index=True) + tags: Optional[str] + deletable: bool = Field(default=True) + user: Link[UserDB] + created_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + updated_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + + class Settings: + name = "docker_images" + + +class AppDB(Document): + app_name: str + user: Link[UserDB] + created_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + updated_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + + class Settings: + name = "app_db" + + +class DeploymentDB(Document): + app: Link[AppDB] + user: Link[UserDB] + container_name: Optional[str] + container_id: Optional[str] + uri: Optional[str] + status: str + created_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + updated_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + + class Settings: + name = "deployments" + + +class VariantBaseDB(Document): + app: Link[AppDB] + user: Link[UserDB] + base_name: str + image: Link[ImageDB] + deployment: Optional[PydanticObjectId] # Link to deployment + created_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + updated_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + + class Settings: + name = "bases" + + +class ConfigDB(BaseModel): + config_name: str + parameters: Dict[str, Any] = Field(default_factory=dict) + + +class AppVariantDB(Document): + app: Link[AppDB] + variant_name: str + revision: int + image: Link[ImageDB] + user: Link[UserDB] + modified_by: Link[UserDB] + parameters: Dict[str, Any] = Field(default=dict) # TODO: deprecated. remove + previous_variant_name: Optional[str] # TODO: deprecated. remove + base_name: Optional[str] + base: Link[VariantBaseDB] + config_name: Optional[str] + config: ConfigDB + created_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + updated_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + + is_deleted: bool = Field( # TODO: deprecated. remove + default=False + ) # soft deletion for using the template variants + + class Settings: + name = "app_variants" + + +class AppVariantRevisionsDB(Document): + variant: Link[AppVariantDB] + revision: int + modified_by: Link[UserDB] + base: Link[VariantBaseDB] + config: ConfigDB + created_at: datetime + updated_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + + class Settings: + name = "app_variant_revisions" + + +class AppEnvironmentDB(Document): + app: Link[AppDB] + name: str + user: Link[UserDB] + revision: int + deployed_app_variant: Optional[PydanticObjectId] + deployed_app_variant_revision: Optional[Link[AppVariantRevisionsDB]] + deployment: Optional[PydanticObjectId] # reference to deployment + created_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + + class Settings: + name = "environments" + + +class AppEnvironmentRevisionDB(Document): + environment: Link[AppEnvironmentDB] + revision: int + modified_by: Link[UserDB] + deployed_app_variant_revision: Optional[PydanticObjectId] + deployment: Optional[PydanticObjectId] # reference to deployment + created_at: datetime + + class Settings: + name = "environments_revisions" + + +class TemplateDB(Document): + type: Optional[str] = Field(default="image") + template_uri: Optional[str] + tag_id: Optional[int] + name: str = Field(unique=True) # tag name of image + repo_name: Optional[str] + title: str + description: str + size: Optional[int] + digest: Optional[str] # sha256 hash of image digest + last_pushed: Optional[datetime] + + class Settings: + name = "templates" + + +class TestSetDB(Document): + name: str + app: Link[AppDB] + csvdata: List[Dict[str, str]] + user: Link[UserDB] + created_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + updated_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + + class Settings: + name = "testsets" + + +class EvaluatorConfigDB(Document): + app: Link[AppDB] + user: Link[UserDB] + name: str + evaluator_key: str + settings_values: Dict[str, Any] = Field(default=dict) + created_at: datetime = Field(default=datetime.now(timezone.utc)) + updated_at: datetime = Field(default=datetime.now(timezone.utc)) + + class Settings: + name = "evaluators_configs" + + +class Error(BaseModel): + message: str + stacktrace: Optional[str] = None + + +class Result(BaseModel): + type: str + value: Optional[Any] = None + error: Optional[Error] = None + + +class InvokationResult(BaseModel): + result: Result + cost: Optional[float] = None + latency: Optional[float] = None + + +class EvaluationScenarioResult(BaseModel): + evaluator_config: PydanticObjectId + result: Result + + +class AggregatedResult(BaseModel): + evaluator_config: PydanticObjectId + result: Result + + +class EvaluationScenarioInputDB(BaseModel): + name: str + type: str + value: str + + +class EvaluationScenarioOutputDB(BaseModel): + result: Result + cost: Optional[float] = None + latency: Optional[float] = None + + +class HumanEvaluationScenarioInput(BaseModel): + input_name: str + input_value: str + + +class HumanEvaluationScenarioOutput(BaseModel): + variant_id: str + variant_output: str + + +class HumanEvaluationDB(Document): + app: Link[AppDB] + user: Link[UserDB] + status: str + evaluation_type: str + variants: List[PydanticObjectId] + variants_revisions: List[PydanticObjectId] + testset: Link[TestSetDB] + created_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + updated_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + + class Settings: + name = "human_evaluations" + + +class HumanEvaluationScenarioDB(Document): + user: Link[UserDB] + evaluation: Link[HumanEvaluationDB] + inputs: List[HumanEvaluationScenarioInput] + outputs: List[HumanEvaluationScenarioOutput] + vote: Optional[str] + score: Optional[Any] + correct_answer: Optional[str] + created_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + updated_at: Optional[datetime] = Field(default=datetime.now(timezone.utc)) + is_pinned: Optional[bool] + note: Optional[str] + + class Settings: + name = "human_evaluations_scenarios" + + +class EvaluationDB(Document): + app: Link[AppDB] + user: Link[UserDB] + status: Result + testset: Link[TestSetDB] + variant: PydanticObjectId + variant_revision: PydanticObjectId + evaluators_configs: List[PydanticObjectId] + aggregated_results: List[AggregatedResult] + average_cost: Optional[Result] = None + total_cost: Optional[Result] = None + average_latency: Optional[Result] = None + created_at: datetime = Field(default=datetime.now(timezone.utc)) + updated_at: datetime = Field(default=datetime.now(timezone.utc)) + + class Settings: + name = "new_evaluations" + + +class CorrectAnswer(BaseModel): + key: str + value: str + + +class EvaluationScenarioDB(Document): + user: Link[UserDB] + evaluation: Link[EvaluationDB] + variant_id: PydanticObjectId + inputs: List[EvaluationScenarioInputDB] + outputs: List[EvaluationScenarioOutputDB] + correct_answers: Optional[List[CorrectAnswer]] + is_pinned: Optional[bool] + note: Optional[str] + evaluators_configs: List[PydanticObjectId] + results: List[EvaluationScenarioResult] + latency: Optional[int] = None + cost: Optional[int] = None + created_at: datetime = Field(default=datetime.now(timezone.utc)) + updated_at: datetime = Field(default=datetime.now(timezone.utc)) + + class Settings: + name = "new_evaluation_scenarios" + + +class OldEvaluationScenarioDB(Document): + user: Link[UserDB] + evaluation: Link[EvaluationDB] + variant_id: PydanticObjectId + inputs: List[EvaluationScenarioInputDB] + outputs: List[EvaluationScenarioOutputDB] + correct_answer: Optional[str] + is_pinned: Optional[bool] + note: Optional[str] + evaluators_configs: List[PydanticObjectId] + results: List[EvaluationScenarioResult] + latency: Optional[int] = None + cost: Optional[int] = None + created_at: datetime = Field(default=datetime.now(timezone.utc)) + updated_at: datetime = Field(default=datetime.now(timezone.utc)) + + class Settings: + name = "new_evaluation_scenarios" + + +class Forward: + @iterative_migration() + async def migrate_correct_answers( + self, + input_document: OldEvaluationScenarioDB, + output_document: EvaluationScenarioDB, + ): + if input_document.correct_answer: + output_document.correct_answers = [ + CorrectAnswer(key="correct_answer", value=input_document.correct_answer) + ] + else: + output_document.correct_answers = [] + + if "correct_answer" in input_document.dict(): + del input_document.__dict__["correct_answer"] + + +class Backward: + ... diff --git a/agenta-backend/agenta_backend/models/api/evaluation_model.py b/agenta-backend/agenta_backend/models/api/evaluation_model.py index cce2d7db7e..0313022409 100644 --- a/agenta-backend/agenta_backend/models/api/evaluation_model.py +++ b/agenta-backend/agenta_backend/models/api/evaluation_model.py @@ -158,13 +158,18 @@ class HumanEvaluationScenarioUpdate(BaseModel): note: Optional[str] +class CorrectAnswer(BaseModel): + key: str + value: str + + class EvaluationScenario(BaseModel): id: Optional[str] evaluation_id: str inputs: List[EvaluationScenarioInput] outputs: List[EvaluationScenarioOutput] evaluation: Optional[str] - correct_answer: Optional[str] + correct_answers: Optional[List[CorrectAnswer]] is_pinned: Optional[bool] note: Optional[str] results: List[EvaluationScenarioResult] diff --git a/agenta-backend/agenta_backend/models/converters.py b/agenta-backend/agenta_backend/models/converters.py index de7c6dabfb..cb73ea5976 100644 --- a/agenta-backend/agenta_backend/models/converters.py +++ b/agenta-backend/agenta_backend/models/converters.py @@ -9,6 +9,7 @@ from agenta_backend.utils.common import isCloudEE from agenta_backend.models.api.user_models import User from agenta_backend.models.api.evaluation_model import ( + CorrectAnswer, Evaluation, HumanEvaluation, EvaluatorConfig, @@ -253,7 +254,10 @@ def evaluation_scenario_db_to_pydantic( EvaluationScenarioOutput(**scenario_output.dict()) for scenario_output in evaluation_scenario_db.outputs ], - correct_answer=evaluation_scenario_db.correct_answer, + correct_answers=[ + CorrectAnswer(**correct_answer.dict()) + for correct_answer in evaluation_scenario_db.correct_answers + ], is_pinned=evaluation_scenario_db.is_pinned or False, note=evaluation_scenario_db.note or "", results=evaluation_scenarios_results_to_pydantic( diff --git a/agenta-backend/agenta_backend/models/db_models.py b/agenta-backend/agenta_backend/models/db_models.py index e67c8b42ce..85877bb20c 100644 --- a/agenta-backend/agenta_backend/models/db_models.py +++ b/agenta-backend/agenta_backend/models/db_models.py @@ -278,13 +278,18 @@ class Settings: name = "new_evaluations" +class CorrectAnswer(BaseModel): + key: str + value: str + + class EvaluationScenarioDB(Document): user: Link[UserDB] evaluation: Link[EvaluationDB] variant_id: PydanticObjectId inputs: List[EvaluationScenarioInputDB] outputs: List[EvaluationScenarioOutputDB] - correct_answer: Optional[str] + correct_answers: Optional[List[CorrectAnswer]] is_pinned: Optional[bool] note: Optional[str] evaluators_configs: List[PydanticObjectId] diff --git a/agenta-backend/agenta_backend/resources/evaluators/evaluators.py b/agenta-backend/agenta_backend/resources/evaluators/evaluators.py index effa7d417e..8e94d2c24e 100644 --- a/agenta-backend/agenta_backend/resources/evaluators/evaluators.py +++ b/agenta-backend/agenta_backend/resources/evaluators/evaluators.py @@ -4,18 +4,22 @@ "key": "auto_exact_match", "direct_use": True, "settings_template": { - "label": "Exact Match Settings", - "description": "Settings for the Exact Match evaluator", + "correct_answer_key": { + "label": "Expected Answer Column", + "default": "correct_answer", + "type": "string", + "advanced": True, # Tells the frontend that this setting is advanced and should be hidden by default + "ground_truth_key": True, # Tells the frontend that is the name of the column in the test set that should be shown as a ground truth to the user + "description": "The name of the column in the test data that contains the correct answer", + }, }, + "description": "Exact Match evaluator determines if the output exactly matches the specified correct answer, ensuring precise alignment with expected results.", }, { "name": "Contains Json", "key": "auto_contains_json", "direct_use": True, - "settings_template": { - "label": "Single Model Testing Settings", - "description": "Checks if the JSON output contains the specified JSON structure.", - }, + "settings_template": {}, "description": "Contains Json evaluator checks if the output contains the specified JSON structure.", }, { @@ -31,7 +35,15 @@ "min": 0, "max": 1, "required": True, - } + }, + "correct_answer_key": { + "label": "Expected Answer Column", + "default": "correct_answer", + "type": "string", + "advanced": True, # Tells the frontend that this setting is advanced and should be hidden by default + "ground_truth_key": True, # Tells the frontend that is the name of the column in the test set that should be shown as a ground truth to the user + "description": "The name of the column in the test data that contains the correct answer", + }, }, "description": "Similarity Match evaluator checks if the generated answer is similar to the expected answer. You need to provide the similarity threshold. It uses the Jaccard similarity to compare the answers.", }, @@ -67,7 +79,15 @@ "default": "", "description": "The name of the field in the JSON output that you wish to evaluate", "required": True, - } + }, + "correct_answer_key": { + "label": "Expected Answer Column", + "default": "correct_answer", + "type": "string", + "advanced": True, # Tells the frontend that this setting is advanced and should be hidden by default + "ground_truth_key": True, # Tells the frontend that is the name of the column in the test set that should be shown as a ground truth to the user + "description": "The name of the column in the test data that contains the correct answer", + }, }, "description": "JSON Field Match evaluator compares specific fields within JSON (JavaScript Object Notation) data. This matching can involve finding similarities or correspondences between fields in different JSON objects.", }, @@ -79,10 +99,18 @@ "prompt_template": { "label": "Prompt Template", "type": "text", - "default": "We have an LLM App that we want to evaluate its outputs. Based on the prompt and the parameters provided below evaluate the output based on the evaluation strategy below:\nEvaluation strategy: 0 to 10 0 is very bad and 10 is very good.\nPrompt: {llm_app_prompt_template}\nInputs: country: {country}\nCorrect Answer:{correct_answer}\nEvaluate this: {variant_output}\n\nAnswer ONLY with one of the given grading or evaluation options.", + "default": "We have an LLM App that we want to evaluate its outputs. Based on the prompt and the parameters provided below evaluate the output based on the evaluation strategy below:\nEvaluation strategy: 0 to 10 0 is very bad and 10 is very good.\nPrompt: {llm_app_prompt_template}\nInputs: country: {country}\nExpected Answer Column:{correct_answer}\nEvaluate this: {variant_output}\n\nAnswer ONLY with one of the given grading or evaluation options.", "description": "Template for AI critique prompts", "required": True, - } + }, + "correct_answer_key": { + "label": "Expected Answer Column", + "default": "correct_answer", + "type": "string", + "advanced": True, # Tells the frontend that this setting is advanced and should be hidden by default + "ground_truth_key": True, # Tells the frontend that is the name of the column in the test set that should be shown as a ground truth to the user + "description": "The name of the column in the test data that contains the correct answer", + }, }, "description": "AI Critique evaluator sends the generated answer and the correct_answer to an LLM model and uses it to evaluate the correctness of the answer. You need to provide the evaluation prompt (or use the default prompt).", }, @@ -112,39 +140,33 @@ "description": "https://your-webhook-url.com", "required": True, }, + "correct_answer_key": { + "label": "Expected Answer Column", + "default": "correct_answer", + "type": "string", + "advanced": True, # Tells the frontend that this setting is advanced and should be hidden by default + "ground_truth_key": True, # Tells the frontend that is the name of the column in the test set that should be shown as a ground truth to the user + "description": "The name of the column in the test data that contains the correct answer", + }, }, "description": "Webhook test evaluator sends the generated answer and the correct_answer to a webhook and expects a response indicating the correctness of the answer. You need to provide the URL of the webhook and the response of the webhook must be between 0 and 1.", }, - { - "name": "A/B Test", - "key": "human_a_b_testing", - "direct_use": False, - "settings_template": { - "label": "A/B Testing Settings", - "description": "Settings for A/B testing configurations", - }, - }, - { - "name": "Single Model Test", - "key": "human_single_model_test", - "direct_use": False, - "settings_template": { - "label": "Single Model Testing Settings", - "description": "Settings for single model testing configurations", - }, - }, { "name": "Starts With", "key": "auto_starts_with", "direct_use": False, "settings_template": { - "label": "Single Model Testing Settings", - "description": "Checks if the output starts with the specified prefix.", - "prefix": {"label": "prefix", "type": "string", "required": True}, + "prefix": { + "label": "prefix", + "type": "string", + "required": True, + "description": "The string to match at the start of the output.", + }, "case_sensitive": { "label": "Case Sensitive", "type": "boolean", "default": True, + "description": "If the evaluation should be case sensitive.", }, }, "description": "Starts With evaluator checks if the output starts with a specified prefix, considering case sensitivity based on the settings.", @@ -154,8 +176,6 @@ "key": "auto_ends_with", "direct_use": False, "settings_template": { - "label": "Single Model Testing Settings", - "description": "Checks if the output ends with the specified suffix.", "case_sensitive": { "label": "Case Sensitive", "type": "boolean", @@ -176,8 +196,6 @@ "key": "auto_contains", "direct_use": False, "settings_template": { - "label": "Single Model Testing Settings", - "description": "Checks if the output contains the specified substring.", "case_sensitive": { "label": "Case Sensitive", "type": "boolean", @@ -198,8 +216,6 @@ "key": "auto_contains_any", "direct_use": False, "settings_template": { - "label": "Single Model Testing Settings", - "description": "Checks if the output contains any of the specified substrings.", "case_sensitive": { "label": "Case Sensitive", "type": "boolean", @@ -220,8 +236,6 @@ "key": "auto_contains_all", "direct_use": False, "settings_template": { - "label": "Single Model Testing Settings", - "description": "Checks if the output contains all of the specified substrings.", "case_sensitive": { "label": "Case Sensitive", "type": "boolean", @@ -242,9 +256,20 @@ "key": "auto_levenshtein_distance", "direct_use": False, "settings_template": { - "label": "Levenshtein Distance Settings", - "description": "Evaluates the Levenshtein distance between the output and the correct answer. If a threshold is specified, it checks if the distance is below this threshold and returns a boolean value. If no threshold is specified, it returns the numerical Levenshtein distance.", - "threshold": {"label": "Threshold", "type": "number", "required": False}, + "threshold": { + "label": "Threshold", + "type": "number", + "required": False, + "description": "The maximum allowed Levenshtein distance between the output and the correct answer.", + }, + "correct_answer_key": { + "label": "Expected Answer Column", + "default": "correct_answer", + "type": "string", + "advanced": True, # Tells the frontend that this setting is advanced and should be hidden by default + "ground_truth_key": True, # Tells the frontend that is the name of the column in the test set that should be shown as a ground truth to the user + "description": "The name of the column in the test data that contains the correct answer", + }, }, "description": "This evaluator calculates the Levenshtein distance between the output and the correct answer. If a threshold is provided in the settings, it returns a boolean indicating whether the distance is within the threshold. If no threshold is provided, it returns the actual Levenshtein distance as a numerical value.", }, diff --git a/agenta-backend/agenta_backend/routers/evaluation_router.py b/agenta-backend/agenta_backend/routers/evaluation_router.py index a8552b73db..cb71942398 100644 --- a/agenta-backend/agenta_backend/routers/evaluation_router.py +++ b/agenta-backend/agenta_backend/routers/evaluation_router.py @@ -119,11 +119,6 @@ async def create_evaluation( return response evaluations = [] - correct_answer_column = ( - "correct_answer" - if payload.correct_answer_column is None - else payload.correct_answer_column - ) for variant_id in payload.variant_ids: evaluation = await evaluation_service.create_new_evaluation( @@ -141,7 +136,6 @@ async def create_evaluation( evaluation_id=evaluation.id, rate_limit_config=payload.rate_limit.dict(), lm_providers_keys=payload.lm_providers_keys, - correct_answer_column=correct_answer_column, ) evaluations.append(evaluation) diff --git a/agenta-backend/agenta_backend/services/db_manager.py b/agenta-backend/agenta_backend/services/db_manager.py index acf8c358cb..dc813026c3 100644 --- a/agenta-backend/agenta_backend/services/db_manager.py +++ b/agenta-backend/agenta_backend/services/db_manager.py @@ -59,6 +59,7 @@ ) from agenta_backend.models.db_models import ( ConfigDB, + CorrectAnswer, TemplateDB, AggregatedResult, AppVariantRevisionsDB, @@ -1907,7 +1908,7 @@ async def create_new_evaluation_scenario( variant_id: str, inputs: List[EvaluationScenarioInputDB], outputs: List[EvaluationScenarioOutputDB], - correct_answer: Optional[str], + correct_answers: Optional[List[CorrectAnswer]], is_pinned: Optional[bool], note: Optional[str], evaluators_configs: List[EvaluatorConfigDB], @@ -1925,7 +1926,7 @@ async def create_new_evaluation_scenario( variant_id=ObjectId(variant_id), inputs=inputs, outputs=outputs, - correct_answer=correct_answer, + correct_answers=correct_answers, is_pinned=is_pinned, note=note, evaluators_configs=evaluators_configs, diff --git a/agenta-backend/agenta_backend/services/evaluator_manager.py b/agenta-backend/agenta_backend/services/evaluator_manager.py index c86a4ef946..c4cc49ace3 100644 --- a/agenta-backend/agenta_backend/services/evaluator_manager.py +++ b/agenta-backend/agenta_backend/services/evaluator_manager.py @@ -17,6 +17,7 @@ from agenta_backend.models.converters import evaluator_config_db_to_pydantic from agenta_backend.resources.evaluators.evaluators import get_all_evaluators from agenta_backend.models.api.evaluation_model import Evaluator, EvaluatorConfig +from agenta_backend.resources.evaluators import evaluators def get_evaluators() -> Optional[List[Evaluator]]: @@ -79,6 +80,7 @@ async def create_evaluator_config( EvaluatorConfigDB: The newly created evaluator configuration object. """ app = await db_manager.fetch_app_by_id(app_id) + evaluator_config = await db_manager.create_evaluator_config( app=app, organization=app.organization if isCloudEE() else None, # noqa, @@ -139,13 +141,22 @@ async def create_ready_to_use_evaluators(app: AppDB): Returns: Nothing. The function works by side effect, modifying the database. """ - evaluators = get_evaluators() - direct_use_evaluators = [ - evaluator for evaluator in evaluators if evaluator.get("direct_use") + evaluator for evaluator in get_evaluators() if evaluator.get("direct_use") ] for evaluator in direct_use_evaluators: + settings_values = { + setting_name: setting.get("default") + for setting_name, setting in evaluator.get("settings_template", {}).items() + if setting.get("ground_truth_key") is True and setting.get("default", "") + } + + for setting_name, default_value in settings_values.items(): + assert ( + default_value != "" + ), f"Default value for ground truth key '{setting_name}' in Evaluator is empty" + await db_manager.create_evaluator_config( app=app, organization=app.organization if isCloudEE() else None, # noqa, @@ -153,7 +164,7 @@ async def create_ready_to_use_evaluators(app: AppDB): user=app.user, name=evaluator["name"], evaluator_key=evaluator["key"], - settings_values={}, + settings_values=settings_values, ) diff --git a/agenta-backend/agenta_backend/services/evaluators_service.py b/agenta-backend/agenta_backend/services/evaluators_service.py index 6a8219e056..d73a4229d9 100644 --- a/agenta-backend/agenta_backend/services/evaluators_service.py +++ b/agenta-backend/agenta_backend/services/evaluators_service.py @@ -1,81 +1,96 @@ -import re import json +import logging +import re +from typing import Any, Dict, List, Tuple + import httpx -from typing import Any, Dict, Tuple +from openai import OpenAI -from agenta_backend.services.security import sandbox from agenta_backend.models.db_models import Error, Result - -from langchain.llms import OpenAI -from langchain.chains import LLMChain -from langchain.prompts import PromptTemplate -import logging +from agenta_backend.services.security import sandbox logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) +def get_correct_answer( + data_point: Dict[str, Any], settings_values: Dict[str, Any] +) -> Any: + """ + Helper function to retrieve the correct answer from the data point based on the settings values. + + Args: + data_point (Dict[str, Any]): The data point containing the correct answer. + settings_values (Dict[str, Any]): The settings values containing the key for the correct answer. + + Returns: + Any: The correct answer from the data point. + + Raises: + ValueError: If the correct answer key is not provided or not found in the data point. + """ + correct_answer_key = settings_values.get("correct_answer_key") + if correct_answer_key is None: + raise ValueError("No correct answer keys provided.") + if correct_answer_key not in data_point: + raise ValueError( + f"Correct answer column '{correct_answer_key}' not found in the test set." + ) + return data_point[correct_answer_key] + + def auto_exact_match( - inputs: Dict[str, Any], + inputs: Dict[str, Any], # pylint: disable=unused-argument output: str, - correct_answer: str, - app_params: Dict[str, Any], + data_point: Dict[str, Any], # pylint: disable=unused-argument + app_params: Dict[str, Any], # pylint: disable=unused-argument settings_values: Dict[str, Any], - lm_providers_keys: Dict[str, Any], + lm_providers_keys: Dict[str, Any], # pylint: disable=unused-argument ) -> Result: + """ + Evaluator function to determine if the output exactly matches the correct answer. + + Args: + inputs (Dict[str, Any]): The inputs for the evaluation. + output (str): The output generated by the model. + data_point (Dict[str, Any]): The data point containing the correct answer. + app_params (Dict[str, Any]): The application parameters. + settings_values (Dict[str, Any]): The settings values containing the key for the correct answer. + lm_providers_keys (Dict[str, Any]): The language model provider keys. + + Returns: + Result: A Result object containing the evaluation result. + """ try: + correct_answer = get_correct_answer(data_point, settings_values) exact_match = True if output == correct_answer else False result = Result(type="bool", value=exact_match) return result - except Exception as e: + except ValueError as e: return Result( type="error", value=None, error=Error( - message="Error during Auto Exact Match evaluation", stacktrace=str(e) + message=str(e), ), ) - - -def auto_similarity_match( - inputs: Dict[str, Any], - output: str, - correct_answer: str, - app_params: Dict[str, Any], - settings_values: Dict[str, Any], - lm_providers_keys: Dict[str, Any], -) -> Result: - try: - set1 = set(output.split()) - set2 = set(correct_answer.split()) - intersect = set1.intersection(set2) - union = set1.union(set2) - - similarity = len(intersect) / len(union) - - is_similar = ( - True if similarity > settings_values["similarity_threshold"] else False - ) - result = Result(type="bool", value=is_similar) - return result - except Exception as e: + except Exception as e: # pylint: disable=broad-except return Result( type="error", value=None, error=Error( - message="Error during Auto Similarity Match evaluation", - stacktrace=str(e), + message="Error during Auto Exact Match evaluation", stacktrace=str(e) ), ) def auto_regex_test( - inputs: Dict[str, Any], + inputs: Dict[str, Any], # pylint: disable=unused-argument output: str, - correct_answer: str, - app_params: Dict[str, Any], + data_point: Dict[str, Any], # pylint: disable=unused-argument + app_params: Dict[str, Any], # pylint: disable=unused-argument settings_values: Dict[str, Any], - lm_providers_keys: Dict[str, Any], + lm_providers_keys: Dict[str, Any], # pylint: disable=unused-argument ) -> Result: try: re_pattern = re.compile(settings_values["regex_pattern"], re.IGNORECASE) @@ -83,7 +98,7 @@ def auto_regex_test( bool(re_pattern.search(output)) == settings_values["regex_should_match"] ) return Result(type="bool", value=result) - except Exception as e: + except Exception as e: # pylint: disable=broad-except return Result( type="error", value=None, @@ -94,31 +109,42 @@ def auto_regex_test( def field_match_test( - inputs: Dict[str, Any], + inputs: Dict[str, Any], # pylint: disable=unused-argument output: str, - correct_answer: str, - app_params: Dict[str, Any], + data_point: Dict[str, Any], + app_params: Dict[str, Any], # pylint: disable=unused-argument settings_values: Dict[str, Any], - lm_providers_keys: Dict[str, Any], + lm_providers_keys: Dict[str, Any], # pylint: disable=unused-argument ) -> Result: try: + correct_answer = get_correct_answer(data_point, settings_values) output_json = json.loads(output) result = output_json[settings_values["json_field"]] == correct_answer return Result(type="bool", value=result) - except Exception as e: - logging.debug("Field Match Test Failed because of Error: " + str(e)) + except ValueError as e: + return Result( + type="error", + value=None, + error=Error( + message=str(e), + ), + ) + except Exception as e: # pylint: disable=broad-except + logging.debug("Field Match Test Failed because of Error: %s", str(e)) return Result(type="bool", value=False) def auto_webhook_test( inputs: Dict[str, Any], output: str, - correct_answer: str, - app_params: Dict[str, Any], + data_point: Dict[str, Any], + app_params: Dict[str, Any], # pylint: disable=unused-argument settings_values: Dict[str, Any], - lm_providers_keys: Dict[str, Any], + lm_providers_keys: Dict[str, Any], # pylint: disable=unused-argument ) -> Result: try: + correct_answer = get_correct_answer(data_point, settings_values) + with httpx.Client() as client: payload = { "correct_answer": correct_answer, @@ -146,6 +172,14 @@ def auto_webhook_test( ), ) return Result(type="number", value=score) + except ValueError as e: + return Result( + type="error", + value=None, + error=Error( + message=str(e), + ), + ) except httpx.HTTPError as e: return Result( type="error", @@ -155,7 +189,7 @@ def auto_webhook_test( stacktrace=str(e), ), ) - except Exception as e: + except Exception as e: # pylint: disable=broad-except return Result( type="error", value=None, @@ -168,21 +202,21 @@ def auto_webhook_test( def auto_custom_code_run( inputs: Dict[str, Any], output: str, - correct_answer: str, + data_point: Dict[str, Any], app_params: Dict[str, Any], settings_values: Dict[str, Any], - lm_providers_keys: Dict[str, Any], + lm_providers_keys: Dict[str, Any], # pylint: disable=unused-argument ) -> Result: try: result = sandbox.execute_code_safely( app_params=app_params, inputs=inputs, output=output, - correct_answer=correct_answer, + data_point=data_point, code=settings_values["code"], ) return Result(type="number", value=result) - except Exception as e: + except Exception as e: # pylint: disable=broad-except return Result( type="error", value=None, @@ -195,31 +229,28 @@ def auto_custom_code_run( def auto_ai_critique( inputs: Dict[str, Any], output: str, - correct_answer: str, + data_point: Dict[str, Any], app_params: Dict[str, Any], settings_values: Dict[str, Any], lm_providers_keys: Dict[str, Any], -) -> str: +) -> Result: """ Evaluate a response using an AI critique based on provided inputs, output, correct answer, app parameters, and settings. Args: inputs (Dict[str, Any]): Input parameters for the LLM app variant. output (str): The output of the LLM app variant. - correct_answer (str): Correct answer for evaluation. + correct_answer_key (str): The key name of the correct answer in the datapoint. app_params (Dict[str, Any]): Application parameters. settings_values (Dict[str, Any]): Settings for the evaluation. lm_providers_keys (Dict[str, Any]): Keys for language model providers. Returns: - str: Evaluation result. + Result: Evaluation result. """ try: - llm = OpenAI( - openai_api_key=lm_providers_keys["OPENAI_API_KEY"], - temperature=0.8, - model="gpt-3.5-turbo-instruct", - ) + correct_answer = get_correct_answer(data_point, settings_values) + openai_api_key = lm_providers_keys["OPENAI_API_KEY"] chain_run_args = { "llm_app_prompt_template": app_params.get("prompt_user", ""), @@ -230,18 +261,21 @@ def auto_ai_critique( for key, value in inputs.items(): chain_run_args[key] = value - prompt = PromptTemplate( - input_variables=list( - chain_run_args.keys() - ), # Use the keys from chain_run_args - template=settings_values["prompt_template"], + prompt_template = settings_values["prompt_template"] + messages = [ + {"role": "system", "content": prompt_template}, + {"role": "user", "content": str(chain_run_args)}, + ] + + client = OpenAI(api_key=openai_api_key) + response = client.chat.completions.create( + model="gpt-3.5-turbo", messages=messages, temperature=0.8 ) - chain = LLMChain(llm=llm, prompt=prompt) - evaluation_output = chain.run(**chain_run_args) + evaluation_output = response.choices[0].message["content"].strip() - return Result(type="text", value=evaluation_output.strip()) - except Exception as e: + return Result(type="text", value=evaluation_output) + except Exception as e: # pylint: disable=broad-except return Result( type="error", value=None, @@ -250,12 +284,12 @@ def auto_ai_critique( def auto_starts_with( - inputs: Dict[str, Any], + inputs: Dict[str, Any], # pylint: disable=unused-argument output: str, - correct_answer: str, - app_params: Dict[str, Any], + data_point: Dict[str, Any], # pylint: disable=unused-argument + app_params: Dict[str, Any], # pylint: disable=unused-argument settings_values: Dict[str, Any], - lm_providers_keys: Dict[str, Any], + lm_providers_keys: Dict[str, Any], # pylint: disable=unused-argument ) -> Result: try: prefix = settings_values.get("prefix", "") @@ -267,7 +301,7 @@ def auto_starts_with( result = Result(type="bool", value=output.startswith(prefix)) return result - except Exception as e: + except Exception as e: # pylint: disable=broad-except return Result( type="error", value=None, @@ -278,12 +312,12 @@ def auto_starts_with( def auto_ends_with( - inputs: Dict[str, Any], + inputs: Dict[str, Any], # pylint: disable=unused-argument output: str, - correct_answer: str, + data_point: Dict[str, Any], # pylint: disable=unused-argument app_params: Dict[str, Any], settings_values: Dict[str, Any], - lm_providers_keys: Dict[str, Any], + lm_providers_keys: Dict[str, Any], # pylint: disable=unused-argument ) -> Result: try: suffix = settings_values.get("suffix", "") @@ -295,7 +329,7 @@ def auto_ends_with( result = Result(type="bool", value=output.endswith(suffix)) return result - except Exception as e: + except Exception as e: # pylint: disable=broad-except return Result( type="error", value=None, @@ -304,12 +338,12 @@ def auto_ends_with( def auto_contains( - inputs: Dict[str, Any], + inputs: Dict[str, Any], # pylint: disable=unused-argument output: str, - correct_answer: str, - app_params: Dict[str, Any], + data_point: Dict[str, Any], # pylint: disable=unused-argument + app_params: Dict[str, Any], # pylint: disable=unused-argument settings_values: Dict[str, Any], - lm_providers_keys: Dict[str, Any], + lm_providers_keys: Dict[str, Any], # pylint: disable=unused-argument ) -> Result: try: substring = settings_values.get("substring", "") @@ -321,7 +355,7 @@ def auto_contains( result = Result(type="bool", value=substring in output) return result - except Exception as e: + except Exception as e: # pylint: disable=broad-except return Result( type="error", value=None, @@ -330,12 +364,12 @@ def auto_contains( def auto_contains_any( - inputs: Dict[str, Any], + inputs: Dict[str, Any], # pylint: disable=unused-argument output: str, - correct_answer: str, - app_params: Dict[str, Any], + data_point: Dict[str, Any], # pylint: disable=unused-argument + app_params: Dict[str, Any], # pylint: disable=unused-argument settings_values: Dict[str, Any], - lm_providers_keys: Dict[str, Any], + lm_providers_keys: Dict[str, Any], # pylint: disable=unused-argument ) -> Result: try: substrings_str = settings_values.get("substrings", "") @@ -350,7 +384,7 @@ def auto_contains_any( type="bool", value=any(substring in output for substring in substrings) ) return result - except Exception as e: + except Exception as e: # pylint: disable=broad-except return Result( type="error", value=None, @@ -361,12 +395,12 @@ def auto_contains_any( def auto_contains_all( - inputs: Dict[str, Any], + inputs: Dict[str, Any], # pylint: disable=unused-argument output: str, - correct_answer: str, - app_params: Dict[str, Any], + data_point: Dict[str, Any], # pylint: disable=unused-argument + app_params: Dict[str, Any], # pylint: disable=unused-argument settings_values: Dict[str, Any], - lm_providers_keys: Dict[str, Any], + lm_providers_keys: Dict[str, Any], # pylint: disable=unused-argument ) -> Result: try: substrings_str = settings_values.get("substrings", "") @@ -381,7 +415,7 @@ def auto_contains_all( type="bool", value=all(substring in output for substring in substrings) ) return result - except Exception as e: + except Exception as e: # pylint: disable=broad-except return Result( type="error", value=None, @@ -392,12 +426,12 @@ def auto_contains_all( def auto_contains_json( - inputs: Dict[str, Any], + inputs: Dict[str, Any], # pylint: disable=unused-argument output: str, - correct_answer: str, - app_params: Dict[str, Any], - settings_values: Dict[str, Any], - lm_providers_keys: Dict[str, Any], + data_point: Dict[str, Any], # pylint: disable=unused-argument + app_params: Dict[str, Any], # pylint: disable=unused-argument + settings_values: Dict[str, Any], # pylint: disable=unused-argument + lm_providers_keys: Dict[str, Any], # pylint: disable=unused-argument ) -> Result: try: try: @@ -411,7 +445,7 @@ def auto_contains_json( contains_json = False return Result(type="bool", value=contains_json) - except Exception as e: + except Exception as e: # pylint: disable=broad-except return Result( type="error", value=None, @@ -423,7 +457,7 @@ def auto_contains_json( def levenshtein_distance(s1, s2): if len(s1) < len(s2): - return levenshtein_distance(s2, s1) + return levenshtein_distance(s2, s1) # pylint: disable=arguments-out-of-order if len(s2) == 0: return len(s1) @@ -442,14 +476,16 @@ def levenshtein_distance(s1, s2): def auto_levenshtein_distance( - inputs: Dict[str, Any], + inputs: Dict[str, Any], # pylint: disable=unused-argument output: str, - correct_answer: str, - app_params: Dict[str, Any], + data_point: Dict[str, Any], + app_params: Dict[str, Any], # pylint: disable=unused-argument settings_values: Dict[str, Any], - lm_providers_keys: Dict[str, Any], + lm_providers_keys: Dict[str, Any], # pylint: disable=unused-argument ) -> Result: try: + correct_answer = get_correct_answer(data_point, settings_values) + distance = levenshtein_distance(output, correct_answer) if "threshold" in settings_values: @@ -459,7 +495,15 @@ def auto_levenshtein_distance( return Result(type="number", value=distance) - except Exception as e: + except ValueError as e: + return Result( + type="error", + value=None, + error=Error( + message=str(e), + ), + ) + except Exception as e: # pylint: disable=broad-except return Result( type="error", value=None, @@ -470,28 +514,98 @@ def auto_levenshtein_distance( ) +def auto_similarity_match( + inputs: Dict[str, Any], + output: str, + data_point: Dict[str, Any], + app_params: Dict[str, Any], + settings_values: Dict[str, Any], + lm_providers_keys: Dict[str, Any], +) -> Result: + try: + correct_answer = get_correct_answer(data_point, settings_values) + set1 = set(output.split()) + set2 = set(correct_answer.split()) + intersect = set1.intersection(set2) + union = set1.union(set2) + + similarity = len(intersect) / len(union) + + is_similar = ( + True if similarity > settings_values["similarity_threshold"] else False + ) + result = Result(type="bool", value=is_similar) + return result + except ValueError as e: + return Result( + type="error", + value=None, + error=Error( + message=str(e), + ), + ) + except Exception as e: # pylint: disable=broad-except + return Result( + type="error", + value=None, + error=Error( + message="Error during Auto Similarity Match evaluation", + stacktrace=str(e), + ), + ) + + +EVALUATOR_FUNCTIONS = { + "auto_exact_match": auto_exact_match, + "auto_regex_test": auto_regex_test, + "field_match_test": field_match_test, + "auto_webhook_test": auto_webhook_test, + "auto_custom_code_run": auto_custom_code_run, + "auto_ai_critique": auto_ai_critique, + "auto_starts_with": auto_starts_with, + "auto_ends_with": auto_ends_with, + "auto_contains": auto_contains, + "auto_contains_any": auto_contains_any, + "auto_contains_all": auto_contains_all, + "auto_contains_json": auto_contains_json, + "auto_levenshtein_distance": auto_levenshtein_distance, + "auto_similarity_match": auto_similarity_match, +} + + def evaluate( evaluator_key: str, inputs: Dict[str, Any], output: str, - correct_answer: str, + data_point: Dict[str, Any], app_params: Dict[str, Any], settings_values: Dict[str, Any], lm_providers_keys: Dict[str, Any], ) -> Result: - evaluation_function = globals().get(evaluator_key, None) + evaluation_function = EVALUATOR_FUNCTIONS.get(evaluator_key, None) if not evaluation_function: - raise ValueError(f"Evaluation method '{evaluator_key}' not found.") + return Result( + type="error", + value=None, + error=Error( + message=f"Evaluation method '{evaluator_key}' not found.", + ), + ) try: return evaluation_function( inputs, output, - correct_answer, + data_point, app_params, settings_values, lm_providers_keys, ) except Exception as exc: - raise RuntimeError( - f"Error occurred while running {evaluator_key} evaluation. Exception: {str(exc)}" + return Result( + type="error", + value=None, + error=Error( + message="Error occurred while running {evaluator_key} evaluation. ", + stacktrace=str(exc), + ), ) diff --git a/agenta-backend/agenta_backend/tasks/evaluations.py b/agenta-backend/agenta_backend/tasks/evaluations.py index 5dd602de6e..15a055b825 100644 --- a/agenta-backend/agenta_backend/tasks/evaluations.py +++ b/agenta-backend/agenta_backend/tasks/evaluations.py @@ -3,20 +3,23 @@ import asyncio import logging import traceback - from typing import Any, Dict, List + from celery import shared_task, states from agenta_backend.utils.common import isCloudEE from agenta_backend.models.db_engine import DBEngine -from agenta_backend.services import evaluators_service, llm_apps_service - -from agenta_backend.models.api.evaluation_model import ( - EvaluationStatusEnum, +from agenta_backend.services import ( + evaluators_service, + llm_apps_service, + deployment_manager, + aggregation_service, ) +from agenta_backend.models.api.evaluation_model import EvaluationStatusEnum from agenta_backend.models.db_models import ( AggregatedResult, AppDB, + CorrectAnswer, EvaluationScenarioInputDB, EvaluationScenarioOutputDB, EvaluationScenarioResult, @@ -24,12 +27,6 @@ Error, Result, ) -from agenta_backend.services import ( - evaluators_service, - llm_apps_service, - deployment_manager, - aggregation_service, -) from agenta_backend.services.db_manager import ( create_new_evaluation_scenario, fetch_app_by_id, @@ -43,23 +40,28 @@ EvaluationScenarioResult, check_if_evaluation_contains_failed_evaluation_scenarios, ) +from agenta_backend.services.evaluator_manager import get_evaluators if isCloudEE(): from agenta_backend.commons.models.db_models import AppDB_ as AppDB else: from agenta_backend.models.db_models import AppDB -from agenta_backend.models.db_models import ( - Result, - AggregatedResult, - EvaluationScenarioResult, - EvaluationScenarioInputDB, - EvaluationScenarioOutputDB, -) # Set logger logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) +# Fetch all evaluators and precompute ground truth keys +all_evaluators = get_evaluators() +ground_truth_keys_dict = { + evaluator["key"]: [ + key + for key, value in evaluator.get("settings_template", {}).items() + if value.get("ground_truth_key") is True + ] + for evaluator in all_evaluators +} + @shared_task(queue="agenta_backend.tasks.evaluations.evaluate", bind=True) def evaluate( @@ -71,19 +73,19 @@ def evaluate( evaluation_id: str, rate_limit_config: Dict[str, int], lm_providers_keys: Dict[str, Any], - correct_answer_column: str, ): """ - Evaluate function that performs the evaluation of an app variant using the provided evaluators and testset. - Saves the results in the Database + Evaluates an app variant using the provided evaluators and testset, and saves the results in the database. Args: + self: The task instance. app_id (str): The ID of the app. variant_id (str): The ID of the app variant. evaluators_config_ids (List[str]): The IDs of the evaluators configurations to be used. testset_id (str): The ID of the testset. - rate_limit_config (Dict[str,int]): See LLMRunRateLimit - correct_answer_column (str): The name of the column in the testset that contains the correct answer. + evaluation_id (str): The ID of the evaluation. + rate_limit_config (Dict[str, int]): Configuration for rate limiting. + lm_providers_keys (Dict[str, Any]): Keys for language model providers. Returns: None @@ -178,11 +180,6 @@ def evaluate( ) for evaluator_config_db in evaluator_config_dbs ] - correct_answer = ( - data_point[correct_answer_column] - if correct_answer_column in data_point - else "" - ) loop.run_until_complete( create_new_evaluation_scenario( @@ -195,7 +192,7 @@ def evaluate( inputs=inputs, is_pinned=False, note="", - correct_answer=correct_answer, + correct_answer=None, outputs=[ EvaluationScenarioOutputDB( result=Result( @@ -214,27 +211,29 @@ def evaluate( continue # 3. We evaluate - evaluators_results: [EvaluationScenarioResult] = [] + evaluators_results: List[EvaluationScenarioResult] = [] + + # Loop over each evaluator configuration to gather the correct answers and evaluate + ground_truth_column_names = [] for evaluator_config_db in evaluator_config_dbs: + ground_truth_keys = ground_truth_keys_dict.get( + evaluator_config_db.evaluator_key, [] + ) + ground_truth_column_names.extend( + evaluator_config_db.settings_values.get(key, "") + for key in ground_truth_keys + ) logger.debug(f"Evaluating with evaluator: {evaluator_config_db}") - if correct_answer_column in data_point: - result = evaluators_service.evaluate( - evaluator_key=evaluator_config_db.evaluator_key, - output=app_output.result.value, - correct_answer=data_point[correct_answer_column], - settings_values=evaluator_config_db.settings_values, - app_params=app_variant_parameters, - inputs=data_point, - lm_providers_keys=lm_providers_keys, - ) - else: - result = Result( - type="error", - value=None, - error=Error( - message=f"No {correct_answer_column} column in test set" - ), - ) + + result = evaluators_service.evaluate( + evaluator_key=evaluator_config_db.evaluator_key, + output=app_output.result.value, + data_point=data_point, + settings_values=evaluator_config_db.settings_values, + app_params=app_variant_parameters, + inputs=data_point, + lm_providers_keys=lm_providers_keys, + ) # Update evaluators aggregated data evaluator_results: List[Result] = evaluators_aggregated_data[ @@ -249,12 +248,17 @@ def evaluate( logger.debug(f"Result: {result_object}") evaluators_results.append(result_object) + all_correct_answers = [ + CorrectAnswer( + key=ground_truth_column_name, + value=data_point[ground_truth_column_name], + ) + if ground_truth_column_name in data_point + else CorrectAnswer(key=ground_truth_column_name, value="") + for ground_truth_column_name in ground_truth_column_names + ] # 4. We save the result of the eval scenario in the db - correct_answer = ( - data_point[correct_answer_column] - if correct_answer_column in data_point - else "" - ) + loop.run_until_complete( create_new_evaluation_scenario( user=app.user, @@ -264,7 +268,7 @@ def evaluate( inputs=inputs, is_pinned=False, note="", - correct_answer=correct_answer, + correct_answers=all_correct_answers, outputs=[ EvaluationScenarioOutputDB( result=Result(type="text", value=app_output.result.value), diff --git a/agenta-backend/agenta_backend/tests/unit/test_evaluators.py b/agenta-backend/agenta_backend/tests/unit/test_evaluators.py index f76dd9e6fb..ff70bbfd9b 100644 --- a/agenta-backend/agenta_backend/tests/unit/test_evaluators.py +++ b/agenta-backend/agenta_backend/tests/unit/test_evaluators.py @@ -12,17 +12,54 @@ @pytest.mark.parametrize( - "output, prefix, case_sensitive, expected", + "output, settings_values, expected", [ - ("Hello world", "He", True, True), - ("hello world", "He", False, True), - ("Hello world", "he", False, True), - ("Hello world", "world", True, False), + ( + "Hello world", + { + "prefix": "He", + "case_sensitive": True, + "correct_answer_keys": ["correct_answer"], + }, + True, + ), + ( + "hello world", + { + "prefix": "He", + "case_sensitive": False, + "correct_answer_keys": ["correct_answer"], + }, + True, + ), + ( + "Hello world", + { + "prefix": "he", + "case_sensitive": False, + "correct_answer_keys": ["correct_answer"], + }, + True, + ), + ( + "Hello world", + { + "prefix": "world", + "case_sensitive": True, + "correct_answer_keys": ["correct_answer"], + }, + False, + ), ], ) -def test_auto_starts_with(output, prefix, case_sensitive, expected): +def test_auto_starts_with(output, settings_values, expected): result = auto_starts_with( - {}, output, "", {}, {"prefix": prefix, "case_sensitive": case_sensitive}, {} + inputs={}, + output=output, + data_point={}, + app_params={}, + settings_values=settings_values, + lm_providers_keys={}, ) assert result.value == expected @@ -41,7 +78,12 @@ def test_auto_starts_with(output, prefix, case_sensitive, expected): ) def test_auto_ends_with(output, suffix, case_sensitive, expected): result = auto_ends_with( - {}, output, "", {}, {"suffix": suffix, "case_sensitive": case_sensitive}, {} + {}, + output, + {}, + {}, + {"suffix": suffix, "case_sensitive": case_sensitive}, + {}, ) assert result.value == expected @@ -61,7 +103,7 @@ def test_auto_contains(output, substring, case_sensitive, expected): result = auto_contains( {}, output, - "", + {}, {}, {"substring": substring, "case_sensitive": case_sensitive}, {}, @@ -85,7 +127,7 @@ def test_auto_contains_any(output, substrings, case_sensitive, expected): result = auto_contains_any( {}, output, - "", + {}, {}, {"substrings": substrings, "case_sensitive": case_sensitive}, {}, @@ -109,7 +151,7 @@ def test_auto_contains_all(output, substrings, case_sensitive, expected): result = auto_contains_all( {}, output, - "", + {}, {}, {"substrings": substrings, "case_sensitive": case_sensitive}, {}, @@ -128,24 +170,58 @@ def test_auto_contains_all(output, substrings, case_sensitive, expected): ], ) def test_auto_contains_json(output, expected): - result = auto_contains_json({}, output, "", {}, {}, {}) + result = auto_contains_json({}, output, {}, {}, {}, {}) assert result.value == expected @pytest.mark.parametrize( - "output, correct_answer, threshold, expected", + "output, data_point, settings_values, expected", [ - ("hello world", "hello world", 5, True), - ("hello world", "hola mundo", 5, False), - ("hello world", "hello world!", 2, True), - ("hello world", "hello wor", 10, True), - ("hello world", "hello worl", None, 1), - ("hello world", "helo world", None, 1), + ( + "hello world", + {"correct_answer": "hello world"}, + {"threshold": 5, "correct_answer_key": "correct_answer"}, + True, + ), + ( + "hello world", + {"correct_answer": "hola mundo"}, + {"threshold": 5, "correct_answer_key": "correct_answer"}, + False, + ), + ( + "hello world", + {"correct_answer": "hello world!"}, + {"threshold": 2, "correct_answer_key": "correct_answer"}, + True, + ), + ( + "hello world", + {"correct_answer": "hello wor"}, + {"threshold": 10, "correct_answer_key": "correct_answer"}, + True, + ), + ( + "hello world", + {"correct_answer": "hello worl"}, + {"correct_answer_key": "correct_answer"}, + 1, + ), + ( + "hello world", + {"correct_answer": "helo world"}, + {"correct_answer_key": "correct_answer"}, + 1, + ), ], ) -def test_auto_levenshtein_distance(output, correct_answer, threshold, expected): - settings_values = {"threshold": threshold} if threshold is not None else {} +def test_auto_levenshtein_distance(output, data_point, settings_values, expected): result = auto_levenshtein_distance( - {}, output, correct_answer, {}, settings_values, {} + inputs={}, + output=output, + data_point=data_point, + app_params={}, + settings_values=settings_values, + lm_providers_keys={}, ) assert result.value == expected diff --git a/agenta-backend/agenta_backend/tests/variants_main_router/test_variant_evaluators_router.py b/agenta-backend/agenta_backend/tests/variants_main_router/test_variant_evaluators_router.py index e45b17fbda..9ff8ad60b2 100644 --- a/agenta-backend/agenta_backend/tests/variants_main_router/test_variant_evaluators_router.py +++ b/agenta-backend/agenta_backend/tests/variants_main_router/test_variant_evaluators_router.py @@ -59,6 +59,7 @@ async def test_create_auto_exact_match_evaluator_config( app = await AppDB.find_one(AppDB.app_name == APP_NAME) payload = auto_exact_match_evaluator_config payload["app_id"] = str(app.id) + payload["settings_values"]["correct_answer_key"] = "correct_answer" response = await test_client.post( f"{BACKEND_API_HOST}/evaluators/configs/", json=payload, timeout=timeout @@ -75,6 +76,7 @@ async def test_create_auto_similarity_match_evaluator_config( app = await AppDB.find_one(AppDB.app_name == APP_NAME) payload = auto_similarity_match_evaluator_config payload["app_id"] = str(app.id) + payload["settings_values"]["correct_answer_key"] = "correct_answer" response = await test_client.post( f"{BACKEND_API_HOST}/evaluators/configs/", json=payload, timeout=timeout @@ -92,6 +94,7 @@ async def test_create_auto_regex_test_evaluator_config( payload = auto_regex_test_evaluator_config payload["app_id"] = str(app.id) payload["settings_values"]["regex_pattern"] = "^ig\\d{3}$" + payload["settings_values"]["correct_answer_key"] = "correct_answer" response = await test_client.post( f"{BACKEND_API_HOST}/evaluators/configs/", json=payload, timeout=timeout @@ -108,6 +111,7 @@ async def test_create_auto_webhook_test_evaluator_config( app = await AppDB.find_one(AppDB.app_name == APP_NAME) payload = auto_webhook_test_evaluator_config payload["app_id"] = str(app.id) + payload["settings_values"]["correct_answer_key"] = "correct_answer" response = await test_client.post( f"{BACKEND_API_HOST}/evaluators/configs/", json=payload, timeout=timeout @@ -124,6 +128,7 @@ async def test_create_auto_ai_critique_evaluator_config( app = await AppDB.find_one(AppDB.app_name == APP_NAME) payload = auto_ai_critique_evaluator_config payload["app_id"] = str(app.id) + payload["settings_values"]["correct_answer_key"] = "correct_answer" response = await test_client.post( f"{BACKEND_API_HOST}/evaluators/configs/", json=payload, timeout=timeout @@ -145,7 +150,31 @@ async def test_get_evaluator_configs(): @pytest.mark.asyncio -async def test_create_evaluation(): +async def test_create_evaluation_auto_exact_match(): + await create_evaluation_with_evaluator("auto_exact_match_evaluator_config") + + +@pytest.mark.asyncio +async def test_create_evaluation_auto_similarity_match(): + await create_evaluation_with_evaluator("auto_similarity_match_evaluator_config") + + +@pytest.mark.asyncio +async def test_create_evaluation_auto_regex_test(): + await create_evaluation_with_evaluator("auto_regex_test_evaluator_config") + + +@pytest.mark.asyncio +async def test_create_evaluation_auto_webhook_test(): + await create_evaluation_with_evaluator("auto_webhook_test_evaluator_config") + + +@pytest.mark.asyncio +async def test_create_evaluation_auto_ai_critique(): + await create_evaluation_with_evaluator("auto_ai_critique_evaluator_config") + + +async def create_evaluation_with_evaluator(evaluator_config_name): # Fetch app, app_variant and testset app = await AppDB.find_one(AppDB.app_name == APP_NAME) app_variant = await AppVariantDB.find_one(AppVariantDB.app.id == app.id) @@ -174,7 +203,8 @@ async def test_create_evaluation(): list_of_configs_ids = [] evaluator_configs = response.json() for evaluator_config in evaluator_configs: - list_of_configs_ids.append(evaluator_config["id"]) + if evaluator_config["evaluator_key"] == evaluator_config_name: + list_of_configs_ids.append(evaluator_config["id"]) # Update payload with list of configs ids payload["evaluators_configs"] = list_of_configs_ids @@ -196,20 +226,20 @@ async def test_create_evaluation(): ) assert response_data is not None + # Wait for evaluation to finish + evaluation_id = response_data["id"] + await wait_for_evaluation_to_finish(evaluation_id) + + # Fetch evaluation results + await fetch_evaluation_results(evaluation_id) -@pytest.mark.asyncio -async def test_fetch_evaluation_status(): - evaluations = ( - await EvaluationDB.find().to_list() - ) # will return only one in this case - evaluation = evaluations[0] - # Prepare and start short-polling request +async def wait_for_evaluation_to_finish(evaluation_id): max_attempts = 12 intervals = 5 # seconds for _ in range(max_attempts): response = await test_client.get( - f"{BACKEND_API_HOST}/evaluations/{str(evaluation.id)}/status/", + f"{BACKEND_API_HOST}/evaluations/{evaluation_id}/status/", timeout=timeout, ) response_data = response.json() @@ -223,21 +253,14 @@ async def test_fetch_evaluation_status(): ), f"Evaluation status did not become '{EvaluationStatusEnum.EVALUATION_FINISHED}' within the specified polling time" -@pytest.mark.asyncio -async def test_fetch_evaluation_results(): - evaluations = ( - await EvaluationDB.find().to_list() - ) # will return only one in this case - evaluation = evaluations[0] - +async def fetch_evaluation_results(evaluation_id): response = await test_client.get( - f"{BACKEND_API_HOST}/evaluations/{str(evaluation.id)}/results/", timeout=timeout + f"{BACKEND_API_HOST}/evaluations/{evaluation_id}/results/", timeout=timeout ) response_data = response.json() assert response.status_code == 200 - assert response_data["evaluation_id"] == str(evaluation.id) - assert len(response_data["results"]) == 7 + assert response_data["evaluation_id"] == evaluation_id @pytest.mark.asyncio diff --git a/agenta-backend/poetry.lock b/agenta-backend/poetry.lock index 468b8ca1e6..09fe882771 100644 --- a/agenta-backend/poetry.lock +++ b/agenta-backend/poetry.lock @@ -1,9 +1,10 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. [[package]] name = "aioboto3" version = "12.4.0" description = "Async boto3 wrapper" +category = "main" optional = false python-versions = "<4.0,>=3.8" files = [ @@ -22,6 +23,7 @@ s3cse = ["cryptography (>=2.3.1)"] name = "aiobotocore" version = "2.12.3" description = "Async client for aws services using botocore and aiohttp" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -44,6 +46,7 @@ boto3 = ["boto3 (>=1.34.41,<1.34.70)"] name = "aiodocker" version = "0.21.0" description = "Docker API client for asyncio" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -59,6 +62,7 @@ typing-extensions = ">=3.6.5" name = "aiohttp" version = "3.9.5" description = "Async http client/server framework (asyncio)" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -155,6 +159,7 @@ speedups = ["Brotli", "aiodns", "brotlicffi"] name = "aioitertools" version = "0.11.0" description = "itertools and builtins for AsyncIO and mixed iterables" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -169,6 +174,7 @@ typing_extensions = {version = ">=4.0", markers = "python_version < \"3.10\""} name = "aiosignal" version = "1.3.1" description = "aiosignal: a list of registered asynchronous callbacks" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -183,6 +189,7 @@ frozenlist = ">=1.1.0" name = "aiosmtplib" version = "1.1.6" description = "asyncio SMTP client" +category = "main" optional = false python-versions = ">=3.5.2,<4.0.0" files = [ @@ -198,6 +205,7 @@ uvloop = ["uvloop (>=0.13,<0.15)"] name = "amqp" version = "5.2.0" description = "Low-level AMQP client for Python (fork of amqplib)." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -212,6 +220,7 @@ vine = ">=5.0.0,<6.0.0" name = "anyio" version = "3.7.1" description = "High level compatibility layer for multiple asynchronous event loop implementations" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -229,10 +238,23 @@ doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd- test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] trio = ["trio (<0.22)"] +[[package]] +name = "appdirs" +version = "1.4.4" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, + {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, +] + [[package]] name = "asgiref" version = "3.8.1" description = "ASGI specs, helper code, and adapters" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -250,6 +272,7 @@ tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] name = "async-timeout" version = "4.0.3" description = "Timeout context manager for asyncio programs" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -261,6 +284,7 @@ files = [ name = "asyncer" version = "0.0.2" description = "Asyncer, async and await, focused on developer experience." +category = "main" optional = false python-versions = ">=3.6.2,<4.0.0" files = [ @@ -275,6 +299,7 @@ anyio = ">=3.4.0,<4.0.0" name = "attrs" version = "23.2.0" description = "Classes Without Boilerplate" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -294,6 +319,7 @@ tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "p name = "backoff" version = "2.2.1" description = "Function decoration for backoff and retry" +category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -305,6 +331,7 @@ files = [ name = "beanie" version = "1.26.0" description = "Asynchronous Python ODM for MongoDB" +category = "main" optional = false python-versions = "<4.0,>=3.7" files = [ @@ -329,6 +356,7 @@ test = ["asgi-lifespan (>=1.0.1)", "dnspython (>=2.1.0)", "fastapi (>=0.100)", " name = "billiard" version = "4.2.0" description = "Python multiprocessing fork with improvements and bugfixes" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -340,6 +368,7 @@ files = [ name = "boto3" version = "1.34.69" description = "The AWS SDK for Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -359,6 +388,7 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] name = "botocore" version = "1.34.69" description = "Low-level, data-driven core of boto 3." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -381,6 +411,7 @@ crt = ["awscrt (==0.19.19)"] name = "cachetools" version = "5.3.3" description = "Extensible memoizing collections and decorators" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -392,6 +423,7 @@ files = [ name = "celery" version = "5.4.0" description = "Distributed Task Queue." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -448,6 +480,7 @@ zstd = ["zstandard (==0.22.0)"] name = "certifi" version = "2024.2.2" description = "Python package for providing Mozilla's CA Bundle." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -459,6 +492,7 @@ files = [ name = "cffi" version = "1.16.0" description = "Foreign Function Interface for Python calling C code." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -523,6 +557,7 @@ pycparser = "*" name = "charset-normalizer" version = "3.3.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -622,6 +657,7 @@ files = [ name = "click" version = "8.1.7" description = "Composable command line interface toolkit" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -636,6 +672,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "click-didyoumean" version = "0.3.1" description = "Enables git-like *did-you-mean* feature in click" +category = "main" optional = false python-versions = ">=3.6.2" files = [ @@ -650,6 +687,7 @@ click = ">=7" name = "click-plugins" version = "1.1.1" description = "An extension module for click to enable registering CLI commands via setuptools entry-points." +category = "main" optional = false python-versions = "*" files = [ @@ -667,6 +705,7 @@ dev = ["coveralls", "pytest (>=3.6)", "pytest-cov", "wheel"] name = "click-repl" version = "0.3.0" description = "REPL plugin for Click" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -685,6 +724,7 @@ testing = ["pytest (>=7.2.1)", "pytest-cov (>=4.0.0)", "tox (>=4.4.3)"] name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -696,6 +736,7 @@ files = [ name = "cryptography" version = "42.0.7" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -750,6 +791,7 @@ test-randomorder = ["pytest-randomly"] name = "dataclasses-json" version = "0.6.6" description = "Easily serialize dataclasses to and from JSON." +category = "main" optional = false python-versions = "<4.0,>=3.7" files = [ @@ -761,10 +803,56 @@ files = [ marshmallow = ">=3.18.0,<4.0.0" typing-inspect = ">=0.4.0,<1" +[[package]] +name = "datasets" +version = "2.19.1" +description = "HuggingFace community-driven open-source library of datasets" +category = "main" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "datasets-2.19.1-py3-none-any.whl", hash = "sha256:f7a78d15896f45004ccac1c298f3c7121f92f91f6f2bfbd4e4f210f827e6e411"}, + {file = "datasets-2.19.1.tar.gz", hash = "sha256:0df9ef6c5e9138cdb996a07385220109ff203c204245578b69cca905eb151d3a"}, +] + +[package.dependencies] +aiohttp = "*" +dill = ">=0.3.0,<0.3.9" +filelock = "*" +fsspec = {version = ">=2023.1.0,<=2024.3.1", extras = ["http"]} +huggingface-hub = ">=0.21.2" +multiprocess = "*" +numpy = ">=1.17" +packaging = "*" +pandas = "*" +pyarrow = ">=12.0.0" +pyarrow-hotfix = "*" +pyyaml = ">=5.1" +requests = ">=2.19.0" +tqdm = ">=4.62.1" +xxhash = "*" + +[package.extras] +apache-beam = ["apache-beam (>=2.26.0)"] +audio = ["librosa", "soundfile (>=0.12.1)"] +benchmarks = ["tensorflow (==2.12.0)", "torch (==2.0.1)", "transformers (==4.30.1)"] +dev = ["Pillow (>=6.2.1)", "absl-py", "apache-beam (>=2.26.0)", "elasticsearch (<8.0.0)", "faiss-cpu (>=1.6.4)", "jax (>=0.3.14)", "jaxlib (>=0.3.14)", "joblib (<1.3.0)", "joblibspark", "librosa", "lz4", "polars[timezone] (>=0.20.0)", "protobuf (<4.0.0)", "py7zr", "pyspark (>=3.4)", "pytest", "pytest-datadir", "pytest-xdist", "rarfile (>=4.0)", "ruff (>=0.3.0)", "s3fs", "s3fs (>=2021.11.1)", "soundfile (>=0.12.1)", "sqlalchemy", "tensorflow (>=2.6.0)", "tiktoken", "torch", "torch (>=2.0.0)", "transformers", "typing-extensions (>=4.6.1)", "zstandard"] +docs = ["s3fs", "tensorflow (>=2.6.0)", "torch", "transformers"] +jax = ["jax (>=0.3.14)", "jaxlib (>=0.3.14)"] +metrics-tests = ["Werkzeug (>=1.0.1)", "accelerate", "bert-score (>=0.3.6)", "jiwer", "langdetect", "mauve-text", "nltk", "requests-file (>=1.5.1)", "rouge-score", "sacrebleu", "sacremoses", "scikit-learn", "scipy", "sentencepiece", "seqeval", "six (>=1.15.0,<1.16.0)", "spacy (>=3.0.0)", "texttable (>=1.6.3)", "tldextract", "tldextract (>=3.1.0)", "toml (>=0.10.1)", "typer (<0.5.0)"] +quality = ["ruff (>=0.3.0)"] +s3 = ["s3fs"] +tensorflow = ["tensorflow (>=2.6.0)"] +tensorflow-gpu = ["tensorflow (>=2.6.0)"] +tests = ["Pillow (>=6.2.1)", "absl-py", "apache-beam (>=2.26.0)", "elasticsearch (<8.0.0)", "faiss-cpu (>=1.6.4)", "jax (>=0.3.14)", "jaxlib (>=0.3.14)", "joblib (<1.3.0)", "joblibspark", "librosa", "lz4", "polars[timezone] (>=0.20.0)", "protobuf (<4.0.0)", "py7zr", "pyspark (>=3.4)", "pytest", "pytest-datadir", "pytest-xdist", "rarfile (>=4.0)", "s3fs (>=2021.11.1)", "soundfile (>=0.12.1)", "sqlalchemy", "tensorflow (>=2.6.0)", "tiktoken", "torch (>=2.0.0)", "transformers", "typing-extensions (>=4.6.1)", "zstandard"] +torch = ["torch"] +vision = ["Pillow (>=6.2.1)"] + [[package]] name = "deprecated" version = "1.2.13" description = "Python @deprecated decorator to deprecate old python classes, functions or methods." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -778,10 +866,39 @@ wrapt = ">=1.10,<2" [package.extras] dev = ["PyTest", "PyTest (<5)", "PyTest-Cov", "PyTest-Cov (<2.6)", "bump2version (<1)", "configparser (<5)", "importlib-metadata (<3)", "importlib-resources (<4)", "sphinx (<2)", "sphinxcontrib-websupport (<2)", "tox", "zipp (<2)"] +[[package]] +name = "dill" +version = "0.3.8" +description = "serialize all of Python" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"}, + {file = "dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca"}, +] + +[package.extras] +graph = ["objgraph (>=1.7.2)"] +profile = ["gprof2dot (>=2022.7.29)"] + +[[package]] +name = "distro" +version = "1.9.0" +description = "Distro - an OS platform information API" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, + {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, +] + [[package]] name = "dnspython" version = "2.6.1" description = "DNS toolkit" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -800,29 +917,32 @@ wmi = ["wmi (>=1.5.1)"] [[package]] name = "docker" -version = "6.1.3" +version = "7.1.0" description = "A Python library for the Docker Engine API." +category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "docker-6.1.3-py3-none-any.whl", hash = "sha256:aecd2277b8bf8e506e484f6ab7aec39abe0038e29fa4a6d3ba86c3fe01844ed9"}, - {file = "docker-6.1.3.tar.gz", hash = "sha256:aa6d17830045ba5ef0168d5eaa34d37beeb113948c413affe1d5991fc11f9a20"}, + {file = "docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0"}, + {file = "docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c"}, ] [package.dependencies] -packaging = ">=14.0" pywin32 = {version = ">=304", markers = "sys_platform == \"win32\""} requests = ">=2.26.0" urllib3 = ">=1.26.0" -websocket-client = ">=0.32.0" [package.extras] +dev = ["coverage (==7.2.7)", "pytest (==7.4.2)", "pytest-cov (==4.1.0)", "pytest-timeout (==2.1.0)", "ruff (==0.1.8)"] +docs = ["myst-parser (==0.18.0)", "sphinx (==5.1.1)"] ssh = ["paramiko (>=2.4.3)"] +websockets = ["websocket-client (>=1.3.0)"] [[package]] name = "exceptiongroup" version = "1.2.1" description = "Backport of PEP 654 (exception groups)" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -837,6 +957,7 @@ test = ["pytest (>=6)"] name = "faker" version = "23.3.0" description = "Faker is a Python package that generates fake data for you." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -851,6 +972,7 @@ python-dateutil = ">=2.4" name = "fastapi" version = "0.109.2" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -870,6 +992,7 @@ all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)" name = "filelock" version = "3.14.0" description = "A platform independent file lock." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -886,6 +1009,7 @@ typing = ["typing-extensions (>=4.8)"] name = "frozenlist" version = "1.4.1" description = "A list-like structure which implements collections.abc.MutableSequence" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -968,10 +1092,50 @@ files = [ {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, ] +[[package]] +name = "fsspec" +version = "2024.3.1" +description = "File-system specification" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fsspec-2024.3.1-py3-none-any.whl", hash = "sha256:918d18d41bf73f0e2b261824baeb1b124bcf771767e3a26425cd7dec3332f512"}, + {file = "fsspec-2024.3.1.tar.gz", hash = "sha256:f39780e282d7d117ffb42bb96992f8a90795e4d0fb0f661a70ca39fe9c43ded9"}, +] + +[package.dependencies] +aiohttp = {version = "<4.0.0a0 || >4.0.0a0,<4.0.0a1 || >4.0.0a1", optional = true, markers = "extra == \"http\""} + +[package.extras] +abfs = ["adlfs"] +adl = ["adlfs"] +arrow = ["pyarrow (>=1)"] +dask = ["dask", "distributed"] +devel = ["pytest", "pytest-cov"] +dropbox = ["dropbox", "dropboxdrivefs", "requests"] +full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] +fuse = ["fusepy"] +gcs = ["gcsfs"] +git = ["pygit2"] +github = ["requests"] +gs = ["gcsfs"] +gui = ["panel"] +hdfs = ["pyarrow (>=1)"] +http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)"] +libarchive = ["libarchive-c"] +oci = ["ocifs"] +s3 = ["s3fs"] +sftp = ["paramiko"] +smb = ["smbprotocol"] +ssh = ["paramiko"] +tqdm = ["tqdm"] + [[package]] name = "google-auth" version = "2.29.0" description = "Google Authentication Library" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -995,6 +1159,7 @@ requests = ["requests (>=2.20.0,<3.0.0.dev0)"] name = "greenlet" version = "3.0.3" description = "Lightweight in-process concurrent programming" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1066,6 +1231,7 @@ test = ["objgraph", "psutil"] name = "h11" version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1077,6 +1243,7 @@ files = [ name = "httpcore" version = "0.17.3" description = "A minimal low-level HTTP client." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1088,16 +1255,17 @@ files = [ anyio = ">=3.0,<5.0" certifi = "*" h11 = ">=0.13,<0.15" -sniffio = "==1.*" +sniffio = ">=1.0.0,<2.0.0" [package.extras] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] [[package]] name = "httpx" version = "0.24.1" description = "The next generation HTTP client." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1113,14 +1281,50 @@ sniffio = "*" [package.extras] brotli = ["brotli", "brotlicffi"] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +cli = ["click (>=8.0.0,<9.0.0)", "pygments (>=2.0.0,<3.0.0)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] + +[[package]] +name = "huggingface-hub" +version = "0.23.2" +description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" +category = "main" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "huggingface_hub-0.23.2-py3-none-any.whl", hash = "sha256:48727a16e704d409c4bb5913613308499664f22a99743435dc3a13b23c485827"}, + {file = "huggingface_hub-0.23.2.tar.gz", hash = "sha256:f6829b62d5fdecb452a76fdbec620cba4c1573655a8d710c1df71735fd9edbd2"}, +] + +[package.dependencies] +filelock = "*" +fsspec = ">=2023.5.0" +packaging = ">=20.9" +pyyaml = ">=5.1" +requests = "*" +tqdm = ">=4.42.1" +typing-extensions = ">=3.7.4.3" + +[package.extras] +all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +cli = ["InquirerPy (==0.3.4)"] +dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"] +hf-transfer = ["hf-transfer (>=0.1.4)"] +inference = ["aiohttp", "minijinja (>=1.0)"] +quality = ["mypy (==1.5.1)", "ruff (>=0.3.0)"] +tensorflow = ["graphviz", "pydot", "tensorflow"] +tensorflow-testing = ["keras (<3.0)", "tensorflow"] +testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] +torch = ["safetensors", "torch"] +typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"] [[package]] name = "idna" version = "3.7" description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1132,6 +1336,7 @@ files = [ name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1143,6 +1348,7 @@ files = [ name = "jmespath" version = "1.0.1" description = "JSON Matching Expressions" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1154,6 +1360,7 @@ files = [ name = "jsonpatch" version = "1.33" description = "Apply JSON-Patches (RFC 6902)" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ @@ -1168,6 +1375,7 @@ jsonpointer = ">=1.9" name = "jsonpointer" version = "2.4" description = "Identify specific nodes in a JSON document (RFC 6901)" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ @@ -1179,6 +1387,7 @@ files = [ name = "kombu" version = "5.3.7" description = "Messaging library for Python." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1212,6 +1421,7 @@ zookeeper = ["kazoo (>=2.8.0)"] name = "kubernetes" version = "28.1.0" description = "Kubernetes python client" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1229,29 +1439,29 @@ requests = "*" requests-oauthlib = "*" six = ">=1.9.0" urllib3 = ">=1.24.2,<2.0" -websocket-client = ">=0.32.0,<0.40.0 || >0.40.0,<0.41.dev0 || >=0.43.dev0" +websocket-client = ">=0.32.0,<0.40.0 || >0.40.0,<0.41.0 || >=0.43.0" [package.extras] adal = ["adal (>=1.0.2)"] [[package]] name = "langchain" -version = "0.0.329" +version = "0.2.1" description = "Building applications with LLMs through composability" +category = "main" optional = false -python-versions = ">=3.8.1,<4.0" +python-versions = "<4.0,>=3.8.1" files = [ - {file = "langchain-0.0.329-py3-none-any.whl", hash = "sha256:5f3e884991271e8b55eda4c63a11105dcd7da119682ce0e3d5d1385b3a4103d2"}, - {file = "langchain-0.0.329.tar.gz", hash = "sha256:488f3cb68a587696f136d4f01f97df8d8270e295b3cc56158057dab0f61f4166"}, + {file = "langchain-0.2.1-py3-none-any.whl", hash = "sha256:3e13bf97c5717bce2c281f5117e8778823e8ccf62d949e73d3869448962b1c97"}, + {file = "langchain-0.2.1.tar.gz", hash = "sha256:5758a315e1ac92eb26dafec5ad0fafa03cafa686aba197d5bb0b1dd28cc03ebe"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" -anyio = "<4.0" async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""} -dataclasses-json = ">=0.5.7,<0.7" -jsonpatch = ">=1.33,<2.0" -langsmith = ">=0.0.52,<0.1.0" +langchain-core = ">=0.2.0,<0.3.0" +langchain-text-splitters = ">=0.2.0,<0.3.0" +langsmith = ">=0.1.17,<0.2.0" numpy = ">=1,<2" pydantic = ">=1,<3" PyYAML = ">=5.3" @@ -1260,32 +1470,119 @@ SQLAlchemy = ">=1.4,<3" tenacity = ">=8.1.0,<9.0.0" [package.extras] -all = ["O365 (>=2.0.26,<3.0.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "amadeus (>=8.1.0)", "arxiv (>=1.4,<2.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "awadb (>=0.3.9,<0.4.0)", "azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-vision (>=0.11.1b1,<0.12.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "beautifulsoup4 (>=4,<5)", "clarifai (>=9.1.0)", "clickhouse-connect (>=0.5.14,<0.6.0)", "cohere (>=4,<5)", "deeplake (>=3.8.3,<4.0.0)", "docarray[hnswlib] (>=0.32.0,<0.33.0)", "duckduckgo-search (>=3.8.3,<4.0.0)", "elasticsearch (>=8,<9)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "google-api-python-client (==2.70.0)", "google-auth (>=2.18.1,<3.0.0)", "google-search-results (>=2,<3)", "gptcache (>=0.1.7)", "html2text (>=2020.1.16,<2021.0.0)", "huggingface_hub (>=0,<1)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "lancedb (>=0.1,<0.2)", "langkit (>=0.0.6,<0.1.0)", "lark (>=1.1.5,<2.0.0)", "librosa (>=0.10.0.post2,<0.11.0)", "lxml (>=4.9.2,<5.0.0)", "manifest-ml (>=0.0.1,<0.0.2)", "marqo (>=1.2.4,<2.0.0)", "momento (>=1.10.1,<2.0.0)", "nebula3-python (>=3.4.0,<4.0.0)", "neo4j (>=5.8.1,<6.0.0)", "networkx (>=2.6.3,<4)", "nlpcloud (>=1,<2)", "nltk (>=3,<4)", "nomic (>=1.0.43,<2.0.0)", "openai (>=0,<1)", "openlm (>=0.0.5,<0.0.6)", "opensearch-py (>=2.0.0,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pexpect (>=4.8.0,<5.0.0)", "pgvector (>=0.1.6,<0.2.0)", "pinecone-client (>=2,<3)", "pinecone-text (>=0.4.2,<0.5.0)", "psycopg2-binary (>=2.9.5,<3.0.0)", "pymongo (>=4.3.3,<5.0.0)", "pyowm (>=3.3.0,<4.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pytesseract (>=0.3.10,<0.4.0)", "python-arango (>=7.5.9,<8.0.0)", "pyvespa (>=0.33.0,<0.34.0)", "qdrant-client (>=1.3.1,<2.0.0)", "rdflib (>=6.3.2,<7.0.0)", "redis (>=4,<5)", "requests-toolbelt (>=1.0.0,<2.0.0)", "sentence-transformers (>=2,<3)", "singlestoredb (>=0.7.1,<0.8.0)", "tensorflow-text (>=2.11.0,<3.0.0)", "tigrisdb (>=1.0.0b6,<2.0.0)", "tiktoken (>=0.3.2,<0.6.0)", "torch (>=1,<3)", "transformers (>=4,<5)", "weaviate-client (>=3,<4)", "wikipedia (>=1,<2)", "wolframalpha (==5.0.0)"] -azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-vision (>=0.11.1b1,<0.12.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b8)", "openai (>=0,<1)"] +azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-textanalytics (>=5.3.0,<6.0.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b8)", "openai (<2)"] clarifai = ["clarifai (>=9.1.0)"] cli = ["typer (>=0.9.0,<0.10.0)"] -cohere = ["cohere (>=4,<5)"] +cohere = ["cohere (>=4,<6)"] docarray = ["docarray[hnswlib] (>=0.32.0,<0.33.0)"] embeddings = ["sentence-transformers (>=2,<3)"] -extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "dashvector (>=1.0.1,<2.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.6.0,<0.7.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "html2text (>=2020.1.16,<2021.0.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (>=0,<1)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] +extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<6)", "couchbase (>=4.1.9,<5.0.0)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "langchain-openai (>=0.1,<0.2)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] javascript = ["esprima (>=4.0.1,<5.0.0)"] -llms = ["clarifai (>=9.1.0)", "cohere (>=4,<5)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (>=0,<1)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] -openai = ["openai (>=0,<1)", "tiktoken (>=0.3.2,<0.6.0)"] +llms = ["clarifai (>=9.1.0)", "cohere (>=4,<6)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (<2)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] +openai = ["openai (<2)", "tiktoken (>=0.7,<1.0)"] qdrant = ["qdrant-client (>=1.3.1,<2.0.0)"] text-helpers = ["chardet (>=5.1.0,<6.0.0)"] +[[package]] +name = "langchain-community" +version = "0.2.1" +description = "Community contributed LangChain integrations." +category = "main" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_community-0.2.1-py3-none-any.whl", hash = "sha256:b834e2c5ded6903b839fcaf566eee90a0ffae53405a0f7748202725e701d39cd"}, + {file = "langchain_community-0.2.1.tar.gz", hash = "sha256:079942e8f15da975769ccaae19042b7bba5481c42020bbbd7d8cad73a9393261"}, +] + +[package.dependencies] +aiohttp = ">=3.8.3,<4.0.0" +dataclasses-json = ">=0.5.7,<0.7" +langchain = ">=0.2.0,<0.3.0" +langchain-core = ">=0.2.0,<0.3.0" +langsmith = ">=0.1.0,<0.2.0" +numpy = ">=1,<2" +PyYAML = ">=5.3" +requests = ">=2,<3" +SQLAlchemy = ">=1.4,<3" +tenacity = ">=8.1.0,<9.0.0" + +[package.extras] +cli = ["typer (>=0.9.0,<0.10.0)"] +extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "azure-identity (>=1.15.0,<2.0.0)", "azure-search-documents (==11.4.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.6,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cloudpathlib (>=0.18,<0.19)", "cloudpickle (>=2.0.0)", "cohere (>=4,<5)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "friendli-client (>=1.2.4,<2.0.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "httpx (>=0.24.1,<0.25.0)", "httpx-sse (>=0.4.0,<0.5.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "nvidia-riva-client (>=2.14.0,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "oracledb (>=2.2.0,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "premai (>=0.3.25,<0.4.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pyjwt (>=2.8.0,<3.0.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "tidb-vector (>=0.0.3,<1.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "tree-sitter (>=0.20.2,<0.21.0)", "tree-sitter-languages (>=1.8.0,<2.0.0)", "upstash-redis (>=0.15.0,<0.16.0)", "vdms (>=0.0.20,<0.0.21)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] + +[[package]] +name = "langchain-core" +version = "0.2.3" +description = "Building applications with LLMs through composability" +category = "main" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_core-0.2.3-py3-none-any.whl", hash = "sha256:22189b5a3a30bfd65eb995f95e627f7c2c3acb322feb89f5f5f2fb7df21833a7"}, + {file = "langchain_core-0.2.3.tar.gz", hash = "sha256:fbc75a64b9c0b7655d96ca57a707df1e6c09efc1539c36adbd73260612549810"}, +] + +[package.dependencies] +jsonpatch = ">=1.33,<2.0" +langsmith = ">=0.1.65,<0.2.0" +packaging = ">=23.2,<24.0" +pydantic = ">=1,<3" +PyYAML = ">=5.3" +tenacity = ">=8.1.0,<9.0.0" + +[package.extras] +extended-testing = ["jinja2 (>=3,<4)"] + +[[package]] +name = "langchain-openai" +version = "0.1.8" +description = "An integration package connecting OpenAI and LangChain" +category = "main" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_openai-0.1.8-py3-none-any.whl", hash = "sha256:8125c84223e9f43b05defbca64eedbcf362fd78a680de6c25e64f973b34a8063"}, + {file = "langchain_openai-0.1.8.tar.gz", hash = "sha256:a11fcce15def7917c44232abda6baaa63dfc79fe44be1531eea650d39a44cd95"}, +] + +[package.dependencies] +langchain-core = ">=0.2.2,<0.3" +openai = ">=1.26.0,<2.0.0" +tiktoken = ">=0.7,<1" + +[[package]] +name = "langchain-text-splitters" +version = "0.2.0" +description = "LangChain text splitting utilities" +category = "main" +optional = false +python-versions = "<4.0,>=3.8.1" +files = [ + {file = "langchain_text_splitters-0.2.0-py3-none-any.whl", hash = "sha256:7b4c6a45f8471630a882b321e138329b6897102a5bc62f4c12be1c0b05bb9199"}, + {file = "langchain_text_splitters-0.2.0.tar.gz", hash = "sha256:b32ab4f7397f7d42c1fa3283fefc2547ba356bd63a68ee9092865e5ad83c82f9"}, +] + +[package.dependencies] +langchain-core = ">=0.2.0,<0.3.0" + +[package.extras] +extended-testing = ["beautifulsoup4 (>=4.12.3,<5.0.0)", "lxml (>=4.9.3,<6.0)"] + [[package]] name = "langsmith" -version = "0.0.92" +version = "0.1.65" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." +category = "main" optional = false -python-versions = ">=3.8.1,<4.0" +python-versions = "<4.0,>=3.8.1" files = [ - {file = "langsmith-0.0.92-py3-none-any.whl", hash = "sha256:ddcf65e3b5ca11893ae8ef9816ce2a11a089d051be491886e43a2c4556b88fd0"}, - {file = "langsmith-0.0.92.tar.gz", hash = "sha256:61a3a502222bdd221b7f592b6fc14756d74c4fc088aa6bd8834b92adfe9ee583"}, + {file = "langsmith-0.1.65-py3-none-any.whl", hash = "sha256:ab4487029240e69cca30da1065f1e9138e5a7ca2bbe8c697f0bd7d5839f71cf7"}, + {file = "langsmith-0.1.65.tar.gz", hash = "sha256:d3c2eb2391478bd79989f02652cf66e29a7959d677614b6993a47cef43f7f43b"}, ] [package.dependencies] +orjson = ">=3.9.14,<4.0.0" pydantic = ">=1,<3" requests = ">=2,<3" @@ -1293,6 +1590,7 @@ requests = ">=2,<3" name = "lazy-model" version = "0.2.0" description = "" +category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -1307,6 +1605,7 @@ pydantic = ">=1.9.0" name = "marshmallow" version = "3.21.2" description = "A lightweight library for converting complex datatypes to and from native Python datatypes." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1326,6 +1625,7 @@ tests = ["pytest", "pytz", "simplejson"] name = "motor" version = "3.4.0" description = "Non-blocking MongoDB driver for Tornado or asyncio" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1350,6 +1650,7 @@ zstd = ["pymongo[zstd] (>=4.5,<5)"] name = "multidict" version = "6.0.5" description = "multidict implementation" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1445,10 +1746,36 @@ files = [ {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, ] +[[package]] +name = "multiprocess" +version = "0.70.16" +description = "better multiprocessing and multithreading in Python" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "multiprocess-0.70.16-pp310-pypy310_pp73-macosx_10_13_x86_64.whl", hash = "sha256:476887be10e2f59ff183c006af746cb6f1fd0eadcfd4ef49e605cbe2659920ee"}, + {file = "multiprocess-0.70.16-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d951bed82c8f73929ac82c61f01a7b5ce8f3e5ef40f5b52553b4f547ce2b08ec"}, + {file = "multiprocess-0.70.16-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:37b55f71c07e2d741374998c043b9520b626a8dddc8b3129222ca4f1a06ef67a"}, + {file = "multiprocess-0.70.16-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ba8c31889abf4511c7308a8c52bb4a30b9d590e7f58523302ba00237702ca054"}, + {file = "multiprocess-0.70.16-pp39-pypy39_pp73-macosx_10_13_x86_64.whl", hash = "sha256:0dfd078c306e08d46d7a8d06fb120313d87aa43af60d66da43ffff40b44d2f41"}, + {file = "multiprocess-0.70.16-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e7b9d0f307cd9bd50851afaac0dba2cb6c44449efff697df7c7645f7d3f2be3a"}, + {file = "multiprocess-0.70.16-py310-none-any.whl", hash = "sha256:c4a9944c67bd49f823687463660a2d6daae94c289adff97e0f9d696ba6371d02"}, + {file = "multiprocess-0.70.16-py311-none-any.whl", hash = "sha256:af4cabb0dac72abfb1e794fa7855c325fd2b55a10a44628a3c1ad3311c04127a"}, + {file = "multiprocess-0.70.16-py312-none-any.whl", hash = "sha256:fc0544c531920dde3b00c29863377f87e1632601092ea2daca74e4beb40faa2e"}, + {file = "multiprocess-0.70.16-py38-none-any.whl", hash = "sha256:a71d82033454891091a226dfc319d0cfa8019a4e888ef9ca910372a446de4435"}, + {file = "multiprocess-0.70.16-py39-none-any.whl", hash = "sha256:a0bafd3ae1b732eac64be2e72038231c1ba97724b60b09400d68f229fcc2fbf3"}, + {file = "multiprocess-0.70.16.tar.gz", hash = "sha256:161af703d4652a0e1410be6abccecde4a7ddffd19341be0a7011b94aeb171ac1"}, +] + +[package.dependencies] +dill = ">=0.3.8" + [[package]] name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1456,42 +1783,55 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "nest-asyncio" +version = "1.6.0" +description = "Patch asyncio to allow nested event loops" +category = "main" +optional = false +python-versions = ">=3.5" +files = [ + {file = "nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c"}, + {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, +] + [[package]] name = "newrelic" -version = "9.9.1" +version = "9.10.0" description = "New Relic Python Agent" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ - {file = "newrelic-9.9.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:474499f482da7f58b5039f2c42dea2880d878b30729ae563bb1498a0bb30be44"}, - {file = "newrelic-9.9.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:3c99cc368a3cfd9ce40ca4bbe2fe3bdd5f7d37865ea5e4bf811ba6fd0d00152d"}, - {file = "newrelic-9.9.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:3ef567a779b068297c040f7410153135fb12e51e4a82084675b0cf142c407551"}, - {file = "newrelic-9.9.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:303117d3402659afac45174dfe7c595b7d4b3c0812a76b712c251c91ef95c430"}, - {file = "newrelic-9.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c813e9c7bdb1381cb0eda4925e07aa8ee21e111b5025d02261605eaabb129f1"}, - {file = "newrelic-9.9.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5d688917307d083d7fa6f3b31eec40c5a3782b160383230f5f644e2d4ae2a26"}, - {file = "newrelic-9.9.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5710910ceb847f8806540e6934764fff6823d7dcc6d30955e9ecb012e20efbfd"}, - {file = "newrelic-9.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:aefa66f59d62ec22a6d347afa73c24bd723521c4cc0fdce7f51c71bfe85c42bc"}, - {file = "newrelic-9.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afdb30c4f89d0f089ac05ca50a383f94cfcdb07aab0b9722d2d5af09626ab304"}, - {file = "newrelic-9.9.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c6361af2a60ab60a5757b13ce0b9b4efeee577a228637b9b8b449d47ec81fdd"}, - {file = "newrelic-9.9.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7aa1be0d0530d0c566dee2c4d43765aba9fc5fae256fac110ba57aae6ae8d8c4"}, - {file = "newrelic-9.9.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8ad34b8eb60f33b0eab9ed7727cdb9452ad7d4381a2c5397e6ed3d4895833fd1"}, - {file = "newrelic-9.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e613f1ffd0d35b1f866382eeee52d8aa9576d82f3de818a84aa2e56c08f1868"}, - {file = "newrelic-9.9.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3264e305ae0e973f3a02f7394460f4c7366822e8a3509cd08b2093f9cb5def5"}, - {file = "newrelic-9.9.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2b165328c05fd2c006cf1f476bebb281579944418a13903e802344660b13332c"}, - {file = "newrelic-9.9.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e3226ac2c0c57955a00a11f6cf982dd6747490254ed322d6fcf36077bfc37386"}, - {file = "newrelic-9.9.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:673ed069516fa4d168cd12b7319bcadf75fbc9f0ebcd147916e281b2bc16c551"}, - {file = "newrelic-9.9.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40820a3dff89cc8e242f0543fabd1692333458f627ebad6f2e56f6c9db7d2efe"}, - {file = "newrelic-9.9.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ddb2d4a2fc3f88c5d1c0b4dec2f8eb89907541501f2ec7ac14e5506ea702e0f5"}, - {file = "newrelic-9.9.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d50fa347584967c15e574a2503fdcafcd13c86c17e589021eae5432d4aad1cca"}, - {file = "newrelic-9.9.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fbca7a8749eadb05eacdfb68af938dc1045c6be8bcc83375d15a840172b5f40e"}, - {file = "newrelic-9.9.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d6feba8968662c7a84ee6fe837d3be8c53a7126398ded3283634bb51dc43e94"}, - {file = "newrelic-9.9.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:eec85620708aea387b602db61fb43504efc5b5fcb7b627d2cbe0a33c3fe10ab9"}, - {file = "newrelic-9.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:21e280c027835062f54be2df48f32834dcc98f382b049c14ee35b80aa7b48ea0"}, - {file = "newrelic-9.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fb0e56324df855c3079d7d86fd6b35e79727759de8c8517be9c06d482092c3b"}, - {file = "newrelic-9.9.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c43a14c48dd8f752da348c3ec80cb500b9ead12abcd40d29d39a0bb8a62a3a0d"}, - {file = "newrelic-9.9.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:763faab4868b0226906c17ef0419dab527964f489cb2e3818d57d0484762cb2e"}, - {file = "newrelic-9.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7f41343548aad28b7722c85d00079b4e61ef48d5a6bdf757c458a5fe860bb099"}, - {file = "newrelic-9.9.1.tar.gz", hash = "sha256:e49c734058c7b6a6c199e8c2657187143061a6eda92cc8ba67739de88a9e203d"}, + {file = "newrelic-9.10.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:a4d4e5670082225ca7ef0ee986ef8e6588f4e530a05d43d66f9368459c0b1f18"}, + {file = "newrelic-9.10.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:f4605bc4feb114235e242dfe260b75ec85d0894f5400aa7f30e75fbbc0423b3f"}, + {file = "newrelic-9.10.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d3be6c97d007ceb142f908f5ab2444807b44dc600a0b7f3254dc685b5b03fd10"}, + {file = "newrelic-9.10.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:4e573d49c1543a488d6567906a9b2cb0c748cdbf80724c322b06874f8e47c789"}, + {file = "newrelic-9.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae0515f7ab19f1a5dd14e31506420d1b86014c5e1340c2a210833248bc765dae"}, + {file = "newrelic-9.10.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acf5cdcafd2971933ad2f9e836284957f4a3eababe88f063cf53b1b1f67f1a16"}, + {file = "newrelic-9.10.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5d18236bf4a80fca4eb1db03448ed72bf8e16b84b3a4ed5fcc29bb91c2d05d54"}, + {file = "newrelic-9.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:744c815f15ec06e441c11a6c57042d2eca8c41401c11de6f47b3e105d952b9bd"}, + {file = "newrelic-9.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:524ed5bfa09d330746b45e0087765da994ca34802cce032063041e404e58414c"}, + {file = "newrelic-9.10.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ad9cd5459b8c620ab7a876bd5d920c3ef2943948d1262a42289d4f8d16dadab"}, + {file = "newrelic-9.10.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4404c649b5e6165dcdd59091092c19b292a43cc96520d5ffd718b628fb866096"}, + {file = "newrelic-9.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e2576bbec0b640d9b76454dcfd5b2f03078e0bb062a7ea3952a8db7b9972c352"}, + {file = "newrelic-9.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77537a020ce84033f39210e46cc43bb3927cec3fb4b34b5c4df802e96fddaedf"}, + {file = "newrelic-9.10.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2236f70b8c6aa79635f2175e7315d032f3a80dfd65ad9c9ed12a921f5df4c655"}, + {file = "newrelic-9.10.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b8201a33caf7632b2e55e3f9687584ad6956aaf5751485cdb2bad7c428a9b400"}, + {file = "newrelic-9.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:6ed4bc2c9a44dfe59958eeecf1f327f0a0fb6324b5e609515bc511944d12db74"}, + {file = "newrelic-9.10.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cc3ddb26c0615ba4e18f87453bca57f0688a43d2fcdd50e2771a77515cfc3ba"}, + {file = "newrelic-9.10.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09912303e04bee6aa1fe1c671e87b4e8e55461081a96210895828798f5ba8c3f"}, + {file = "newrelic-9.10.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:40368dca0d423efe40b210686d7018787d4365a24ee1deca136b3b7c9d850325"}, + {file = "newrelic-9.10.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56f4c309a07a2c66243b12d18056c32aa704735469741495642c31be4a1c77fa"}, + {file = "newrelic-9.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d68fc707d896dc7da8d6939bcc1f995bf9e463c2b911fc63250a10e1502a234"}, + {file = "newrelic-9.10.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cd462804a6ede617fb3b4b126e9083b3ee8b4ed1250f7cc12299ebacb785432"}, + {file = "newrelic-9.10.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ceef4fef2a5cffb69e9e1742bd18a35625ca62c3856c7016c22be68ec876753d"}, + {file = "newrelic-9.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1f11d9c17b50982fcc39de71f6592a61920ec5e5c29b9105edc9f8fb7f2480b9"}, + {file = "newrelic-9.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf6757d422954e61082715dbba4208cae17bf3720006bc337c3f87f19ede2876"}, + {file = "newrelic-9.10.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae84bacfdc60792bd04e681027cc5c58e6737a04c652e9be2eda84abe21f57f5"}, + {file = "newrelic-9.10.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:667722cf1f4ed9f6cd99f4fbe247fc2bdb941935528e14a93659ba2c651dc889"}, + {file = "newrelic-9.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d0c18210648889416da3de61aa282248e012cb507ba9841511407f922fff9a52"}, + {file = "newrelic-9.10.0.tar.gz", hash = "sha256:02db25b0fd2fc835efe4a7f1c92dbc5bbb95125341aba07152041aa6a5666cda"}, ] [package.extras] @@ -1501,6 +1841,7 @@ infinite-tracing = ["grpcio", "protobuf"] name = "numpy" version = "1.26.4" description = "Fundamental package for array computing in Python" +category = "main" optional = false python-versions = ">=3.9" files = [ @@ -1546,6 +1887,7 @@ files = [ name = "oauthlib" version = "3.2.2" description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1560,41 +1902,175 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] [[package]] name = "openai" -version = "0.27.10" -description = "Python client library for the OpenAI API" +version = "1.30.5" +description = "The official Python library for the openai API" +category = "main" optional = false python-versions = ">=3.7.1" files = [ - {file = "openai-0.27.10-py3-none-any.whl", hash = "sha256:beabd1757e3286fa166dde3b70ebb5ad8081af046876b47c14c41e203ed22a14"}, - {file = "openai-0.27.10.tar.gz", hash = "sha256:60e09edf7100080283688748c6803b7b3b52d5a55d21890f3815292a0552d83b"}, + {file = "openai-1.30.5-py3-none-any.whl", hash = "sha256:2ad95e926de0d2e09cde632a9204b0a6dca4a03c2cdcc84329b01f355784355a"}, + {file = "openai-1.30.5.tar.gz", hash = "sha256:5366562eb2c5917e6116ae0391b7ae6e3acd62b0ae3f565ada32b35d8fcfa106"}, ] [package.dependencies] -aiohttp = "*" -requests = ">=2.20" -tqdm = "*" +anyio = ">=3.5.0,<5" +distro = ">=1.7.0,<2" +httpx = ">=0.23.0,<1" +pydantic = ">=1.9.0,<3" +sniffio = "*" +tqdm = ">4" +typing-extensions = ">=4.7,<5" [package.extras] -datalib = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] -dev = ["black (>=21.6b0,<22.0)", "pytest (==6.*)", "pytest-asyncio", "pytest-mock"] -embeddings = ["matplotlib", "numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "plotly", "scikit-learn (>=1.0.2)", "scipy", "tenacity (>=8.0.1)"] -wandb = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "wandb"] +datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] + +[[package]] +name = "orjson" +version = "3.10.3" +description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "orjson-3.10.3-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9fb6c3f9f5490a3eb4ddd46fc1b6eadb0d6fc16fb3f07320149c3286a1409dd8"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:252124b198662eee80428f1af8c63f7ff077c88723fe206a25df8dc57a57b1fa"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f3e87733823089a338ef9bbf363ef4de45e5c599a9bf50a7a9b82e86d0228da"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8334c0d87103bb9fbbe59b78129f1f40d1d1e8355bbed2ca71853af15fa4ed3"}, + {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1952c03439e4dce23482ac846e7961f9d4ec62086eb98ae76d97bd41d72644d7"}, + {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c0403ed9c706dcd2809f1600ed18f4aae50be263bd7112e54b50e2c2bc3ebd6d"}, + {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:382e52aa4270a037d41f325e7d1dfa395b7de0c367800b6f337d8157367bf3a7"}, + {file = "orjson-3.10.3-cp310-none-win32.whl", hash = "sha256:be2aab54313752c04f2cbaab4515291ef5af8c2256ce22abc007f89f42f49109"}, + {file = "orjson-3.10.3-cp310-none-win_amd64.whl", hash = "sha256:416b195f78ae461601893f482287cee1e3059ec49b4f99479aedf22a20b1098b"}, + {file = "orjson-3.10.3-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:73100d9abbbe730331f2242c1fc0bcb46a3ea3b4ae3348847e5a141265479700"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a12eee96e3ab828dbfcb4d5a0023aa971b27143a1d35dc214c176fdfb29b3"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520de5e2ef0b4ae546bea25129d6c7c74edb43fc6cf5213f511a927f2b28148b"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccaa0a401fc02e8828a5bedfd80f8cd389d24f65e5ca3954d72c6582495b4bcf"}, + {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7bc9e8bc11bac40f905640acd41cbeaa87209e7e1f57ade386da658092dc16"}, + {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3582b34b70543a1ed6944aca75e219e1192661a63da4d039d088a09c67543b08"}, + {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c23dfa91481de880890d17aa7b91d586a4746a4c2aa9a145bebdbaf233768d5"}, + {file = "orjson-3.10.3-cp311-none-win32.whl", hash = "sha256:1770e2a0eae728b050705206d84eda8b074b65ee835e7f85c919f5705b006c9b"}, + {file = "orjson-3.10.3-cp311-none-win_amd64.whl", hash = "sha256:93433b3c1f852660eb5abdc1f4dd0ced2be031ba30900433223b28ee0140cde5"}, + {file = "orjson-3.10.3-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a39aa73e53bec8d410875683bfa3a8edf61e5a1c7bb4014f65f81d36467ea098"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0943a96b3fa09bee1afdfccc2cb236c9c64715afa375b2af296c73d91c23eab2"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e852baafceff8da3c9defae29414cc8513a1586ad93e45f27b89a639c68e8176"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18566beb5acd76f3769c1d1a7ec06cdb81edc4d55d2765fb677e3eaa10fa99e0"}, + {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd2218d5a3aa43060efe649ec564ebedec8ce6ae0a43654b81376216d5ebd42"}, + {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cf20465e74c6e17a104ecf01bf8cd3b7b252565b4ccee4548f18b012ff2f8069"}, + {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba7f67aa7f983c4345eeda16054a4677289011a478ca947cd69c0a86ea45e534"}, + {file = "orjson-3.10.3-cp312-none-win32.whl", hash = "sha256:17e0713fc159abc261eea0f4feda611d32eabc35708b74bef6ad44f6c78d5ea0"}, + {file = "orjson-3.10.3-cp312-none-win_amd64.whl", hash = "sha256:4c895383b1ec42b017dd2c75ae8a5b862fc489006afde06f14afbdd0309b2af0"}, + {file = "orjson-3.10.3-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:be2719e5041e9fb76c8c2c06b9600fe8e8584e6980061ff88dcbc2691a16d20d"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0175a5798bdc878956099f5c54b9837cb62cfbf5d0b86ba6d77e43861bcec2"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:978be58a68ade24f1af7758626806e13cff7748a677faf95fbb298359aa1e20d"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16bda83b5c61586f6f788333d3cf3ed19015e3b9019188c56983b5a299210eb5"}, + {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ad1f26bea425041e0a1adad34630c4825a9e3adec49079b1fb6ac8d36f8b754"}, + {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9e253498bee561fe85d6325ba55ff2ff08fb5e7184cd6a4d7754133bd19c9195"}, + {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0a62f9968bab8a676a164263e485f30a0b748255ee2f4ae49a0224be95f4532b"}, + {file = "orjson-3.10.3-cp38-none-win32.whl", hash = "sha256:8d0b84403d287d4bfa9bf7d1dc298d5c1c5d9f444f3737929a66f2fe4fb8f134"}, + {file = "orjson-3.10.3-cp38-none-win_amd64.whl", hash = "sha256:8bc7a4df90da5d535e18157220d7915780d07198b54f4de0110eca6b6c11e290"}, + {file = "orjson-3.10.3-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9059d15c30e675a58fdcd6f95465c1522b8426e092de9fff20edebfdc15e1cb0"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d40c7f7938c9c2b934b297412c067936d0b54e4b8ab916fd1a9eb8f54c02294"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4a654ec1de8fdaae1d80d55cee65893cb06494e124681ab335218be6a0691e7"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:831c6ef73f9aa53c5f40ae8f949ff7681b38eaddb6904aab89dca4d85099cb78"}, + {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99b880d7e34542db89f48d14ddecbd26f06838b12427d5a25d71baceb5ba119d"}, + {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e5e176c994ce4bd434d7aafb9ecc893c15f347d3d2bbd8e7ce0b63071c52e25"}, + {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b69a58a37dab856491bf2d3bbf259775fdce262b727f96aafbda359cb1d114d8"}, + {file = "orjson-3.10.3-cp39-none-win32.whl", hash = "sha256:b8d4d1a6868cde356f1402c8faeb50d62cee765a1f7ffcfd6de732ab0581e063"}, + {file = "orjson-3.10.3-cp39-none-win_amd64.whl", hash = "sha256:5102f50c5fc46d94f2033fe00d392588564378260d64377aec702f21a7a22912"}, + {file = "orjson-3.10.3.tar.gz", hash = "sha256:2b166507acae7ba2f7c315dcf185a9111ad5e992ac81f2d507aac39193c2c818"}, +] [[package]] name = "packaging" -version = "24.0" +version = "23.2" description = "Core utilities for Python packages" +category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, - {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] +[[package]] +name = "pandas" +version = "2.2.2" +description = "Powerful data structures for data analysis, time series, and statistics" +category = "main" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"}, + {file = "pandas-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238"}, + {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08"}, + {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0"}, + {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51"}, + {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e5a0b00e1e56a842f922e7fae8ae4077aee4af0acb5ae3622bd4b4c30aedf99"}, + {file = "pandas-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:ddf818e4e6c7c6f4f7c8a12709696d193976b591cc7dc50588d3d1a6b5dc8772"}, + {file = "pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288"}, + {file = "pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151"}, + {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b"}, + {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee"}, + {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2925720037f06e89af896c70bca73459d7e6a4be96f9de79e2d440bd499fe0db"}, + {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1"}, + {file = "pandas-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24"}, + {file = "pandas-2.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef"}, + {file = "pandas-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce"}, + {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad"}, + {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad"}, + {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76"}, + {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32"}, + {file = "pandas-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23"}, + {file = "pandas-2.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2"}, + {file = "pandas-2.2.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd"}, + {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863"}, + {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921"}, + {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a"}, + {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92fd6b027924a7e178ac202cfbe25e53368db90d56872d20ffae94b96c7acc57"}, + {file = "pandas-2.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:640cef9aa381b60e296db324337a554aeeb883ead99dc8f6c18e81a93942f5f4"}, + {file = "pandas-2.2.2.tar.gz", hash = "sha256:9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54"}, +] + +[package.dependencies] +numpy = [ + {version = ">=1.22.4", markers = "python_version < \"3.11\""}, + {version = ">=1.23.2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, +] +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.7" + +[package.extras] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] +aws = ["s3fs (>=2022.11.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] +compression = ["zstandard (>=0.19.0)"] +computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] +consortium-standard = ["dataframe-api-compat (>=0.1.7)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] +feather = ["pyarrow (>=10.0.1)"] +fss = ["fsspec (>=2022.11.0)"] +gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] +hdf5 = ["tables (>=3.8.0)"] +html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] +mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=10.0.1)"] +performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] +plot = ["matplotlib (>=3.6.3)"] +postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] +pyarrow = ["pyarrow (>=10.0.1)"] +spss = ["pyreadstat (>=1.2.0)"] +sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.9.2)"] + [[package]] name = "phonenumbers" version = "8.12.48" description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers." +category = "main" optional = false python-versions = "*" files = [ @@ -1606,6 +2082,7 @@ files = [ name = "pkce" version = "1.0.3" description = "PKCE Pyhton generator." +category = "main" optional = false python-versions = ">=3" files = [ @@ -1617,6 +2094,7 @@ files = [ name = "pluggy" version = "1.5.0" description = "plugin and hook calling mechanisms for python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1630,22 +2108,85 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "prompt-toolkit" -version = "3.0.43" +version = "3.0.45" description = "Library for building powerful interactive command lines in Python" +category = "main" optional = false python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.43-py3-none-any.whl", hash = "sha256:a11a29cb3bf0a28a387fe5122cdb649816a957cd9261dcedf8c9f1fef33eacf6"}, - {file = "prompt_toolkit-3.0.43.tar.gz", hash = "sha256:3527b7af26106cbc65a040bcc84839a3566ec1b051bb0bfe953631e704b0ff7d"}, + {file = "prompt_toolkit-3.0.45-py3-none-any.whl", hash = "sha256:a29b89160e494e3ea8622b09fa5897610b437884dcdcd054fdc1308883326c2a"}, + {file = "prompt_toolkit-3.0.45.tar.gz", hash = "sha256:07c60ee4ab7b7e90824b61afa840c8f5aad2d46b3e2e10acc33d8ecc94a49089"}, ] [package.dependencies] wcwidth = "*" +[[package]] +name = "pyarrow" +version = "16.1.0" +description = "Python library for Apache Arrow" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyarrow-16.1.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:17e23b9a65a70cc733d8b738baa6ad3722298fa0c81d88f63ff94bf25eaa77b9"}, + {file = "pyarrow-16.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4740cc41e2ba5d641071d0ab5e9ef9b5e6e8c7611351a5cb7c1d175eaf43674a"}, + {file = "pyarrow-16.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98100e0268d04e0eec47b73f20b39c45b4006f3c4233719c3848aa27a03c1aef"}, + {file = "pyarrow-16.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f68f409e7b283c085f2da014f9ef81e885d90dcd733bd648cfba3ef265961848"}, + {file = "pyarrow-16.1.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:a8914cd176f448e09746037b0c6b3a9d7688cef451ec5735094055116857580c"}, + {file = "pyarrow-16.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:48be160782c0556156d91adbdd5a4a7e719f8d407cb46ae3bb4eaee09b3111bd"}, + {file = "pyarrow-16.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:9cf389d444b0f41d9fe1444b70650fea31e9d52cfcb5f818b7888b91b586efff"}, + {file = "pyarrow-16.1.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:d0ebea336b535b37eee9eee31761813086d33ed06de9ab6fc6aaa0bace7b250c"}, + {file = "pyarrow-16.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e73cfc4a99e796727919c5541c65bb88b973377501e39b9842ea71401ca6c1c"}, + {file = "pyarrow-16.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf9251264247ecfe93e5f5a0cd43b8ae834f1e61d1abca22da55b20c788417f6"}, + {file = "pyarrow-16.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddf5aace92d520d3d2a20031d8b0ec27b4395cab9f74e07cc95edf42a5cc0147"}, + {file = "pyarrow-16.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:25233642583bf658f629eb230b9bb79d9af4d9f9229890b3c878699c82f7d11e"}, + {file = "pyarrow-16.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a33a64576fddfbec0a44112eaf844c20853647ca833e9a647bfae0582b2ff94b"}, + {file = "pyarrow-16.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:185d121b50836379fe012753cf15c4ba9638bda9645183ab36246923875f8d1b"}, + {file = "pyarrow-16.1.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:2e51ca1d6ed7f2e9d5c3c83decf27b0d17bb207a7dea986e8dc3e24f80ff7d6f"}, + {file = "pyarrow-16.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:06ebccb6f8cb7357de85f60d5da50e83507954af617d7b05f48af1621d331c9a"}, + {file = "pyarrow-16.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b04707f1979815f5e49824ce52d1dceb46e2f12909a48a6a753fe7cafbc44a0c"}, + {file = "pyarrow-16.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d32000693deff8dc5df444b032b5985a48592c0697cb6e3071a5d59888714e2"}, + {file = "pyarrow-16.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:8785bb10d5d6fd5e15d718ee1d1f914fe768bf8b4d1e5e9bf253de8a26cb1628"}, + {file = "pyarrow-16.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:e1369af39587b794873b8a307cc6623a3b1194e69399af0efd05bb202195a5a7"}, + {file = "pyarrow-16.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:febde33305f1498f6df85e8020bca496d0e9ebf2093bab9e0f65e2b4ae2b3444"}, + {file = "pyarrow-16.1.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b5f5705ab977947a43ac83b52ade3b881eb6e95fcc02d76f501d549a210ba77f"}, + {file = "pyarrow-16.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0d27bf89dfc2576f6206e9cd6cf7a107c9c06dc13d53bbc25b0bd4556f19cf5f"}, + {file = "pyarrow-16.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d07de3ee730647a600037bc1d7b7994067ed64d0eba797ac74b2bc77384f4c2"}, + {file = "pyarrow-16.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbef391b63f708e103df99fbaa3acf9f671d77a183a07546ba2f2c297b361e83"}, + {file = "pyarrow-16.1.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:19741c4dbbbc986d38856ee7ddfdd6a00fc3b0fc2d928795b95410d38bb97d15"}, + {file = "pyarrow-16.1.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:f2c5fb249caa17b94e2b9278b36a05ce03d3180e6da0c4c3b3ce5b2788f30eed"}, + {file = "pyarrow-16.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:e6b6d3cd35fbb93b70ade1336022cc1147b95ec6af7d36906ca7fe432eb09710"}, + {file = "pyarrow-16.1.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:18da9b76a36a954665ccca8aa6bd9f46c1145f79c0bb8f4f244f5f8e799bca55"}, + {file = "pyarrow-16.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:99f7549779b6e434467d2aa43ab2b7224dd9e41bdde486020bae198978c9e05e"}, + {file = "pyarrow-16.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f07fdffe4fd5b15f5ec15c8b64584868d063bc22b86b46c9695624ca3505b7b4"}, + {file = "pyarrow-16.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddfe389a08ea374972bd4065d5f25d14e36b43ebc22fc75f7b951f24378bf0b5"}, + {file = "pyarrow-16.1.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:3b20bd67c94b3a2ea0a749d2a5712fc845a69cb5d52e78e6449bbd295611f3aa"}, + {file = "pyarrow-16.1.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:ba8ac20693c0bb0bf4b238751d4409e62852004a8cf031c73b0e0962b03e45e3"}, + {file = "pyarrow-16.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:31a1851751433d89a986616015841977e0a188662fcffd1a5677453f1df2de0a"}, + {file = "pyarrow-16.1.0.tar.gz", hash = "sha256:15fbb22ea96d11f0b5768504a3f961edab25eaf4197c341720c4a387f6c60315"}, +] + +[package.dependencies] +numpy = ">=1.16.6" + +[[package]] +name = "pyarrow-hotfix" +version = "0.6" +description = "" +category = "main" +optional = false +python-versions = ">=3.5" +files = [ + {file = "pyarrow_hotfix-0.6-py3-none-any.whl", hash = "sha256:dcc9ae2d220dff0083be6a9aa8e0cdee5182ad358d4931fce825c545e5c89178"}, + {file = "pyarrow_hotfix-0.6.tar.gz", hash = "sha256:79d3e030f7ff890d408a100ac16d6f00b14d44a502d7897cd9fc3e3a534e9945"}, +] + [[package]] name = "pyasn1" version = "0.6.0" description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1657,6 +2198,7 @@ files = [ name = "pyasn1-modules" version = "0.4.0" description = "A collection of ASN.1-based protocols modules" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1671,6 +2213,7 @@ pyasn1 = ">=0.4.6,<0.7.0" name = "pycparser" version = "2.22" description = "C parser in Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1682,6 +2225,7 @@ files = [ name = "pycryptodome" version = "3.10.4" description = "Cryptographic library for Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -1721,6 +2265,7 @@ files = [ name = "pydantic" version = "1.10.15" description = "Data validation and settings management using python type hints" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1773,6 +2318,7 @@ email = ["email-validator (>=1.0.3)"] name = "pyjwt" version = "2.8.0" description = "JSON Web Token implementation in Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1793,6 +2339,7 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] name = "pymongo" version = "4.7.2" description = "Python driver for MongoDB " +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1870,10 +2417,22 @@ snappy = ["python-snappy"] test = ["pytest (>=7)"] zstd = ["zstandard"] +[[package]] +name = "pysbd" +version = "0.3.4" +description = "pysbd (Python Sentence Boundary Disambiguation) is a rule-based sentence boundary detection that works out-of-the-box across many languages." +category = "main" +optional = false +python-versions = ">=3" +files = [ + {file = "pysbd-0.3.4-py3-none-any.whl", hash = "sha256:cd838939b7b0b185fcf86b0baf6636667dfb6e474743beeff878e9f42e022953"}, +] + [[package]] name = "pytest" version = "7.4.4" description = "pytest: simple powerful testing with Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1896,6 +2455,7 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no name = "pytest-asyncio" version = "0.21.2" description = "Pytest support for asyncio" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1914,6 +2474,7 @@ testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy name = "pytest-mock" version = "3.14.0" description = "Thin-wrapper around the mock package for easier use with pytest" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1931,6 +2492,7 @@ dev = ["pre-commit", "pytest-asyncio", "tox"] name = "python-dateutil" version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -1945,6 +2507,7 @@ six = ">=1.5" name = "python-http-client" version = "3.3.7" description = "HTTP REST client, simplified for Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1956,6 +2519,7 @@ files = [ name = "python-multipart" version = "0.0.7" description = "A streaming multipart parser for Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1970,6 +2534,7 @@ dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatc name = "pytz" version = "2024.1" description = "World timezone definitions, modern and historical" +category = "main" optional = false python-versions = "*" files = [ @@ -1981,6 +2546,7 @@ files = [ name = "pywin32" version = "306" description = "Python for Window Extensions" +category = "main" optional = false python-versions = "*" files = [ @@ -2004,6 +2570,7 @@ files = [ name = "pyyaml" version = "6.0.1" description = "YAML parser and emitter for Python" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2012,7 +2579,6 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -2020,16 +2586,8 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -2046,7 +2604,6 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -2054,16 +2611,43 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] +[[package]] +name = "ragas" +version = "0.1.9" +description = "" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "ragas-0.1.9-py3-none-any.whl", hash = "sha256:acdf7ef0868a1dd00b2bdf03d13bc9877425e4b0e0040938105503dd932615df"}, +] + +[package.dependencies] +appdirs = "*" +datasets = "*" +langchain = "*" +langchain-community = "*" +langchain-core = "*" +langchain-openai = "*" +nest-asyncio = "*" +numpy = "*" +openai = ">1" +pysbd = ">=0.3.4" +tiktoken = "*" + +[package.extras] +all = ["sentence-transformers"] + [[package]] name = "redis" version = "4.6.0" description = "Python client for Redis database and key-value store" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2078,15 +2662,105 @@ async-timeout = {version = ">=4.0.2", markers = "python_full_version <= \"3.11.2 hiredis = ["hiredis (>=1.0.0)"] ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"] +[[package]] +name = "regex" +version = "2024.5.15" +description = "Alternative regular expression module, to replace re." +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53"}, + {file = "regex-2024.5.15-cp310-cp310-win32.whl", hash = "sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3"}, + {file = "regex-2024.5.15-cp310-cp310-win_amd64.whl", hash = "sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68"}, + {file = "regex-2024.5.15-cp311-cp311-win32.whl", hash = "sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa"}, + {file = "regex-2024.5.15-cp311-cp311-win_amd64.whl", hash = "sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80"}, + {file = "regex-2024.5.15-cp312-cp312-win32.whl", hash = "sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe"}, + {file = "regex-2024.5.15-cp312-cp312-win_amd64.whl", hash = "sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741"}, + {file = "regex-2024.5.15-cp38-cp38-win32.whl", hash = "sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9"}, + {file = "regex-2024.5.15-cp38-cp38-win_amd64.whl", hash = "sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456"}, + {file = "regex-2024.5.15-cp39-cp39-win32.whl", hash = "sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694"}, + {file = "regex-2024.5.15-cp39-cp39-win_amd64.whl", hash = "sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388"}, + {file = "regex-2024.5.15.tar.gz", hash = "sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c"}, +] + [[package]] name = "requests" -version = "2.31.0" +version = "2.32.3" description = "Python HTTP for Humans." +category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -2101,13 +2775,14 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "requests-file" -version = "2.0.0" +version = "2.1.0" description = "File transport adapter for Requests" +category = "main" optional = false python-versions = "*" files = [ - {file = "requests-file-2.0.0.tar.gz", hash = "sha256:20c5931629c558fda566cacc10cfe2cd502433e628f568c34c80d96a0cc95972"}, - {file = "requests_file-2.0.0-py2.py3-none-any.whl", hash = "sha256:3e493d390adb44aa102ebea827a48717336d5268968c370eaf19abaf5cae13bf"}, + {file = "requests_file-2.1.0-py2.py3-none-any.whl", hash = "sha256:cf270de5a4c5874e84599fc5778303d496c10ae5e870bfa378818f35d21bda5c"}, + {file = "requests_file-2.1.0.tar.gz", hash = "sha256:0f549a3f3b0699415ac04d167e9cb39bccfb730cb832b4d20be3d9867356e658"}, ] [package.dependencies] @@ -2117,6 +2792,7 @@ requests = ">=1.0.0" name = "requests-oauthlib" version = "2.0.0" description = "OAuthlib authentication support for Requests." +category = "main" optional = false python-versions = ">=3.4" files = [ @@ -2135,6 +2811,7 @@ rsa = ["oauthlib[signedtoken] (>=3.0.0)"] name = "restrictedpython" version = "6.2" description = "RestrictedPython is a defined subset of the Python language which allows to provide a program input into a trusted environment." +category = "main" optional = false python-versions = ">=3.6, <3.12" files = [ @@ -2150,6 +2827,7 @@ test = ["pytest", "pytest-mock"] name = "rsa" version = "4.9" description = "Pure-Python RSA implementation" +category = "main" optional = false python-versions = ">=3.6,<4" files = [ @@ -2164,6 +2842,7 @@ pyasn1 = ">=0.1.3" name = "s3transfer" version = "0.10.1" description = "An Amazon S3 Transfer Manager" +category = "main" optional = false python-versions = ">= 3.8" files = [ @@ -2181,6 +2860,7 @@ crt = ["botocore[crt] (>=1.33.2,<2.0a.0)"] name = "sendgrid" version = "6.11.0" description = "Twilio SendGrid library for Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -2196,6 +2876,7 @@ starkbank-ecdsa = ">=2.0.1" name = "sentry-sdk" version = "1.45.0" description = "Python client for Sentry (https://sentry.io)" +category = "main" optional = false python-versions = "*" files = [ @@ -2244,6 +2925,7 @@ tornado = ["tornado (>=5)"] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -2255,6 +2937,7 @@ files = [ name = "sniffio" version = "1.3.1" description = "Sniff out which async library your code is running under" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2266,6 +2949,7 @@ files = [ name = "sqlalchemy" version = "1.4.41" description = "Database Abstraction Library" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -2313,7 +2997,7 @@ files = [ ] [package.dependencies] -greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"} +greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and platform_machine == \"aarch64\" or python_version >= \"3\" and platform_machine == \"ppc64le\" or python_version >= \"3\" and platform_machine == \"x86_64\" or python_version >= \"3\" and platform_machine == \"amd64\" or python_version >= \"3\" and platform_machine == \"AMD64\" or python_version >= \"3\" and platform_machine == \"win32\" or python_version >= \"3\" and platform_machine == \"WIN32\""} [package.extras] aiomysql = ["aiomysql", "greenlet (!=0.4.17)"] @@ -2340,6 +3024,7 @@ sqlcipher = ["sqlcipher3-binary"] name = "sqlalchemy2-stubs" version = "0.0.2a38" description = "Typing Stubs for SQLAlchemy 1.4" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2354,6 +3039,7 @@ typing-extensions = ">=3.7.4" name = "sqlmodel" version = "0.0.8" description = "SQLModel, SQL databases in Python, designed for simplicity, compatibility, and robustness." +category = "main" optional = false python-versions = ">=3.6.1,<4.0.0" files = [ @@ -2370,6 +3056,7 @@ sqlalchemy2-stubs = "*" name = "starkbank-ecdsa" version = "2.2.0" description = "A lightweight and fast pure python ECDSA library" +category = "main" optional = false python-versions = "*" files = [ @@ -2380,6 +3067,7 @@ files = [ name = "starlette" version = "0.36.3" description = "The little ASGI library that shines." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2398,6 +3086,7 @@ full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7 name = "supertokens-python" version = "0.15.3" description = "SuperTokens SDK for Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2412,7 +3101,7 @@ Deprecated = "1.2.13" httpx = ">=0.15.0,<0.25.0" phonenumbers = "8.12.48" pkce = "1.0.3" -pycryptodome = "==3.10.*" +pycryptodome = ">=3.10.0,<3.11.0" PyJWT = {version = ">=2.6.0,<3.0.0", extras = ["crypto"]} tldextract = "3.1.0" twilio = "7.9.1" @@ -2428,6 +3117,7 @@ flask = ["Flask", "flask-cors", "python-dotenv (==0.19.2)"] name = "tenacity" version = "8.3.0" description = "Retry code until it succeeds" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2439,10 +3129,64 @@ files = [ doc = ["reno", "sphinx"] test = ["pytest", "tornado (>=4.5)", "typeguard"] +[[package]] +name = "tiktoken" +version = "0.7.0" +description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tiktoken-0.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485f3cc6aba7c6b6ce388ba634fbba656d9ee27f766216f45146beb4ac18b25f"}, + {file = "tiktoken-0.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e54be9a2cd2f6d6ffa3517b064983fb695c9a9d8aa7d574d1ef3c3f931a99225"}, + {file = "tiktoken-0.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79383a6e2c654c6040e5f8506f3750db9ddd71b550c724e673203b4f6b4b4590"}, + {file = "tiktoken-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d4511c52caacf3c4981d1ae2df85908bd31853f33d30b345c8b6830763f769c"}, + {file = "tiktoken-0.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13c94efacdd3de9aff824a788353aa5749c0faee1fbe3816df365ea450b82311"}, + {file = "tiktoken-0.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8e58c7eb29d2ab35a7a8929cbeea60216a4ccdf42efa8974d8e176d50c9a3df5"}, + {file = "tiktoken-0.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:21a20c3bd1dd3e55b91c1331bf25f4af522c525e771691adbc9a69336fa7f702"}, + {file = "tiktoken-0.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:10c7674f81e6e350fcbed7c09a65bca9356eaab27fb2dac65a1e440f2bcfe30f"}, + {file = "tiktoken-0.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:084cec29713bc9d4189a937f8a35dbdfa785bd1235a34c1124fe2323821ee93f"}, + {file = "tiktoken-0.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:811229fde1652fedcca7c6dfe76724d0908775b353556d8a71ed74d866f73f7b"}, + {file = "tiktoken-0.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86b6e7dc2e7ad1b3757e8a24597415bafcfb454cebf9a33a01f2e6ba2e663992"}, + {file = "tiktoken-0.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1063c5748be36344c7e18c7913c53e2cca116764c2080177e57d62c7ad4576d1"}, + {file = "tiktoken-0.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:20295d21419bfcca092644f7e2f2138ff947a6eb8cfc732c09cc7d76988d4a89"}, + {file = "tiktoken-0.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:959d993749b083acc57a317cbc643fb85c014d055b2119b739487288f4e5d1cb"}, + {file = "tiktoken-0.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:71c55d066388c55a9c00f61d2c456a6086673ab7dec22dd739c23f77195b1908"}, + {file = "tiktoken-0.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:09ed925bccaa8043e34c519fbb2f99110bd07c6fd67714793c21ac298e449410"}, + {file = "tiktoken-0.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03c6c40ff1db0f48a7b4d2dafeae73a5607aacb472fa11f125e7baf9dce73704"}, + {file = "tiktoken-0.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d20b5c6af30e621b4aca094ee61777a44118f52d886dbe4f02b70dfe05c15350"}, + {file = "tiktoken-0.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d427614c3e074004efa2f2411e16c826f9df427d3c70a54725cae860f09e4bf4"}, + {file = "tiktoken-0.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8c46d7af7b8c6987fac9b9f61041b452afe92eb087d29c9ce54951280f899a97"}, + {file = "tiktoken-0.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:0bc603c30b9e371e7c4c7935aba02af5994a909fc3c0fe66e7004070858d3f8f"}, + {file = "tiktoken-0.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2398fecd38c921bcd68418675a6d155fad5f5e14c2e92fcf5fe566fa5485a858"}, + {file = "tiktoken-0.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f5f6afb52fb8a7ea1c811e435e4188f2bef81b5e0f7a8635cc79b0eef0193d6"}, + {file = "tiktoken-0.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:861f9ee616766d736be4147abac500732b505bf7013cfaf019b85892637f235e"}, + {file = "tiktoken-0.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54031f95c6939f6b78122c0aa03a93273a96365103793a22e1793ee86da31685"}, + {file = "tiktoken-0.7.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fffdcb319b614cf14f04d02a52e26b1d1ae14a570f90e9b55461a72672f7b13d"}, + {file = "tiktoken-0.7.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c72baaeaefa03ff9ba9688624143c858d1f6b755bb85d456d59e529e17234769"}, + {file = "tiktoken-0.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:131b8aeb043a8f112aad9f46011dced25d62629091e51d9dc1adbf4a1cc6aa98"}, + {file = "tiktoken-0.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cabc6dc77460df44ec5b879e68692c63551ae4fae7460dd4ff17181df75f1db7"}, + {file = "tiktoken-0.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8d57f29171255f74c0aeacd0651e29aa47dff6f070cb9f35ebc14c82278f3b25"}, + {file = "tiktoken-0.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ee92776fdbb3efa02a83f968c19d4997a55c8e9ce7be821ceee04a1d1ee149c"}, + {file = "tiktoken-0.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e215292e99cb41fbc96988ef62ea63bb0ce1e15f2c147a61acc319f8b4cbe5bf"}, + {file = "tiktoken-0.7.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8a81bac94769cab437dd3ab0b8a4bc4e0f9cf6835bcaa88de71f39af1791727a"}, + {file = "tiktoken-0.7.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d6d73ea93e91d5ca771256dfc9d1d29f5a554b83821a1dc0891987636e0ae226"}, + {file = "tiktoken-0.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:2bcb28ddf79ffa424f171dfeef9a4daff61a94c631ca6813f43967cb263b83b9"}, + {file = "tiktoken-0.7.0.tar.gz", hash = "sha256:1077266e949c24e0291f6c350433c6f0971365ece2b173a23bc3b9f9defef6b6"}, +] + +[package.dependencies] +regex = ">=2022.1.18" +requests = ">=2.26.0" + +[package.extras] +blobfile = ["blobfile (>=2)"] + [[package]] name = "tldextract" version = "3.1.0" description = "Accurately separate the TLD from the registered domain and subdomains of a URL, using the Public Suffix List. By default, this includes the public ICANN TLDs and their exceptions. You can optionally support the Public Suffix List's private domains as well." +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -2460,6 +3204,7 @@ requests-file = ">=1.4" name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -2471,6 +3216,7 @@ files = [ name = "tomli" version = "2.0.1" description = "A lil' TOML parser" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2482,6 +3228,7 @@ files = [ name = "tqdm" version = "4.66.4" description = "Fast, Extensible Progress Meter" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2502,6 +3249,7 @@ telegram = ["requests"] name = "twilio" version = "7.9.1" description = "Twilio API client and TwiML generator" +category = "main" optional = false python-versions = ">=3.6.0" files = [ @@ -2516,19 +3264,21 @@ requests = ">=2.0.0" [[package]] name = "typing-extensions" -version = "4.11.0" +version = "4.12.0" description = "Backported and Experimental Type Hints for Python 3.8+" +category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"}, - {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, + {file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"}, + {file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"}, ] [[package]] name = "typing-inspect" version = "0.9.0" description = "Runtime inspection utilities for typing module." +category = "main" optional = false python-versions = "*" files = [ @@ -2544,6 +3294,7 @@ typing-extensions = ">=3.7.4" name = "tzdata" version = "2024.1" description = "Provider of IANA time zone data" +category = "main" optional = false python-versions = ">=2" files = [ @@ -2555,6 +3306,7 @@ files = [ name = "urllib3" version = "1.26.18" description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -2571,6 +3323,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] name = "uvicorn" version = "0.22.0" description = "The lightning-fast ASGI server." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2589,6 +3342,7 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", name = "vine" version = "5.1.0" description = "Python promises." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2600,6 +3354,7 @@ files = [ name = "watchdog" version = "3.0.0" description = "Filesystem events monitoring" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2642,6 +3397,7 @@ watchmedo = ["PyYAML (>=3.10)"] name = "wcwidth" version = "0.2.13" description = "Measures the displayed width of unicode strings in a terminal" +category = "main" optional = false python-versions = "*" files = [ @@ -2653,6 +3409,7 @@ files = [ name = "websocket-client" version = "1.8.0" description = "WebSocket client for Python with low level API options" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2669,6 +3426,7 @@ test = ["websockets"] name = "wrapt" version = "1.16.0" description = "Module for decorators, wrappers and monkey patching." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2744,10 +3502,129 @@ files = [ {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, ] +[[package]] +name = "xxhash" +version = "3.4.1" +description = "Python binding for xxHash" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "xxhash-3.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:91dbfa55346ad3e18e738742236554531a621042e419b70ad8f3c1d9c7a16e7f"}, + {file = "xxhash-3.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:665a65c2a48a72068fcc4d21721510df5f51f1142541c890491afc80451636d2"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb11628470a6004dc71a09fe90c2f459ff03d611376c1debeec2d648f44cb693"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5bef2a7dc7b4f4beb45a1edbba9b9194c60a43a89598a87f1a0226d183764189"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c0f7b2d547d72c7eda7aa817acf8791f0146b12b9eba1d4432c531fb0352228"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00f2fdef6b41c9db3d2fc0e7f94cb3db86693e5c45d6de09625caad9a469635b"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23cfd9ca09acaf07a43e5a695143d9a21bf00f5b49b15c07d5388cadf1f9ce11"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6a9ff50a3cf88355ca4731682c168049af1ca222d1d2925ef7119c1a78e95b3b"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f1d7c69a1e9ca5faa75546fdd267f214f63f52f12692f9b3a2f6467c9e67d5e7"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:672b273040d5d5a6864a36287f3514efcd1d4b1b6a7480f294c4b1d1ee1b8de0"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4178f78d70e88f1c4a89ff1ffe9f43147185930bb962ee3979dba15f2b1cc799"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9804b9eb254d4b8cc83ab5a2002128f7d631dd427aa873c8727dba7f1f0d1c2b"}, + {file = "xxhash-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c09c49473212d9c87261d22c74370457cfff5db2ddfc7fd1e35c80c31a8c14ce"}, + {file = "xxhash-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:ebbb1616435b4a194ce3466d7247df23499475c7ed4eb2681a1fa42ff766aff6"}, + {file = "xxhash-3.4.1-cp310-cp310-win_arm64.whl", hash = "sha256:25dc66be3db54f8a2d136f695b00cfe88018e59ccff0f3b8f545869f376a8a46"}, + {file = "xxhash-3.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58c49083801885273e262c0f5bbeac23e520564b8357fbb18fb94ff09d3d3ea5"}, + {file = "xxhash-3.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b526015a973bfbe81e804a586b703f163861da36d186627e27524f5427b0d520"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36ad4457644c91a966f6fe137d7467636bdc51a6ce10a1d04f365c70d6a16d7e"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:248d3e83d119770f96003271fe41e049dd4ae52da2feb8f832b7a20e791d2920"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2070b6d5bbef5ee031666cf21d4953c16e92c2f8a24a94b5c240f8995ba3b1d0"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2746035f518f0410915e247877f7df43ef3372bf36cfa52cc4bc33e85242641"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a8ba6181514681c2591840d5632fcf7356ab287d4aff1c8dea20f3c78097088"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0aac5010869240e95f740de43cd6a05eae180c59edd182ad93bf12ee289484fa"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4cb11d8debab1626181633d184b2372aaa09825bde709bf927704ed72765bed1"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b29728cff2c12f3d9f1d940528ee83918d803c0567866e062683f300d1d2eff3"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:a15cbf3a9c40672523bdb6ea97ff74b443406ba0ab9bca10ceccd9546414bd84"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6e66df260fed01ed8ea790c2913271641c58481e807790d9fca8bfd5a3c13844"}, + {file = "xxhash-3.4.1-cp311-cp311-win32.whl", hash = "sha256:e867f68a8f381ea12858e6d67378c05359d3a53a888913b5f7d35fbf68939d5f"}, + {file = "xxhash-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:200a5a3ad9c7c0c02ed1484a1d838b63edcf92ff538770ea07456a3732c577f4"}, + {file = "xxhash-3.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:1d03f1c0d16d24ea032e99f61c552cb2b77d502e545187338bea461fde253583"}, + {file = "xxhash-3.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c4bbba9b182697a52bc0c9f8ec0ba1acb914b4937cd4a877ad78a3b3eeabefb3"}, + {file = "xxhash-3.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9fd28a9da300e64e434cfc96567a8387d9a96e824a9be1452a1e7248b7763b78"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6066d88c9329ab230e18998daec53d819daeee99d003955c8db6fc4971b45ca3"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93805bc3233ad89abf51772f2ed3355097a5dc74e6080de19706fc447da99cd3"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64da57d5ed586ebb2ecdde1e997fa37c27fe32fe61a656b77fabbc58e6fbff6e"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a97322e9a7440bf3c9805cbaac090358b43f650516486746f7fa482672593df"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbe750d512982ee7d831838a5dee9e9848f3fb440e4734cca3f298228cc957a6"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:fd79d4087727daf4d5b8afe594b37d611ab95dc8e29fe1a7517320794837eb7d"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:743612da4071ff9aa4d055f3f111ae5247342931dedb955268954ef7201a71ff"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:b41edaf05734092f24f48c0958b3c6cbaaa5b7e024880692078c6b1f8247e2fc"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:a90356ead70d715fe64c30cd0969072de1860e56b78adf7c69d954b43e29d9fa"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ac56eebb364e44c85e1d9e9cc5f6031d78a34f0092fea7fc80478139369a8b4a"}, + {file = "xxhash-3.4.1-cp312-cp312-win32.whl", hash = "sha256:911035345932a153c427107397c1518f8ce456f93c618dd1c5b54ebb22e73747"}, + {file = "xxhash-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:f31ce76489f8601cc7b8713201ce94b4bd7b7ce90ba3353dccce7e9e1fee71fa"}, + {file = "xxhash-3.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:b5beb1c6a72fdc7584102f42c4d9df232ee018ddf806e8c90906547dfb43b2da"}, + {file = "xxhash-3.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6d42b24d1496deb05dee5a24ed510b16de1d6c866c626c2beb11aebf3be278b9"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b685fab18876b14a8f94813fa2ca80cfb5ab6a85d31d5539b7cd749ce9e3624"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:419ffe34c17ae2df019a4685e8d3934d46b2e0bbe46221ab40b7e04ed9f11137"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e041ce5714f95251a88670c114b748bca3bf80cc72400e9f23e6d0d59cf2681"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc860d887c5cb2f524899fb8338e1bb3d5789f75fac179101920d9afddef284b"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:312eba88ffe0a05e332e3a6f9788b73883752be63f8588a6dc1261a3eaaaf2b2"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e01226b6b6a1ffe4e6bd6d08cfcb3ca708b16f02eb06dd44f3c6e53285f03e4f"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9f3025a0d5d8cf406a9313cd0d5789c77433ba2004b1c75439b67678e5136537"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:6d3472fd4afef2a567d5f14411d94060099901cd8ce9788b22b8c6f13c606a93"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:43984c0a92f06cac434ad181f329a1445017c33807b7ae4f033878d860a4b0f2"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a55e0506fdb09640a82ec4f44171273eeabf6f371a4ec605633adb2837b5d9d5"}, + {file = "xxhash-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:faec30437919555b039a8bdbaba49c013043e8f76c999670aef146d33e05b3a0"}, + {file = "xxhash-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:c9e1b646af61f1fc7083bb7b40536be944f1ac67ef5e360bca2d73430186971a"}, + {file = "xxhash-3.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:961d948b7b1c1b6c08484bbce3d489cdf153e4122c3dfb07c2039621243d8795"}, + {file = "xxhash-3.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:719a378930504ab159f7b8e20fa2aa1896cde050011af838af7e7e3518dd82de"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74fb5cb9406ccd7c4dd917f16630d2e5e8cbbb02fc2fca4e559b2a47a64f4940"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5dab508ac39e0ab988039bc7f962c6ad021acd81fd29145962b068df4148c476"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c59f3e46e7daf4c589e8e853d700ef6607afa037bfad32c390175da28127e8c"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cc07256eff0795e0f642df74ad096f8c5d23fe66bc138b83970b50fc7f7f6c5"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9f749999ed80f3955a4af0eb18bb43993f04939350b07b8dd2f44edc98ffee9"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7688d7c02149a90a3d46d55b341ab7ad1b4a3f767be2357e211b4e893efbaaf6"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a8b4977963926f60b0d4f830941c864bed16aa151206c01ad5c531636da5708e"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:8106d88da330f6535a58a8195aa463ef5281a9aa23b04af1848ff715c4398fb4"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4c76a77dbd169450b61c06fd2d5d436189fc8ab7c1571d39265d4822da16df22"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:11f11357c86d83e53719c592021fd524efa9cf024dc7cb1dfb57bbbd0d8713f2"}, + {file = "xxhash-3.4.1-cp38-cp38-win32.whl", hash = "sha256:0c786a6cd74e8765c6809892a0d45886e7c3dc54de4985b4a5eb8b630f3b8e3b"}, + {file = "xxhash-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:aabf37fb8fa27430d50507deeab2ee7b1bcce89910dd10657c38e71fee835594"}, + {file = "xxhash-3.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6127813abc1477f3a83529b6bbcfeddc23162cece76fa69aee8f6a8a97720562"}, + {file = "xxhash-3.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef2e194262f5db16075caea7b3f7f49392242c688412f386d3c7b07c7733a70a"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71be94265b6c6590f0018bbf73759d21a41c6bda20409782d8117e76cd0dfa8b"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10e0a619cdd1c0980e25eb04e30fe96cf8f4324758fa497080af9c21a6de573f"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa122124d2e3bd36581dd78c0efa5f429f5220313479fb1072858188bc2d5ff1"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17032f5a4fea0a074717fe33477cb5ee723a5f428de7563e75af64bfc1b1e10"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca7783b20e3e4f3f52f093538895863f21d18598f9a48211ad757680c3bd006f"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d77d09a1113899fad5f354a1eb4f0a9afcf58cefff51082c8ad643ff890e30cf"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:21287bcdd299fdc3328cc0fbbdeaa46838a1c05391264e51ddb38a3f5b09611f"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:dfd7a6cc483e20b4ad90224aeb589e64ec0f31e5610ab9957ff4314270b2bf31"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:543c7fcbc02bbb4840ea9915134e14dc3dc15cbd5a30873a7a5bf66039db97ec"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fe0a98d990e433013f41827b62be9ab43e3cf18e08b1483fcc343bda0d691182"}, + {file = "xxhash-3.4.1-cp39-cp39-win32.whl", hash = "sha256:b9097af00ebf429cc7c0e7d2fdf28384e4e2e91008130ccda8d5ae653db71e54"}, + {file = "xxhash-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:d699b921af0dcde50ab18be76c0d832f803034d80470703700cb7df0fbec2832"}, + {file = "xxhash-3.4.1-cp39-cp39-win_arm64.whl", hash = "sha256:2be491723405e15cc099ade1280133ccfbf6322d2ef568494fb7d07d280e7eee"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:431625fad7ab5649368c4849d2b49a83dc711b1f20e1f7f04955aab86cd307bc"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc6dbd5fc3c9886a9e041848508b7fb65fd82f94cc793253990f81617b61fe49"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3ff8dbd0ec97aec842476cb8ccc3e17dd288cd6ce3c8ef38bff83d6eb927817"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef73a53fe90558a4096e3256752268a8bdc0322f4692ed928b6cd7ce06ad4fe3"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:450401f42bbd274b519d3d8dcf3c57166913381a3d2664d6609004685039f9d3"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a162840cf4de8a7cd8720ff3b4417fbc10001eefdd2d21541a8226bb5556e3bb"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b736a2a2728ba45017cb67785e03125a79d246462dfa892d023b827007412c52"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d0ae4c2e7698adef58710d6e7a32ff518b66b98854b1c68e70eee504ad061d8"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6322c4291c3ff174dcd104fae41500e75dad12be6f3085d119c2c8a80956c51"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:dd59ed668801c3fae282f8f4edadf6dc7784db6d18139b584b6d9677ddde1b6b"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:92693c487e39523a80474b0394645b393f0ae781d8db3474ccdcead0559ccf45"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4603a0f642a1e8d7f3ba5c4c25509aca6a9c1cc16f85091004a7028607ead663"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fa45e8cbfbadb40a920fe9ca40c34b393e0b067082d94006f7f64e70c7490a6"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:595b252943b3552de491ff51e5bb79660f84f033977f88f6ca1605846637b7c6"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:562d8b8f783c6af969806aaacf95b6c7b776929ae26c0cd941d54644ea7ef51e"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:41ddeae47cf2828335d8d991f2d2b03b0bdc89289dc64349d712ff8ce59d0647"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c44d584afdf3c4dbb3277e32321d1a7b01d6071c1992524b6543025fb8f4206f"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd7bddb3a5b86213cc3f2c61500c16945a1b80ecd572f3078ddbbe68f9dabdfb"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9ecb6c987b62437c2f99c01e97caf8d25660bf541fe79a481d05732e5236719c"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:696b4e18b7023527d5c50ed0626ac0520edac45a50ec7cf3fc265cd08b1f4c03"}, + {file = "xxhash-3.4.1.tar.gz", hash = "sha256:0379d6cf1ff987cd421609a264ce025e74f346e3e145dd106c0cc2e3ec3f99a9"}, +] + [[package]] name = "yarl" version = "1.9.4" description = "Yet another URL library" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2850,4 +3727,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "ba485fa0da6abc5be86f63b3694311532f1a89605e021984b6117475767434e0" +content-hash = "1ec6041622ce147bb8c2784049018a6b3c46d302deb653642425e8a0eedd2a87" diff --git a/agenta-backend/pyproject.toml b/agenta-backend/pyproject.toml index bb0be6a2ee..c52c5e7277 100644 --- a/agenta-backend/pyproject.toml +++ b/agenta-backend/pyproject.toml @@ -10,7 +10,7 @@ packages = [{include = "agenta_backend"}] python = "^3.9" fastapi = "^0.109.1" pydantic = "^1.10.7" -docker = "^6.1.1" +docker = "7.1.0" toml = "^0.10.2" uvicorn = "^0.22.0" sqlmodel = "^0.0.8" @@ -19,8 +19,6 @@ python-multipart = "^0.0.7" backoff = "^2.2.1" redis = "^4.6.0" aiodocker = "^0.21.0" -openai = "^0.27.8" -langchain = "^0.0.329" supertokens-python = "^0.15.1" sendgrid = "^6.10.0" restrictedpython = { version = "^6.2", python = ">=3.9,<3.12" } @@ -35,6 +33,8 @@ watchdog = {extras = ["watchmedo"], version = "^3.0.0"} beanie = "^1.25.0" newrelic = "^9.8.0" aioboto3 = "^12.4.0" +ragas = "^0.1.8" +openai = "^1.30.4" [tool.poetry.group.dev.dependencies] pytest = "^7.3.1" diff --git a/agenta-web/src/components/pages/evaluations/FilterColumns/FilterColumns.tsx b/agenta-web/src/components/pages/evaluations/FilterColumns/FilterColumns.tsx new file mode 100644 index 0000000000..884a43b15f --- /dev/null +++ b/agenta-web/src/components/pages/evaluations/FilterColumns/FilterColumns.tsx @@ -0,0 +1,88 @@ +import {JSSTheme} from "@/lib/Types" +import {CheckOutlined, DownOutlined} from "@ant-design/icons" +import {Button, Dropdown, Space} from "antd" +import {ItemType} from "antd/es/menu/hooks/useItems" +import React from "react" +import {createUseStyles} from "react-jss" +import {ColDef} from "ag-grid-community" + +const useStyles = createUseStyles((theme: JSSTheme) => ({ + dropdownMenu: { + "&>.ant-dropdown-menu-item": { + "& .anticon-check": { + display: "none", + }, + }, + "&>.ant-dropdown-menu-item-selected": { + "&:not(:hover)": { + backgroundColor: "transparent !important", + }, + "& .anticon-check": { + display: "inline-flex !important", + }, + }, + }, +})) + +export const generateFilterItems = (colDefs: ColDef[]) => { + return colDefs.map((configs) => ({ + key: configs.headerName as string, + label: ( + + + <>{configs.headerName} + + ), + })) +} + +interface FilterColumnsProps { + isOpen: boolean + handleOpenChange: ( + open: boolean, + info: { + source: "trigger" | "menu" + }, + ) => void + shownCols: string[] + items: ItemType[] + onClick: ({key}: {key: string}) => void + buttonText?: string +} + +const FilterColumns = ({ + isOpen, + handleOpenChange, + shownCols, + items, + onClick, + buttonText, +}: FilterColumnsProps) => { + const classes = useStyles() + + return ( + + + + ) +} + +export default FilterColumns diff --git a/agenta-web/src/components/pages/evaluations/evaluationCompare/EvaluationCompare.tsx b/agenta-web/src/components/pages/evaluations/evaluationCompare/EvaluationCompare.tsx index 050c6d091d..be9a2d5ad3 100644 --- a/agenta-web/src/components/pages/evaluations/evaluationCompare/EvaluationCompare.tsx +++ b/agenta-web/src/components/pages/evaluations/evaluationCompare/EvaluationCompare.tsx @@ -11,18 +11,12 @@ import { import {fetchAllComparisonResults} from "@/services/evaluations" import {ColDef} from "ag-grid-community" import {AgGridReact} from "ag-grid-react" -import {Button, Dropdown, DropdownProps, Space, Spin, Switch, Tag, Tooltip, Typography} from "antd" +import {Button, DropdownProps, Space, Spin, Tag, Tooltip, Typography} from "antd" import React, {useEffect, useMemo, useRef, useState} from "react" import {createUseStyles} from "react-jss" -import {getFilterParams, getTypedValue} from "@/lib/helpers/evaluate" +import {getFilterParams, getTypedValue, removeCorrectAnswerPrefix} from "@/lib/helpers/evaluate" import {getColorFromStr, getRandomColors} from "@/lib/helpers/colors" -import { - CheckOutlined, - CloseCircleOutlined, - DownOutlined, - DownloadOutlined, - UndoOutlined, -} from "@ant-design/icons" +import {CheckOutlined, CloseCircleOutlined, DownloadOutlined, UndoOutlined} from "@ant-design/icons" import {getAppValues} from "@/contexts/app.context" import {useQueryParam} from "@/hooks/useQuery" import {LongTextCellRenderer} from "../cellRenderers/cellRenderers" @@ -32,7 +26,8 @@ import {useAtom} from "jotai" import {evaluatorsAtom} from "@/lib/atoms/evaluation" import CompareOutputDiff from "@/components/CompareOutputDiff/CompareOutputDiff" import {formatCurrency, formatLatency} from "@/lib/helpers/formatters" -import {useLocalStorage} from "usehooks-ts" +import FilterColumns, {generateFilterItems} from "../FilterColumns/FilterColumns" +import _ from "lodash" const useStyles = createUseStyles((theme: JSSTheme) => ({ table: { @@ -82,17 +77,24 @@ const EvaluationCompareMode: React.FC = () => { const evaluationIdsArray = evaluationIdsStr.split(",").filter((item) => !!item) const [evalIds, setEvalIds] = useState(evaluationIdsArray) const [hiddenVariants, setHiddenVariants] = useState([]) - const [showDiff, setShowDiff] = useLocalStorage("showDiff", "show") const [fetching, setFetching] = useState(false) const [rows, setRows] = useState([]) const [testset, setTestset] = useState() const [evaluators] = useAtom(evaluatorsAtom) const gridRef = useRef>() - const [filterColsDropdown, setFilterColsDropdown] = useState(false) + const [isFilterColsDropdownOpen, setIsFilterColsDropdownOpen] = useState(false) + const [isDiffDropdownOpen, setIsDiffDropdownOpen] = useState(false) + const [selectedCorrectAnswer, setSelectedCorrectAnswer] = useState(["noDiffColumnIsSelected"]) - const handleOpenChange: DropdownProps["onOpenChange"] = (nextOpen, info) => { + const handleOpenChangeDiff: DropdownProps["onOpenChange"] = (nextOpen, info) => { if (info.source === "trigger" || nextOpen) { - setFilterColsDropdown(nextOpen) + setIsDiffDropdownOpen(nextOpen) + } + } + + const handleOpenChangeFilterCols: DropdownProps["onOpenChange"] = (nextOpen, info) => { + if (info.source === "trigger" || nextOpen) { + setIsFilterColsDropdownOpen(nextOpen) } } @@ -122,9 +124,19 @@ const EvaluationCompareMode: React.FC = () => { if (!rows.length || !variants.length) return [] - inputs.forEach((ip, ix) => { + inputs.forEach((input, ix) => { colDefs.push({ - headerName: `Input: ${ip.name}`, + headerName: `Input: ${input.name}`, + headerComponent: (props: any) => { + return ( + + + {input.name} + Input + + + ) + }, minWidth: 200, flex: 1, field: `inputs.${ix}.value` as any, @@ -134,15 +146,29 @@ const EvaluationCompareMode: React.FC = () => { }) }) - colDefs.push({ - headerName: "Expected Output", - minWidth: 280, - flex: 1, - field: "correctAnswer", - ...getFilterParams("text"), - pinned: "left", - cellRenderer: (params: any) => LongTextCellRenderer(params), - }) + Object.keys(rows[0]) + .filter((item) => item.startsWith("correctAnswer_")) + .forEach((key) => + colDefs.push({ + headerName: `${removeCorrectAnswerPrefix(key)}`, + hide: hiddenVariants.includes(`${removeCorrectAnswerPrefix(key)}`), + headerComponent: (props: any) => { + return ( + + + {removeCorrectAnswerPrefix(key)} + Ground Truth + + + ) + }, + minWidth: 280, + flex: 1, + field: key, + ...getFilterParams("text"), + cellRenderer: (params: any) => LongTextCellRenderer(params), + }), + ) variants.forEach((variant, vi) => { colDefs.push({ @@ -159,11 +185,11 @@ const EvaluationCompareMode: React.FC = () => { flex: 1, field: `variants.${vi}.output` as any, ...getFilterParams("text"), - hide: !evalIds.includes(variant.evaluationId) || hiddenVariants.includes("Output"), + hide: hiddenVariants.includes("Output"), cellRenderer: (params: any) => { return ( <> - {showDiff === "show" + {selectedCorrectAnswer[0] !== "noDiffColumnIsSelected" ? LongTextCellRenderer( params, = () => { item.evaluationId === variant.evaluationId, )?.output?.result, )} - expectedOutput={params.data?.correctAnswer} + expectedOutput={ + params.data[selectedCorrectAnswer[0]] || "" + } />, ) : LongTextCellRenderer( @@ -189,28 +217,10 @@ const EvaluationCompareMode: React.FC = () => { ) }, valueGetter: (params) => { - return ( - <> - {showDiff === "show" ? ( - - - item.evaluationId === variant.evaluationId, - )?.output?.result, - )} - expectedOutput={params.data?.correctAnswer} - /> - - ) : ( - getTypedValue( - params.data?.variants.find( - (item) => item.evaluationId === variant.evaluationId, - )?.output?.result, - ) - )} - + return getTypedValue( + params.data?.variants.find( + (item) => item.evaluationId === variant.evaluationId, + )?.output?.result, ) }, }) @@ -251,9 +261,7 @@ const EvaluationCompareMode: React.FC = () => { headerName: config.name, field: "variants.0.evaluatorConfigs.0.result" as any, ...getFilterParams("text"), - hide: - !evalIds.includes(variant.evaluationId) || - hiddenVariants.includes(config.name), + hide: hiddenVariants.includes(config.name), valueGetter: (params) => { return getTypedValue( params.data?.variants @@ -277,7 +285,7 @@ const EvaluationCompareMode: React.FC = () => { ), - hide: !evalIds.includes(variant.evaluationId) || hiddenVariants.includes("Latency"), + hide: hiddenVariants.includes("Latency"), minWidth: 120, headerName: "Latency", flex: 1, @@ -316,7 +324,7 @@ const EvaluationCompareMode: React.FC = () => { }) return colDefs - }, [rows, showDiff, hiddenVariants, evalIds]) + }, [rows, hiddenVariants, evalIds, selectedCorrectAnswer]) const fetcher = () => { setFetching(true) @@ -435,51 +443,56 @@ const EvaluationCompareMode: React.FC = () => { - - Show Difference: - setShowDiff(showDiff === "show" ? "hide" : "show")} - /> - - - !item.headerName?.startsWith("Input") && - !item.headerName?.includes("Expected Output"), - ) - .reduce((acc, curr) => { - if (curr.headerName && !acc.includes(curr.headerName)) { - acc.push(curr.headerName) - } - return acc - }, [] as string[]) - .map((configs) => ({ - key: configs as string, - label: ( - - - <>{configs} - - ), - })), - onClick: ({key}) => { - handleToggleVariantVisibility(key) - setFilterColsDropdown(true) - }, - className: classes.dropdownMenu, + !item.headerName?.startsWith("Input")), + "headerName", + ), + )} + isOpen={isFilterColsDropdownOpen} + handleOpenChange={handleOpenChangeFilterCols} + shownCols={shownCols} + onClick={({key}) => { + handleToggleVariantVisibility(key) + setIsFilterColsDropdownOpen(true) }} - > - - + /> + {!!rows.length && ( +
+ Apply difference with: + item.startsWith("correctAnswer_")) + .map((key) => ({ + key: key as string, + label: ( + + + <>{removeCorrectAnswerPrefix(key)} + + ), + }))} + buttonText={ + removeCorrectAnswerPrefix(selectedCorrectAnswer[0]) === + "noDiffColumnIsSelected" + ? "Select Ground Truth" + : removeCorrectAnswerPrefix(selectedCorrectAnswer[0]) + } + isOpen={isDiffDropdownOpen} + handleOpenChange={handleOpenChangeDiff} + shownCols={selectedCorrectAnswer} + onClick={({key}) => { + if (key === selectedCorrectAnswer[0]) { + setSelectedCorrectAnswer(["noDiffColumnIsSelected"]) + } else { + setSelectedCorrectAnswer([key]) + } + setIsDiffDropdownOpen(true) + }} + /> +
+ )} - + />
diff --git a/agenta-web/src/components/pages/evaluations/evaluationScenarios/EvaluationScenarios.tsx b/agenta-web/src/components/pages/evaluations/evaluationScenarios/EvaluationScenarios.tsx index e375c46e9d..908ada0e0c 100644 --- a/agenta-web/src/components/pages/evaluations/evaluationScenarios/EvaluationScenarios.tsx +++ b/agenta-web/src/components/pages/evaluations/evaluationScenarios/EvaluationScenarios.tsx @@ -1,15 +1,15 @@ import {useAppTheme} from "@/components/Layout/ThemeContextProvider" import {useAppId} from "@/hooks/useAppId" -import {JSSTheme, _Evaluation, _EvaluationScenario} from "@/lib/Types" +import {CorrectAnswer, JSSTheme, _Evaluation, _EvaluationScenario} from "@/lib/Types" import { deleteEvaluations, fetchAllEvaluationScenarios, fetchAllEvaluators, } from "@/services/evaluations" -import {DeleteOutlined, DownloadOutlined} from "@ant-design/icons" +import {CheckOutlined, DeleteOutlined, DownloadOutlined} from "@ant-design/icons" import {ColDef} from "ag-grid-community" import {AgGridReact} from "ag-grid-react" -import {Space, Spin, Switch, Tag, Tooltip, Typography} from "antd" +import {DropdownProps, Space, Spin, Tag, Tooltip, Typography} from "antd" import {useRouter} from "next/router" import React, {useEffect, useMemo, useRef, useState} from "react" import {createUseStyles} from "react-jss" @@ -23,7 +23,8 @@ import {useAtom} from "jotai" import {evaluatorsAtom} from "@/lib/atoms/evaluation" import CompareOutputDiff from "@/components/CompareOutputDiff/CompareOutputDiff" import {formatCurrency, formatLatency} from "@/lib/helpers/formatters" -import {useLocalStorage} from "usehooks-ts" +import _ from "lodash" +import FilterColumns, {generateFilterItems} from "../FilterColumns/FilterColumns" const useStyles = createUseStyles((theme: JSSTheme) => ({ infoRow: { @@ -56,7 +57,27 @@ const EvaluationScenarios: React.FC = () => { const [evaluators, setEvaluators] = useAtom(evaluatorsAtom) const gridRef = useRef>() const evalaution = scenarios[0]?.evaluation - const [showDiff, setShowDiff] = useLocalStorage("showDiff", "show") + const [selectedCorrectAnswer, setSelectedCorrectAnswer] = useState(["noDiffColumnIsSelected"]) + const [isFilterColsDropdownOpen, setIsFilterColsDropdownOpen] = useState(false) + const [isDiffDropdownOpen, setIsDiffDropdownOpen] = useState(false) + const [hiddenCols, setHiddenCols] = useState([]) + + const handleOpenChangeFilterCols: DropdownProps["onOpenChange"] = (nextOpen, info) => { + if (info.source === "trigger" || nextOpen) { + setIsFilterColsDropdownOpen(nextOpen) + } + } + + const handleOpenChangeDiff: DropdownProps["onOpenChange"] = (nextOpen, info) => { + if (info.source === "trigger" || nextOpen) { + setIsDiffDropdownOpen(nextOpen) + } + } + + const uniqueCorrectAnswers: CorrectAnswer[] = _.uniqBy( + scenarios[0]?.correct_answers || [], + "key", + ) const colDefs = useMemo(() => { const colDefs: ColDef<_EvaluationScenario>[] = [] @@ -67,6 +88,17 @@ const EvaluationScenarios: React.FC = () => { flex: 1, minWidth: 240, headerName: `Input: ${input.name}`, + hide: hiddenCols.includes(`Input: ${input.name}`), + headerComponent: (props: any) => { + return ( + + + {input.name} + Input + + + ) + }, ...getFilterParams(input.type === "number" ? "number" : "text"), field: `inputs.${index}`, valueGetter: (params) => { @@ -75,25 +107,41 @@ const EvaluationScenarios: React.FC = () => { cellRenderer: (params: any) => LongTextCellRenderer(params), }) }) - colDefs.push({ - flex: 1, - minWidth: 300, - headerName: "Expected Output", - field: "correct_answer", - ...getFilterParams("text"), - valueGetter: (params) => { - return params.data?.correct_answer?.toString() || "" - }, - cellRenderer: (params: any) => LongTextCellRenderer(params), + + uniqueCorrectAnswers.forEach((answer: CorrectAnswer, index: number) => { + colDefs.push({ + headerName: answer.key, + hide: hiddenCols.includes(answer.key), + headerComponent: (props: any) => { + return ( + + + {answer.key} + Ground Truth + + + ) + }, + minWidth: 200, + flex: 1, + ...getFilterParams("text"), + valueGetter: (params) => params.data?.correct_answers?.[index]?.value || "", + cellRenderer: (params: any) => LongTextCellRenderer(params), + }) }) evalaution?.variants.forEach((_, index) => { colDefs.push({ flex: 1, minWidth: 300, headerName: "Output", + hide: hiddenCols.includes("Output"), ...getFilterParams("text"), field: `outputs.0`, cellRenderer: (params: any) => { + const correctAnswer = params?.data?.correct_answers?.find( + (item: any) => item.key === selectedCorrectAnswer[0], + ) + const result = params.data?.outputs[index].result if (result && result.type == "error") { return LongTextCellRenderer( @@ -101,12 +149,12 @@ const EvaluationScenarios: React.FC = () => { `${result?.error?.message}\n${result?.error?.stacktrace}`, ) } - return showDiff === "show" + return selectedCorrectAnswer[0] !== "noDiffColumnIsSelected" ? LongTextCellRenderer( params, , ) : LongTextCellRenderer(params) @@ -120,6 +168,7 @@ const EvaluationScenarios: React.FC = () => { scenarios[0]?.evaluators_configs.forEach((config, index) => { colDefs.push({ headerName: config?.name, + hide: hiddenCols.includes(config.name), headerComponent: (props: any) => { const evaluator = evaluators.find((item) => item.key === config?.evaluator_key)! return ( @@ -147,6 +196,7 @@ const EvaluationScenarios: React.FC = () => { flex: 1, minWidth: 120, headerName: "Cost", + hide: hiddenCols.includes("Cost"), ...getFilterParams("text"), valueGetter: (params) => { return params.data?.outputs[0].cost == undefined @@ -159,6 +209,7 @@ const EvaluationScenarios: React.FC = () => { flex: 1, minWidth: 120, headerName: "Latency", + hide: hiddenCols.includes("Latency"), ...getFilterParams("text"), valueGetter: (params) => { return params.data?.outputs[0].latency == undefined @@ -167,7 +218,23 @@ const EvaluationScenarios: React.FC = () => { }, }) return colDefs - }, [evalaution, scenarios, showDiff]) + }, [evalaution, scenarios, selectedCorrectAnswer, hiddenCols]) + + const shownCols = useMemo( + () => + colDefs + .map((item) => item.headerName) + .filter((item) => item !== undefined && !hiddenCols.includes(item)) as string[], + [colDefs], + ) + + const onToggleEvaluatorVisibility = (evalConfigId: string) => { + if (!hiddenCols.includes(evalConfigId)) { + setHiddenCols([...hiddenCols, evalConfigId]) + } else { + setHiddenCols(hiddenCols.filter((item) => item !== evalConfigId)) + } + } const fetcher = () => { setFetching(true) @@ -241,13 +308,48 @@ const EvaluationScenarios: React.FC = () => { - - Show Difference: - setShowDiff(showDiff === "show" ? "hide" : "show")} - /> - + { + onToggleEvaluatorVisibility(key) + setIsFilterColsDropdownOpen(true) + }} + /> + {!!scenarios.length && !!scenarios[0].correct_answers?.length && ( +
+ Apply difference with: + ({ + key: answer.key as string, + label: ( + + + <>{answer.key} + + ), + }))} + buttonText={ + selectedCorrectAnswer[0] === "noDiffColumnIsSelected" + ? "Select Ground Truth" + : selectedCorrectAnswer[0] + } + isOpen={isDiffDropdownOpen} + handleOpenChange={handleOpenChangeDiff} + shownCols={selectedCorrectAnswer} + onClick={({key}) => { + if (key === selectedCorrectAnswer[0]) { + setSelectedCorrectAnswer(["noDiffColumnIsSelected"]) + } else { + setSelectedCorrectAnswer([key]) + } + setIsDiffDropdownOpen(true) + }} + /> +
+ )} diff --git a/agenta-web/src/components/pages/evaluations/evaluators/AdvancedSettings.tsx b/agenta-web/src/components/pages/evaluations/evaluators/AdvancedSettings.tsx new file mode 100644 index 0000000000..9e3c4ea4a4 --- /dev/null +++ b/agenta-web/src/components/pages/evaluations/evaluators/AdvancedSettings.tsx @@ -0,0 +1,95 @@ +import React from "react" +import {Form, Input, InputNumber, Switch, Tooltip, Collapse, theme} from "antd" +import {CaretRightOutlined, InfoCircleOutlined} from "@ant-design/icons" +import {createUseStyles} from "react-jss" +import {Editor} from "@monaco-editor/react" +import {useAppTheme} from "@/components/Layout/ThemeContextProvider" + +const useStyles = createUseStyles((theme: any) => ({ + label: { + display: "flex", + alignItems: "center", + gap: "0.5rem", + }, + editor: { + border: `1px solid ${theme.colorBorder}`, + borderRadius: theme.borderRadius, + overflow: "hidden", + }, +})) + +type AdvancedSettingsProps = { + settings: Record[] +} + +const AdvancedSettings: React.FC = ({settings}) => { + const classes = useStyles() + const {appTheme} = useAppTheme() + const {token} = theme.useToken() + + return ( + } + className={"my-[10px]"} + > + + {settings.map((field) => { + const rules = [ + {required: field.required ?? true, message: "This field is required"}, + ] + + return ( + + {field.label} + {field.description && ( + + + + )} + + } + initialValue={field.default} + rules={rules} + > + {field.type === "string" || field.type === "regex" ? ( + + ) : field.type === "number" ? ( + + ) : field.type === "boolean" || field.type === "bool" ? ( + + ) : field.type === "text" ? ( + + ) : field.type === "code" ? ( + + ) : field.type === "object" ? ( + + ) : null} + + ) + })} + + + ) +} + +export default AdvancedSettings diff --git a/agenta-web/src/components/pages/evaluations/evaluators/EvaluatorCard.tsx b/agenta-web/src/components/pages/evaluations/evaluators/EvaluatorCard.tsx index ddf540e463..bd3550bd0b 100644 --- a/agenta-web/src/components/pages/evaluations/evaluators/EvaluatorCard.tsx +++ b/agenta-web/src/components/pages/evaluations/evaluators/EvaluatorCard.tsx @@ -84,22 +84,14 @@ const EvaluatorCard: React.FC = ({evaluatorConfig, onEdit, onSuccessDelet return ( , - , - ] - } + actions={[ + , + , + ]} data-cy="evaluator-card" >
diff --git a/agenta-web/src/components/pages/evaluations/evaluators/NewEvaluatorModal.tsx b/agenta-web/src/components/pages/evaluations/evaluators/NewEvaluatorModal.tsx index 6ea154af35..5fd8fc1bf8 100644 --- a/agenta-web/src/components/pages/evaluations/evaluators/NewEvaluatorModal.tsx +++ b/agenta-web/src/components/pages/evaluations/evaluators/NewEvaluatorModal.tsx @@ -10,7 +10,7 @@ import { } from "@/services/evaluations" import {ArrowLeftOutlined, EditOutlined, InfoCircleOutlined, PlusOutlined} from "@ant-design/icons" import {Editor} from "@monaco-editor/react" -import {Button, Form, Input, InputNumber, Modal, Switch, Table, Tag, Tooltip, theme} from "antd" +import {Button, Form, Input, InputNumber, Modal, Switch, Table, Tooltip, theme} from "antd" import {Rule} from "antd/es/form" import {useAtom} from "jotai" import Image from "next/image" @@ -18,6 +18,7 @@ import Link from "next/link" import React, {useEffect, useMemo, useState} from "react" import {createUseStyles} from "react-jss" import {ColumnsType} from "antd/es/table" +import AdvancedSettings from "./AdvancedSettings" const useStyles = createUseStyles((theme: JSSTheme) => ({ label: { @@ -124,6 +125,7 @@ const DynamicFormField: React.FC = ({ const {appTheme} = useAppTheme() const classes = useStyles() const {token} = theme.useToken() + const [showAdvancedSettings, setShowAdvancedSettings] = useState(false) const rules: Rule[] = [{required: required ?? true, message: "This field is required"}] if (type === "regex") @@ -152,48 +154,51 @@ const DynamicFormField: React.FC = ({ return ( <> - - {label} - {description && ( - - - - )} -
- } - initialValue={defaultVal} - rules={rules} - > - {type === "string" || type === "regex" ? ( - - ) : type === "number" ? ( - - ) : type === "boolean" || type === "bool" ? ( - - ) : type === "text" ? ( - - ) : type === "code" ? ( - - ) : type === "object" ? ( - - ) : null} - + {label !== "Correct Answer" && ( + + {label} + {description && ( + + + + )} + + } + initialValue={defaultVal} + rules={rules} + > + {type === "string" || type === "regex" ? ( + + ) : type === "number" ? ( + + ) : type === "boolean" || type === "bool" ? ( + + ) : type === "text" ? ( + + ) : type === "code" ? ( + + ) : type === "object" ? ( + + ) : null} + + )} + {ExternalHelpInfo} ) @@ -218,7 +223,7 @@ const NewEvaluatorModal: React.FC = ({ ...props }) => { const classes = useStyles() - const evaluators = useAtom(evaluatorsAtom)[0].filter((item) => !item.direct_use) + const evaluators = useAtom(evaluatorsAtom)[0] const [selectedEval, setSelectedEval] = useState(null) const [submitLoading, setSubmitLoading] = useState(false) const [searchTerm, setSearchTerm] = useState("") @@ -244,6 +249,7 @@ const NewEvaluatorModal: React.FC = ({ .map((key) => ({ key, ...selectedEval?.settings_template[key]!, + advanced: selectedEval?.settings_template[key]?.advanced || false, })), [selectedEval], ) @@ -258,13 +264,28 @@ const NewEvaluatorModal: React.FC = ({ } }, [newEvalModalConfigOpen]) + const advancedSettingsFields = evalFields.filter((field) => field.advanced) + const basicSettingsFields = evalFields.filter((field) => !field.advanced) + console.log(evalFields) + console.log(basicSettingsFields) + const onSubmit = (values: CreateEvaluationConfigData) => { setSubmitLoading(true) if (!selectedEval?.key) throw new Error("No selected key") + const settingsValues = values.settings_values || {} + + if ( + !settingsValues.correct_answer_key && + selectedEval.settings_template.correct_answer_key.default + ) { + settingsValues["correct_answer_key"] = + selectedEval.settings_template.correct_answer_key.default + } + const data = { ...values, evaluator_key: selectedEval.key, - settings_values: values.settings_values || {}, + settings_values: settingsValues, } ;(editMode ? updateEvaluatorConfig(initialValues?.id!, data) @@ -394,7 +415,7 @@ const NewEvaluatorModal: React.FC = ({ - {evalFields.map((field) => ( + {basicSettingsFields.map((field) => ( = ({ /> ))} + {advancedSettingsFields.length > 0 && ( + + )} +
{!editMode && ( diff --git a/agenta-web/src/lib/Types.ts b/agenta-web/src/lib/Types.ts index 93915a99cb..c742244029 100644 --- a/agenta-web/src/lib/Types.ts +++ b/agenta-web/src/lib/Types.ts @@ -339,6 +339,7 @@ export interface EvaluationSettingsTemplate { min?: number max?: number required?: boolean + advanced?: boolean } export interface Evaluator { @@ -383,6 +384,11 @@ export enum EvaluationStatusType { ERROR = "error", } +export interface CorrectAnswer { + key: string + value: string +} + export interface _Evaluation { id: string appId: string @@ -421,7 +427,7 @@ export interface _EvaluationScenario { evaluators_configs: EvaluatorConfig[] inputs: (TypedValue & {name: string})[] outputs: {result: TypedValue; cost?: number; latency?: number}[] - correct_answer?: string + correct_answers?: CorrectAnswer[] is_pinned?: boolean note?: string results: {evaluator_config: string; result: TypedValue & {error: null | EvaluationError}}[] @@ -452,7 +458,6 @@ export interface AnnotationScenario { export type ComparisonResultRow = { inputs: {name: string; value: string}[] - correctAnswer: string variants: { variantId: string variantName: string @@ -464,7 +469,7 @@ export type ComparisonResultRow = { }[] }[] id: string -} +} & {[key: string]: any} export type RequestMetadata = { cost: number diff --git a/agenta-web/src/lib/helpers/evaluate.ts b/agenta-web/src/lib/helpers/evaluate.ts index 55edfe758d..915bc44ed0 100644 --- a/agenta-web/src/lib/helpers/evaluate.ts +++ b/agenta-web/src/lib/helpers/evaluate.ts @@ -338,3 +338,7 @@ const getCustomComparator = (type: CellDataType) => (valueA: string, valueB: str if (type === "number") return getNumber(valueA) - getNumber(valueB) return 0 } + +export const removeCorrectAnswerPrefix = (str: string) => { + return str.replace(/^correctAnswer_/, "") +} diff --git a/agenta-web/src/services/evaluations/index.ts b/agenta-web/src/services/evaluations/index.ts index c672840052..625c7d4645 100644 --- a/agenta-web/src/services/evaluations/index.ts +++ b/agenta-web/src/services/evaluations/index.ts @@ -25,6 +25,7 @@ import dayjs from "dayjs" import {loadTestset} from "@/lib/services/api" import {runningStatuses} from "@/components/pages/evaluations/cellRenderers/cellRenderers" import {calcEvalDuration} from "@/lib/helpers/evaluate" +import _ from "lodash" //Prefix convention: // - fetch: GET single entity from server @@ -225,6 +226,11 @@ export const fetchAllComparisonResults = async (evaluationIds: string[]) => { const inputNames = Array.from(inputsNameSet) const inputValuesSet = new Set() const variants = scenarioGroups.map((group) => group[0].evaluation.variants[0]) + const correctAnswers = _.uniqBy( + scenarioGroups.map((group) => group[0].correct_answers).flat(), + "key", + ) + for (const data of testset.csvdata) { const inputValues = inputNames .filter((name) => data[name] !== undefined) @@ -238,7 +244,9 @@ export const fetchAllComparisonResults = async (evaluationIds: string[]) => { inputs: inputNames .map((name) => ({name, value: data[name]})) .filter((ip) => ip.value !== undefined), - correctAnswer: data.correct_answer || "", + ...correctAnswers.reduce((acc, curr) => { + return {...acc, [`correctAnswer_${curr?.key}`]: data[curr?.key!]} + }, {}), variants: variants.map((variant, ix) => { const group = scenarioGroups[ix] const scenario = group.find((scenario) =>