From 9023ffc882a022a6732dbe430b4cfa9b3579a5bf Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Mon, 13 Jan 2025 18:20:46 +0000 Subject: [PATCH 01/64] Bug fixes for deployment --- .vscode/tasks.json | 2 +- README.md | 2 +- adi_function_app/.env | 12 - .../text_2_sql_column_value_store.py | 25 +- .../text_2_sql_schema_store.py | 2 +- .../.funcignore | 0 .../GETTING_STARTED.md | 2 +- .../README.md | 0 .../adi_2_ai_search.py | 0 .../environment.py | 0 image_processing/figure_analysis.py | 182 ++++++ .../function_app.py | 2 +- .../host.json | 0 .../images/Indexing vs Indexing with ADI.png | Bin .../key_phrase_extraction.py | 0 image_processing/layout_analysis.py | 585 ++++++++++++++++++ image_processing/layout_and_figure_merger.py | 123 ++++ image_processing/layout_holders.py | 51 ++ .../local.settings.json | 0 .../mark_up_cleaner.py | 30 +- .../pyproject.toml | 19 +- .../semantic_text_chunker.py | 39 +- .../storage_account.py | 0 pyproject.toml | 2 +- uv.lock | 424 ++++++++----- 25 files changed, 1287 insertions(+), 215 deletions(-) delete mode 100644 adi_function_app/.env rename {adi_function_app => image_processing}/.funcignore (100%) rename {adi_function_app => image_processing}/GETTING_STARTED.md (90%) rename {adi_function_app => image_processing}/README.md (100%) rename {adi_function_app => image_processing}/adi_2_ai_search.py (100%) rename {adi_function_app => image_processing}/environment.py (100%) create mode 100644 image_processing/figure_analysis.py rename {adi_function_app => image_processing}/function_app.py (98%) rename {adi_function_app => image_processing}/host.json (100%) rename {adi_function_app => image_processing}/images/Indexing vs Indexing with ADI.png (100%) rename {adi_function_app => image_processing}/key_phrase_extraction.py (100%) create mode 100644 image_processing/layout_analysis.py create mode 100644 image_processing/layout_and_figure_merger.py create mode 100644 image_processing/layout_holders.py rename {adi_function_app => image_processing}/local.settings.json (100%) rename {adi_function_app => image_processing}/mark_up_cleaner.py (84%) rename {adi_function_app => image_processing}/pyproject.toml (71%) rename {adi_function_app => image_processing}/semantic_text_chunker.py (94%) rename {adi_function_app => image_processing}/storage_account.py (100%) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 359b7107..dd3b781a 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -5,7 +5,7 @@ "isBackground": true, "label": "func: host start", "options": { - "cwd": "${workspaceFolder}/ai_search_with_adi_function_app" + "cwd": "${workspaceFolder}/ai_search_with_image_processing" }, "problemMatcher": "$func-python-watch", "type": "func" diff --git a/README.md b/README.md index 8e37f5d4..0e0622fc 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ It is intended that the plugins and skills provided in this repository, are adap ## Components - `./text_2_sql` contains an three Multi-Shot implementations for Text2SQL generation and querying which can be used to answer questions backed by a database as a knowledge base. A **prompt based** and **vector based** approach are shown, both of which exhibit great performance in answering sql queries. Additionally, a further iteration on the vector based approach is shown which uses a **query cache** to further speed up generation. With these plugins, your RAG application can now access and pull data from any SQL table exposed to it to answer questions. -- `./adi_function_app` contains code for linking **Azure Document Intelligence** with AI Search to process complex documents with charts and images, and uses **multi-modal models (gpt4o)** to interpret and understand these. With this custom skill, the RAG application can **draw insights from complex charts** and images during the vector search. This function app also contains a **Semantic Text Chunking** method that aims to intelligently group similar sentences, retaining figures and tables together, whilst separating out distinct sentences. +- `./image_processing` contains code for linking **Azure Document Intelligence** with AI Search to process complex documents with charts and images, and uses **multi-modal models (gpt4o)** to interpret and understand these. With this custom skill, the RAG application can **draw insights from complex charts** and images during the vector search. This function app also contains a **Semantic Text Chunking** method that aims to intelligently group similar sentences, retaining figures and tables together, whilst separating out distinct sentences. - `./deploy_ai_search` provides an easy Python based utility for deploying an index, indexer and corresponding skillset for AI Search and for Text2SQL. The above components have been successfully used on production RAG projects to increase the quality of responses. diff --git a/adi_function_app/.env b/adi_function_app/.env deleted file mode 100644 index eb0ec417..00000000 --- a/adi_function_app/.env +++ /dev/null @@ -1,12 +0,0 @@ -FunctionApp__ClientId= -IdentityType= # system_assigned or user_assigned or key -OpenAI__ApiKey= -OpenAI__Endpoint= -OpenAI__MultiModalDeployment= -OpenAI__ApiVersion= -AIService__DocumentIntelligence__Endpoint= -AIService__DocumentIntelligence__Key= -AIService__Language__Endpoint= -AIService__Language__Key= -StorageAccount__Endpoint= -StorageAccount__ConnectionString= diff --git a/deploy_ai_search/src/deploy_ai_search/text_2_sql_column_value_store.py b/deploy_ai_search/src/deploy_ai_search/text_2_sql_column_value_store.py index cb759a62..36c53e09 100644 --- a/deploy_ai_search/src/deploy_ai_search/text_2_sql_column_value_store.py +++ b/deploy_ai_search/src/deploy_ai_search/text_2_sql_column_value_store.py @@ -20,6 +20,7 @@ ) import os from text_2_sql_core.utils.database import DatabaseEngine +from text_2_sql_core.connectors.factory import ConnectorFactory class Text2SqlColumnValueStoreAISearch(AISearch): @@ -43,25 +44,9 @@ def __init__( os.environ["Text2Sql__DatabaseEngine"].upper() ] - self.parsing_mode = BlobIndexerParsingMode.JSON_LINES - - @property - def excluded_fields_for_database_engine(self): - """A method to get the excluded fields for the database engine.""" - - all_engine_specific_fields = ["Warehouse", "Database", "Catalog"] - if self.database_engine == DatabaseEngine.SNOWFLAKE: - engine_specific_fields = ["Warehouse", "Database"] - elif self.database_engine == DatabaseEngine.TSQL: - engine_specific_fields = ["Database"] - elif self.database_engine == DatabaseEngine.DATABRICKS: - engine_specific_fields = ["Catalog"] + self.database_connector = ConnectorFactory.get_database_connector() - return [ - field - for field in all_engine_specific_fields - if field not in engine_specific_fields - ] + self.parsing_mode = BlobIndexerParsingMode.JSON_LINES def get_index_fields(self) -> list[SearchableField]: """This function returns the index fields for sql index. @@ -123,7 +108,7 @@ def get_index_fields(self) -> list[SearchableField]: fields = [ field for field in fields - if field.name not in self.excluded_fields_for_database_engine + if field.name not in self.database_connector.excluded_engine_specific_fields ] return fields @@ -238,7 +223,7 @@ def get_indexer(self) -> SearchIndexer: field_mapping for field_mapping in indexer.output_field_mappings if field_mapping.target_field_name - not in self.excluded_fields_for_database_engine + not in self.database_connector.excluded_engine_specific_fields ] return indexer diff --git a/deploy_ai_search/src/deploy_ai_search/text_2_sql_schema_store.py b/deploy_ai_search/src/deploy_ai_search/text_2_sql_schema_store.py index 28d59b3f..47a59bde 100644 --- a/deploy_ai_search/src/deploy_ai_search/text_2_sql_schema_store.py +++ b/deploy_ai_search/src/deploy_ai_search/text_2_sql_schema_store.py @@ -346,7 +346,7 @@ def get_indexer(self) -> SearchIndexer: field_mapping for field_mapping in indexer.output_field_mappings if field_mapping.target_field_name - not in self.excluded_fields_for_database_engine + not in self.database_connector.excluded_engine_specific_fields ] return indexer diff --git a/adi_function_app/.funcignore b/image_processing/.funcignore similarity index 100% rename from adi_function_app/.funcignore rename to image_processing/.funcignore diff --git a/adi_function_app/GETTING_STARTED.md b/image_processing/GETTING_STARTED.md similarity index 90% rename from adi_function_app/GETTING_STARTED.md rename to image_processing/GETTING_STARTED.md index 331158ff..f4e52223 100644 --- a/adi_function_app/GETTING_STARTED.md +++ b/image_processing/GETTING_STARTED.md @@ -4,7 +4,7 @@ To get started, perform the following steps: 1. Setup Azure OpenAI in your subscription with **gpt-4o-mini** & an embedding model, an Python Function App, AI Search and a storage account. 2. Clone this repository and deploy the AI Search rag documents indexes from `deploy_ai_search`. -3. Run `uv sync` within the adi_function_app directory to install dependencies. +3. Run `uv sync` within the image_processing directory to install dependencies. 4. Configure the environment variables of the function app based on the provided sample 5. Package your Azure Function and upload to your Function App 6. Upload a document for indexing or send a direct HTTP request to the Azure Function. diff --git a/adi_function_app/README.md b/image_processing/README.md similarity index 100% rename from adi_function_app/README.md rename to image_processing/README.md diff --git a/adi_function_app/adi_2_ai_search.py b/image_processing/adi_2_ai_search.py similarity index 100% rename from adi_function_app/adi_2_ai_search.py rename to image_processing/adi_2_ai_search.py diff --git a/adi_function_app/environment.py b/image_processing/environment.py similarity index 100% rename from adi_function_app/environment.py rename to image_processing/environment.py diff --git a/image_processing/figure_analysis.py b/image_processing/figure_analysis.py new file mode 100644 index 00000000..0a674285 --- /dev/null +++ b/image_processing/figure_analysis.py @@ -0,0 +1,182 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +import json +import logging +import os +import azure.functions as func +from azure.identity import DefaultAzureCredential, get_bearer_token_provider +import asyncio +from openai import ( + AsyncAzureOpenAI, + OpenAIError, + APIError, + APIStatusError, + BadRequestError, +) +from tenacity import retry, stop_after_attempt, wait_exponential +from layout_holders import FigureHolder + + +class FigureAnalysis: + @retry( + stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=1, max=10) + ) + async def understand_image_with_gptv(self, figure: FigureHolder) -> dict: + """ + Generates a description for an image using the GPT-4V model. + + Parameters: + - image_base64 (str): image file. + - caption (str): The caption for the image. + + Returns: + - img_description (str): The generated description for the image. + """ + + MAX_TOKENS = 2000 + api_version = os.environ["AZURE_OPENAI_API_VERSION"] + model = os.environ["OPENAI_MAIN_DEPLOYMENT_NAME"] + + token_provider = get_bearer_token_provider( + DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" + ) + + system_prompt = """You are an expert in technical image analysis. Your task is to provided analysis of images. You should FOCUS on what info can be inferred from the image and the meaning of the data inside the image. Draw actionable insights and conclusions from the image. Do not describe the image in a general way or describe the image in a way that is not useful for decision-making. + + If the image is a chart for instance, you should describe the data trends, patterns, and insights that can be drawn from the chart. For example, you could describe the increase or decrease in sales over time, the peak sales period, or the sales performance of a particular product. + + If the image is a map, you should describe the geographical features, landmarks, and any other relevant information that can be inferred from the map. + + If the image is a diagram, you should describe the components, relationships, and any other relevant information that can be inferred from the diagram. + + Include any data points, labels, and other relevant information that can be inferred from the image. + + Provide a well-structured, detailed, and actionable analysis of the image. Focus on extracting data and information that can be inferred from the image. + + IMPORTANT: If the provided image is a logo or photograph, simply return 'Irrelevant Image'.""" + + user_input = "Perform technical analysis on this image. Provide a well-structured, description." + + if figure.caption is not None and len(figure.caption) > 0: + user_input += " (note: it has the following caption: {})".format( + figure.caption + ) + + try: + async with AsyncAzureOpenAI( + api_key=None, + api_version=api_version, + azure_ad_token_provider=token_provider, + azure_endpoint=os.environ.get("AZURE_OPENAI_ENDPOINT"), + ) as client: + # We send both image caption and the image body to GPTv for better understanding + response = await client.chat.completions.create( + model=model, + messages=[ + { + "role": "system", + "content": system_prompt, + }, + { + "role": "user", + "content": [ + { + "type": "text", + "text": user_input, + }, + { + "type": "image_url", + "image_url": { + "url": f"data:image/png;base64,{figure.data}" + }, + }, + ], + }, + ], + max_tokens=MAX_TOKENS, + ) + except (OpenAIError, APIError, APIStatusError, BadRequestError) as e: + logging.error(f"Failed to analyse image. Error: {e}") + + if "ResponsibleAIPolicyViolation" in e.message: + logging.error("Responsible AI Policy Violation") + figure.description = "Irrelevant Image" + + return figure + + raise e + else: + logging.info(f"Response: {response}") + + figure.description = response.choices[0].message.content + + logging.info(f"Image Description: {figure.description}") + + return figure + + async def analyse(self, record: dict) -> dict: + """ + Analyse the image and generate a description for it. + + Parameters: + - record (dict): The record containing the image and its caption. + + Returns: + - record (dict): The record containing the image, its caption, and the generated description. + """ + + logging.info(f"Record: {record}") + figure = FigureHolder(**record["data"]["figure"]) + + try: + updated_data = await self.understand_image_with_gptv(figure) + logging.info(f"Updated Data: {updated_data}") + except Exception as e: + logging.error(f"Failed to analyse image. Error: {e}") + logging.error(f"Failed input: {record}") + return { + "recordId": record["recordId"], + "data": {}, + "errors": [ + { + "message": "Failed to analyse image. Pass a valid source in the request body.", + } + ], + "warnings": None, + } + else: + return { + "recordId": record["recordId"], + "data": {"updated_figure": updated_data.model_dump()}, + "errors": None, + "warnings": None, + } + + +async def main(req: func.HttpRequest) -> func.HttpResponse: + try: + req_body = req.get_json() + values = req_body.get("values") + except ValueError: + return func.HttpResponse( + "Please valid Custom Skill Payload in the request body", status_code=400 + ) + else: + logging.info("Input Values: %s", values) + + record_tasks = [] + + figure_analysis = FigureAnalysis() + + for value in values: + record_tasks.append(asyncio.create_task(figure_analysis.analyse(value))) + + results = await asyncio.gather(*record_tasks) + logging.info("Results: %s", results) + + return func.HttpResponse( + json.dumps({"values": results}), + status_code=200, + mimetype="application/json", + ) diff --git a/adi_function_app/function_app.py b/image_processing/function_app.py similarity index 98% rename from adi_function_app/function_app.py rename to image_processing/function_app.py index 5188023e..8bc9482a 100644 --- a/adi_function_app/function_app.py +++ b/image_processing/function_app.py @@ -6,7 +6,7 @@ import asyncio from adi_2_ai_search import process_adi_2_ai_search -from adi_function_app.mark_up_cleaner import process_mark_up_cleaner +from image_processing.mark_up_cleaner import process_mark_up_cleaner from key_phrase_extraction import process_key_phrase_extraction from semantic_text_chunker import process_semantic_text_chunker, SemanticTextChunker diff --git a/adi_function_app/host.json b/image_processing/host.json similarity index 100% rename from adi_function_app/host.json rename to image_processing/host.json diff --git a/adi_function_app/images/Indexing vs Indexing with ADI.png b/image_processing/images/Indexing vs Indexing with ADI.png similarity index 100% rename from adi_function_app/images/Indexing vs Indexing with ADI.png rename to image_processing/images/Indexing vs Indexing with ADI.png diff --git a/adi_function_app/key_phrase_extraction.py b/image_processing/key_phrase_extraction.py similarity index 100% rename from adi_function_app/key_phrase_extraction.py rename to image_processing/key_phrase_extraction.py diff --git a/image_processing/layout_analysis.py b/image_processing/layout_analysis.py new file mode 100644 index 00000000..a7c7a645 --- /dev/null +++ b/image_processing/layout_analysis.py @@ -0,0 +1,585 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. +# This code originates from: https://github.com/microsoft/dstoolkit-text2sql-and-imageprocessing + +import json +import logging +import os +import urllib +import azure.functions as func +import tempfile +from azure.storage.blob.aio import BlobServiceClient +from azure.identity import DefaultAzureCredential +import base64 +from azure.ai.documentintelligence.aio import DocumentIntelligenceClient +from azure.ai.documentintelligence.models import ( + DocumentContentFormat, + AnalyzeOutputOption, + AnalyzeDocumentRequest, +) +import asyncio +from typing import Union +from tenacity import retry, stop_after_attempt, wait_exponential +from layout_holders import ( + FigureHolder, + LayoutHolder, + PageWiseContentHolder, + NonPageWiseContentHolder, +) + + +class StorageAccountHelper: + """Helper class for interacting with Azure Blob Storage.""" + + @property + def account_url(self) -> str: + """Get the account URL of the Azure Blob Storage.""" + storage_account_name = os.environ.get("DATA_STORAGE_ACCOUNT_NAME") + return f"https://{storage_account_name}.blob.core.windows.net" + + async def get_client(self): + """Get the BlobServiceClient object.""" + + credential = DefaultAzureCredential() + return BlobServiceClient(account_url=self.account_url, credential=credential) + + async def add_metadata_to_blob( + self, source: str, container: str, metadata: dict + ) -> None: + """Add metadata to the blob. + + Args + source (str): The source of the blob. + container (str): The container of the blob. + metadata (dict): The metadata to add to the blob.""" + + blob = urllib.parse.unquote_plus(source) + + blob_service_client = await self.get_client() + async with blob_service_client: + async with blob_service_client.get_blob_client( + container=container, blob=blob + ) as blob_client: + await blob_client.set_blob_metadata(metadata) + + logging.info("Metadata Added") + + async def upload_blob( + self, container: str, blob: str, data, content_type: str + ) -> str: + """Upload the file to the Azure Blob Storage. + + Args: + container (str): The container of the blob. + blob (str): The blob name. + data (bytes): The data to upload. + + Returns: + str: url of the uploaded blob.""" + + logging.info("Uploading Blob...") + logging.info(f"Container: {container}") + logging.info(f"Blob: {blob}") + + blob_service_client = await self.get_client() + async with blob_service_client: + async with blob_service_client.get_blob_client( + container=container, blob=blob + ) as blob_client: + await blob_client.upload_blob( + data, + overwrite=True, + blob_type="BlockBlob", + content_type=content_type, + ) + + return blob_client.url + + async def download_blob_to_temp_dir( + self, source: str, container: str, target_file_name + ) -> tuple[str, dict]: + """Download the file from the Azure Blob Storage. + + Args: + source (str): The source of the blob. + container (str): The container of the blob. + target_file_name (str): The target file name.""" + + blob = urllib.parse.unquote_plus(source) + + blob_service_client = await self.get_client() + async with blob_service_client: + async with blob_service_client.get_blob_client( + container=container, blob=blob + ) as blob_client: + blob_download = await blob_client.download_blob() + blob_contents = await blob_download.readall() + + blob_properties = await blob_client.get_blob_properties() + + logging.info("Blob Downloaded") + # Get the temporary directory + temp_dir = tempfile.gettempdir() + + # Define the temporary file path + temp_file_path = os.path.join(temp_dir, target_file_name) + + # Write the blob contents to the temporary file + with open(temp_file_path, "wb") as temp_file: + temp_file.write(blob_contents) + + return temp_file_path, blob_properties.metadata + + +class LayoutAnalysis: + def __init__( + self, + page_wise: bool = False, + extract_figures: bool = True, + record_id: int = None, + source: str = None, + ): + self.result = None + self.operation_id = None + + self.page_wise = page_wise + self.extract_figures = extract_figures + + self.record_id = record_id + self.source = source + + self.blob = None + self.container = None + self.file_extension = None + self.target_file_name = None + + def extract_file_info(self): + """Extract the file information from the source.""" + source_parts = self.source.split("/") + self.blob = "/".join(source_parts[4:]) + logging.info(f"Blob: {self.blob}") + + self.container = source_parts[3] + + self.images_container = f"{self.container}-images" + + self.file_extension = self.blob.split(".")[-1] + + self.target_file_name = f"{self.record_id}.{self.file_extension}" + + @retry( + stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=1, max=10) + ) + async def download_figure_image(self, figure_id: str) -> bytearray: + """Download the image associated with a figure extracted by the Azure Document Intelligence service. + + Args: + ----- + model_id (str): The model ID used for the analysis. + operation_id (str): The operation ID of the analysis. + figure_id (str): The ID of the figure to download. + + Returns: + -------- + bytes: The image associated with the figure.""" + + logging.info(f"Downloading Image for Figure ID: {figure_id}") + document_intelligence_client = await self.get_document_intelligence_client() + try: + async with document_intelligence_client: + response = await document_intelligence_client.get_analyze_result_figure( + model_id=self.result.model_id, + result_id=self.operation_id, + figure_id=figure_id, + ) + + logging.info(f"Response: {response}") + + full_bytes = bytearray() + async for chunk in response: + full_bytes.extend(chunk) + except Exception as e: + logging.error(e) + logging.error(f"Failed to download image for Figure ID: {figure_id}") + raise e + + return full_bytes + + async def process_figures_from_extracted_content( + self, + text_holder: LayoutHolder, + ) -> Union[str, dict]: + """Process the figures extracted from the content using ADI and send them for analysis. + + Args: + ----- + result (AnalyzeResult): The result of the document analysis. + operation_id (str): The operation ID of the analysis. + container_and_blob (str): The container and blob of the document. + markdown_content (str): The extracted content in Markdown format. + page_number (int): The page number to process. If None, all pages are processed. + page_offset (int): The offset of the page. + + Returns: + -------- + str: The updated Markdown content with the figure descriptions. + dict: A mapping of the FigureId to the stored Uri in blob storage.""" + + figure_processing_datas = [] + download_image_tasks = [] + figure_upload_tasks = [] + + storage_account_helper = await self.get_storage_account_helper() + if self.result.figures: + for figure in self.result.figures: + if figure.id is None: + continue + + for region in figure.bounding_regions: + if ( + text_holder.page_number is not None + and region.page_number != text_holder.page_number + ): + continue + + logging.info(f"Figure ID: {figure.id}") + download_image_tasks.append( + self.download_figure_image( + figure_id=figure.id, + ) + ) + + image_blob = f"{self.blob}/{figure.id}.png" + + caption = ( + figure.caption.content if figure.caption is not None else None + ) + + logging.info(f"Figure Caption: {caption}") + uri = "{}/{}/{}".format( + storage_account_helper.account_url, + self.images_container, + image_blob, + ) + + offset = figure.spans[0].offset - text_holder.page_offsets + + image_processing_data = FigureHolder( + figure_id=figure.id, + container=self.images_container, + image_blob=image_blob, + caption=caption, + offset=offset, + length=figure.spans[0].length, + page_number=region.page_number, + uri=uri, + ) + + figure_processing_datas.append(image_processing_data) + + break + + logging.info("Running image download tasks") + image_responses = await asyncio.gather(*download_image_tasks) + logging.info("Finished image download tasks") + + for figure_processing_data, response in zip( + figure_processing_datas, image_responses + ): + base_64_image = base64.b64encode(response).decode("utf-8") + + image_data = base64.b64decode(base_64_image) + + figure_processing_data.data = base_64_image + + figure_upload_tasks.append( + storage_account_helper.upload_blob( + figure_processing_data.container, + figure_processing_data.image_blob, + image_data, + "image/png", + ) + ) + + text_holder.figures.append(figure_processing_data) + + await asyncio.gather(*figure_upload_tasks) + + def create_page_wise_content(self) -> list[LayoutHolder]: + """Create a list of page-wise content extracted by the Azure Document Intelligence service. + + Args: + ----- + result (AnalyzeResult): The result of the document analysis. + + Returns: + -------- + list: A list of page-wise content extracted by the Azure Document Intelligence service. + """ + + page_wise_contents = [] + + for page in self.result.pages: + page_content = self.result.content[ + page.spans[0]["offset"] : page.spans[0]["offset"] + + page.spans[0]["length"] + ] + + page_wise_contents.append( + LayoutHolder( + content=page_content, + page_number=page.page_number, + page_offsets=page.spans[0]["offset"], + ) + ) + + return page_wise_contents + + async def get_document_intelligence_client(self) -> DocumentIntelligenceClient: + """Get the Azure Document Intelligence client. + + Returns: + -------- + DocumentIntelligenceClient: The Azure Document Intelligence client.""" + + credential = DefaultAzureCredential() + + return DocumentIntelligenceClient( + endpoint=os.environ["COGNITIVE_SERVICES_ENDPOINT"], + credential=credential, + ) + + async def get_storage_account_helper(self) -> StorageAccountHelper: + """Get the Storage Account Helper. + + Returns: + -------- + StorageAccountHelper: The Storage Account Helper.""" + + return StorageAccountHelper() + + @retry( + stop=stop_after_attempt(2), wait=wait_exponential(multiplier=1, min=1, max=10) + ) + async def analyse_document(self, file_path: str): + """Analyse a document using the Azure Document Intelligence service. + + Args: + ----- + file_path (str): The path to the document to analyse. + + Returns: + -------- + AnalyzeResult: The result of the document analysis. + str: The operation ID of the analysis. + """ + with open(file_path, "rb") as f: + file_read = f.read() + + document_intelligence_client = await self.get_document_intelligence_client() + async with document_intelligence_client: + poller = await document_intelligence_client.begin_analyze_document( + model_id="prebuilt-layout", + body=AnalyzeDocumentRequest(bytes_source=file_read), + output_content_format=DocumentContentFormat.MARKDOWN, + output=[AnalyzeOutputOption.FIGURES], + ) + + self.result = await poller.result() + + self.operation_id = poller.details["operation_id"] + + if ( + self.result is None + or self.result.content is None + or self.result.pages is None + ): + raise ValueError( + "Failed to analyze the document with Azure Document Intelligence." + ) + + async def analyse(self): + """Orchestrate the analysis of the document using the Azure Document Intelligence service. + + Args: + ----- + record_id (int): The record ID. + source (str): The source of the document to analyse.""" + try: + self.extract_file_info() + storage_account_helper = await self.get_storage_account_helper() + temp_file_path, _ = await storage_account_helper.download_blob_to_temp_dir( + self.blob, self.container, self.target_file_name + ) + logging.info(temp_file_path) + except Exception as e: + logging.error(f"Failed to download the blob: {e}") + return { + "recordId": self.record_id, + "data": {}, + "errors": [ + { + "message": f"Failed to download the blob. Check the source and try again. {e}", + } + ], + "warnings": None, + } + + try: + await self.analyse_document(temp_file_path) + except Exception as e: + logging.error(e) + logging.error( + "Failed to analyse %s with Azure Document Intelligence.", self.blob + ) + return { + "recordId": self.record_id, + "data": {}, + "errors": [ + { + "message": f"Failed to analyze the document with Azure Document Intelligence. Check the logs and try again. {e}", + } + ], + "warnings": None, + } + + try: + if self.page_wise: + cleaned_text_holders = [] + page_wise_text_holders = self.create_page_wise_content() + content_with_figures_tasks = [] + + for page_wise_text_holder in page_wise_text_holders: + if self.extract_figures: + content_with_figures_tasks.append( + self.process_figures_from_extracted_content( + page_wise_text_holder + ) + ) + + if len(page_wise_text_holder.content) == 0: + logging.error( + "No content found in the cleaned result for slide %s.", + page_wise_text_holder.page_number, + ) + else: + cleaned_text_holders.append(page_wise_text_holder) + + if self.extract_figures: + await asyncio.gather(*content_with_figures_tasks) + + output_record = PageWiseContentHolder( + page_wise_layout=cleaned_text_holders + ) + else: + text_content = LayoutHolder( + content=self.result.content, page_number=None, page_offsets=0 + ) + + if self.extract_figures: + await self.process_figures_from_extracted_content(text_content) + + output_record = NonPageWiseContentHolder(layout=text_content) + + except Exception as e: + logging.error(e) + logging.error(f"Failed to process the extracted content: {e}") + return { + "recordId": self.record_id, + "data": {}, + "errors": [ + { + "message": f"Failed to process the extracted content. Check the logs and try again. {e}", + } + ], + "warnings": None, + } + + output_holder = { + "recordId": self.record_id, + "data": output_record.model_dump(), + "errors": None, + "warnings": None, + } + + logging.info(f"final output: {output_holder}") + + return output_holder + + +async def process_layout_analysis( + record: dict, page_wise: bool = False, extract_figures: bool = True +) -> dict: + """Process the extracted content from the Azure Document Intelligence service and prepare it for Azure Search. + + Args: + ----- + record (dict): The record containing the extracted content. + page_wise (bool): Whether to chunk the content by page. + + Returns: + -------- + dict: The processed content ready for Azure Search.""" + logging.info("Python HTTP trigger function processed a request.") + + try: + source = record["data"]["source"] + record_id = record["recordId"] + logging.info(f"Request Body: {record}") + + layout_analysis = LayoutAnalysis( + page_wise=page_wise, + extract_figures=extract_figures, + record_id=record_id, + source=source, + ) + + return await layout_analysis.analyse() + except KeyError: + return { + "recordId": record["recordId"], + "data": {}, + "errors": [ + { + "message": "Failed to extract data with ADI. Pass a valid source in the request body.", + } + ], + "warnings": None, + } + + +async def main(req: func.HttpRequest) -> func.HttpResponse: + try: + req_body = req.get_json() + values = req_body.get("values") + adi_config = req.headers + + page_wise = adi_config.get("page_wise", "False").lower() == "true" + extract_figures = adi_config.get("extract_figures", "True").lower() == "true" + logging.info(f"Chunk by Page: {page_wise}") + except ValueError: + return func.HttpResponse( + "Please valid Custom Skill Payload in the request body", status_code=400 + ) + else: + logging.info("Input Values: %s", values) + + record_tasks = [] + + for value in values: + record_tasks.append( + asyncio.create_task( + process_layout_analysis( + value, page_wise=page_wise, extract_figures=extract_figures + ) + ) + ) + + results = await asyncio.gather(*record_tasks) + logging.info("Results: %s", results) + + return func.HttpResponse( + json.dumps({"values": results}), + status_code=200, + mimetype="application/json", + ) diff --git a/image_processing/layout_and_figure_merger.py b/image_processing/layout_and_figure_merger.py new file mode 100644 index 00000000..31ad833f --- /dev/null +++ b/image_processing/layout_and_figure_merger.py @@ -0,0 +1,123 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +import logging +import re +from layout_holders import FigureHolder, LayoutHolder + + +class LayoutAndFigureMerger: + def insert_figure_description( + self, layout_holder: LayoutHolder, figure_holder: FigureHolder + ) -> int: + """ + Updates the figure description in the Markdown content. + + Args: + layout_holder (LayoutHolder): The layout text. + figure_holder (FigureHolder): The figure to be updated. + + Returns: + str: The updated Markdown content with the new figure description. + """ + + # Calculate the end index of the content to be replaced + end_index = figure_holder.offset + figure_holder.length + + # Ensure that the end_index does not exceed the length of the Markdown content + if end_index > len(layout_holder.content): + logging.info( + "End index exceeds the length of the content. Adjusting the end index to the length of the content." + ) + end_index = len(layout_holder.content) + + # Replace the old string with the new string + layout_holder.content = ( + layout_holder.content[: figure_holder.offset] + + figure_holder.markdown + + layout_holder.content[end_index:] + ) + + return len(figure_holder.markdown) - figure_holder.length + + async def merge_figures_into_layout( + self, layout: LayoutHolder, figures: list[FigureHolder] + ) -> LayoutHolder: + """ + Merges the figures into the layout. + + Args: + layout (LayoutHolder): The layout text. + figures (list): The list of figures. + + Returns: + LayoutHolder: The updated layout text with the figures. + """ + # Initialize the offset + running_offset = 0 + + # Iterate over the figures + for figure in figures: + logging.info(f"Inserting Figure: {figure.figure_id}") + # Update the figure description in the layout + figure.offset += running_offset + length = self.insert_figure_description(layout, figure) + + # Update the offset + running_offset += length + + # Remove irrelevant figures + irrelevant_figure_pattern = r"]*>.*?Irrelevant Image.*?" + layout.content = re.sub( + irrelevant_figure_pattern, "", layout.content, flags=re.DOTALL + ) + + empty_or_whitespace_figure_pattern = r"]*>\s*" + layout.content = re.sub( + empty_or_whitespace_figure_pattern, "", layout.content, flags=re.DOTALL + ) + + html_comments_pattern = r"" + layout.content = re.sub( + html_comments_pattern, "", layout.content, flags=re.DOTALL + ) + + return layout + + async def merge(self, record: dict) -> dict: + """ + Analyse the image and generate a description for it. + + Parameters: + - record (dict): The record containing the image and its caption. + + Returns: + - record (dict): The record containing the image, its caption, and the generated description. + """ + layout = LayoutHolder(**record["data"]["layout"]) + + figures = [FigureHolder(**figure) for figure in record["data"]["figures"]] + + try: + logging.info(f"Input Data: {layout}") + updated_layout = await self.merge_figures_into_layout(layout, figures) + logging.info(f"Updated Data: {updated_layout}") + except Exception as e: + logging.error(f"Failed to merge figures into layout. Error: {e}") + return { + "recordId": record["recordId"], + "data": {}, + "errors": [ + { + "message": "Failed to merge figures into layout.", + } + ], + "warnings": None, + } + else: + return { + "recordId": record["recordId"], + "data": updated_layout.model_dump(), + "errors": None, + "warnings": None, + } diff --git a/image_processing/layout_holders.py b/image_processing/layout_holders.py new file mode 100644 index 00000000..9388c8ba --- /dev/null +++ b/image_processing/layout_holders.py @@ -0,0 +1,51 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +from pydantic import BaseModel, Field +from typing import Optional + + +class FigureHolder(BaseModel): + """A class to hold the figure extracted from the document.""" + + figure_id: str + container: str + image_blob: str + caption: Optional[str] = Field(default=None) + offset: int + length: int + page_number: Optional[int] = Field(default=None) + uri: str + description: Optional[str] = Field(default="") + data: Optional[str] = Field(default=None) + + @property + def markdown(self) -> str: + """Convert the figure to a Markdown string. + + Returns: + -------- + str: The Markdown string representation of the figure.""" + + return f"
{self.description}
" + + +class LayoutHolder(BaseModel): + """A class to hold the text extracted from the document.""" + + content: str + page_number: Optional[int] = None + page_offsets: Optional[int] = 0 + figures: list[FigureHolder] = Field(default_factory=list) + + +class PageWiseContentHolder(BaseModel): + """A class to hold the page-wise content extracted from the document.""" + + page_wise_layout: list[LayoutHolder] + + +class NonPageWiseContentHolder(BaseModel): + """A class to hold the non-page-wise content extracted from the document.""" + + layout: LayoutHolder diff --git a/adi_function_app/local.settings.json b/image_processing/local.settings.json similarity index 100% rename from adi_function_app/local.settings.json rename to image_processing/local.settings.json diff --git a/adi_function_app/mark_up_cleaner.py b/image_processing/mark_up_cleaner.py similarity index 84% rename from adi_function_app/mark_up_cleaner.py rename to image_processing/mark_up_cleaner.py index 6138f549..3871644d 100644 --- a/adi_function_app/mark_up_cleaner.py +++ b/image_processing/mark_up_cleaner.py @@ -29,13 +29,6 @@ def clean_sections(sections: list) -> list: return cleaned_sections -def extract_figure_ids(text: str) -> list: - # Regex pattern to capture FigureId values - figure_id_pattern = r' str: """ Remove specified Markdown tags from the text, keeping the contents of the tags. @@ -51,7 +44,10 @@ def remove_markdown_tags(text: str, tag_patterns: dict) -> str: for tag, pattern in tag_patterns.items(): try: # Replace the tags using the specific pattern, keeping the content inside the tags - text = re.sub(pattern, r"\1", text, flags=re.DOTALL) + if tag == "header": + text = re.sub(pattern, r"\2", text, flags=re.DOTALL | re.MULTILINE) + else: + text = re.sub(pattern, r"\1", text, flags=re.DOTALL) except re.error as e: logging.error(f"Regex error for tag '{tag}': {e}") except Exception as e: @@ -59,9 +55,7 @@ def remove_markdown_tags(text: str, tag_patterns: dict) -> str: return text -def clean_text_and_extract_metadata( - src_text: str, figure_storage_prefix: str -) -> tuple[str, str]: +def clean_text_and_extract_metadata(src_text: str) -> tuple[str, str]: """This function performs following cleanup activities on the text, remove all unicode characters remove line spacing,remove stop words, normalize characters @@ -82,14 +76,7 @@ def clean_text_and_extract_metadata( return_record["marked_up_chunk"] = src_text return_record["sections"] = get_sections(src_text) - figure_ids = extract_figure_ids(src_text) - - figures = [] - for figure_id in figure_ids: - figure_uri = f"{figure_storage_prefix}/{figure_id}.png" - figures.append({"figure_id": figure_id, "figure_uri": figure_uri}) - - return_record["figures"] = figures + logging.info(f"Sections: {return_record['sections']}") # Define specific patterns for each tag tag_patterns = { @@ -97,9 +84,12 @@ def clean_text_and_extract_metadata( "figure": r"(.*?)", "figures": r"\(figures/\d+\)(.*?)\(figures/\d+\)", "figcaption": r"
(.*?)
", + "header": r"^\s*(#{1,6})\s*(.*?)\s*$", } cleaned_text = remove_markdown_tags(src_text, tag_patterns) + logging.info(f"Removed markdown tags: {cleaned_text}") + # Updated regex to keep Unicode letters, punctuation, whitespace, currency symbols, and percentage signs, # while also removing non-printable characters cleaned_text = re.sub(r"[^\p{L}\p{P}\s\p{Sc}%\x20-\x7E]", "", cleaned_text) @@ -138,7 +128,7 @@ async def process_mark_up_cleaner(record: dict) -> dict: } cleaned_record["data"] = clean_text_and_extract_metadata( - record["data"]["chunk"], record["data"]["figure_storage_prefix"] + record["data"]["chunk"] ) except Exception as e: diff --git a/adi_function_app/pyproject.toml b/image_processing/pyproject.toml similarity index 71% rename from adi_function_app/pyproject.toml rename to image_processing/pyproject.toml index 11d7e3d2..4fb94d7f 100644 --- a/adi_function_app/pyproject.toml +++ b/image_processing/pyproject.toml @@ -1,5 +1,5 @@ [project] -name = "adi-function-app" +name = "image_processing" version = "0.1.0" description = "Add your description here" readme = "README.md" @@ -17,7 +17,7 @@ dependencies = [ "python-dotenv>=1.0.1", "regex>=2024.11.6", "tenacity>=9.0.0", - "azure-ai-documentintelligence==1.0.0b4", + "azure-ai-documentintelligence==1.0.0", "azure-ai-textanalytics>=5.3.0", "azure-ai-vision-imageanalysis>=1.0.0", "pymupdf>=1.24.14", @@ -26,5 +26,18 @@ dependencies = [ "numpy<2.0.0", "spacy>=3.7.5", "tiktoken>=0.8.0", - "en-core-web-md @ https://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.7.1/en_core_web_md-3.7.1.tar.gz" + "en-core-web-md @ https://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.7.1/en_core_web_md-3.7.1.tar.gz", + "model2vec>=0.3.5", + "pydantic>=2.10.5", +] + +[dependency-groups] +dev = [ + "black>=24.10.0", + "ipykernel>=6.29.5", + "jupyter>=1.1.1", + "pre-commit>=4.0.1", + "pygments>=2.18.0", + "ruff>=0.8.1", + "python-dotenv>=1.0.1", ] diff --git a/adi_function_app/semantic_text_chunker.py b/image_processing/semantic_text_chunker.py similarity index 94% rename from adi_function_app/semantic_text_chunker.py rename to image_processing/semantic_text_chunker.py index a150523e..e990b7bd 100644 --- a/adi_function_app/semantic_text_chunker.py +++ b/image_processing/semantic_text_chunker.py @@ -6,8 +6,7 @@ import tiktoken import spacy import numpy as np - -logging.basicConfig(level=logging.INFO) +from model2vec import StaticModel class SemanticTextChunker: @@ -17,11 +16,16 @@ def __init__( similarity_threshold: float = 0.8, max_chunk_tokens: int = 200, min_chunk_tokens: int = 50, + distill_model=True, ): self.num_surrounding_sentences = num_surrounding_sentences self.similarity_threshold = similarity_threshold self.max_chunk_tokens = max_chunk_tokens self.min_chunk_tokens = min_chunk_tokens + + self.distill_model = distill_model + model_name = "minishlab/M2V_base_output" + self.distilled_model = StaticModel.from_pretrained(model_name) try: self._nlp_model = spacy.load("en_core_web_md") except IOError as e: @@ -68,8 +72,12 @@ async def chunk(self, text: str) -> list[dict]: Returns: list(str): The list of chunks""" + logging.info(f"Chunking text: {text}") + sentences = self.split_into_sentences(text) + logging.info(f"Number of sentences: {len(sentences)}") + ( grouped_sentences, is_table_or_figure_map, @@ -106,6 +114,9 @@ async def chunk(self, text: str) -> list[dict]: logging.info(f"Number of final chunks: {len(cleaned_final_chunks)}") logging.info(f"Chunks: {cleaned_final_chunks}") + if len(cleaned_final_chunks) == 0: + raise ValueError("No chunks were generated") + return cleaned_final_chunks def filter_empty_figures(self, text): @@ -143,6 +154,8 @@ def split_into_sentences(self, text: str) -> list[str]: # Filter out empty
...
tags cleaned_text = self.filter_empty_figures(cleaned_text) + logging.info(f"Cleaned text: {cleaned_text}") + doc = self._nlp_model(cleaned_text) tag_split_sentences = [] @@ -179,6 +192,7 @@ def split_into_sentences(self, text: str) -> list[str]: and part.endswith("\n\n") is False ): part = part + "\n\n" + heading_split_sentences.append(part) return heading_split_sentences @@ -215,7 +229,12 @@ def group_figures_and_tables_into_sentences(self, sentences: list[str]): else: holding_sentences.append(current_sentence) - assert len(holding_sentences) == 0, "Holding sentences should be empty" + if len(holding_sentences) > 0: + full_sentence = " ".join(holding_sentences) + grouped_sentences.append(full_sentence) + holding_sentences = [] + + is_table_or_figure_map.append(True) return grouped_sentences, is_table_or_figure_map @@ -285,7 +304,7 @@ def retrive_current_chunk_at_n(n): current_chunk_tokens = self.num_tokens_from_string(" ".join(current_chunk)) if len(current_chunk) >= 2 and current_chunk_tokens >= self.min_chunk_tokens: - logging.debug("Comparing chunks") + logging.info("Comparing chunks") cosine_sim = self.sentence_similarity( retrieve_current_chunks_from_n(-2), current_sentence ) @@ -300,7 +319,7 @@ def retrive_current_chunk_at_n(n): new_chunk = retrive_current_chunk_at_n(0) current_chunk = [retrive_current_chunk_at_n(1)] else: - logging.debug("Chunk too small to compare") + logging.info("Chunk too small to compare") return new_chunk, current_chunk @@ -427,14 +446,18 @@ def retrieve_current_chunk(): return chunks, new_is_table_or_figure_map def sentence_similarity(self, text_1, text_2): - vec1 = self._nlp_model(text_1).vector - vec2 = self._nlp_model(text_2).vector + if self.distill_model: + vec1 = self.distilled_model.encode(text_1) + vec2 = self.distilled_model.encode(text_2) + else: + vec1 = self._nlp_model(text_1).vector + vec2 = self._nlp_model(text_2).vector dot_product = np.dot(vec1, vec2) magnitude = np.linalg.norm(vec1) * np.linalg.norm(vec2) similarity = dot_product / magnitude if magnitude != 0 else 0.0 - logging.debug( + logging.info( f"""Similarity between '{text_1}' and '{ text_2}': {similarity}""" ) diff --git a/adi_function_app/storage_account.py b/image_processing/storage_account.py similarity index 100% rename from adi_function_app/storage_account.py rename to image_processing/storage_account.py diff --git a/pyproject.toml b/pyproject.toml index 2247cfa4..b79fff70 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,7 @@ dev = [ ] [tool.uv.workspace] -members = ["text_2_sql/text_2_sql_core", "text_2_sql/autogen", "deploy_ai_search", "adi_function_app", "text_2_sql/semantic_kernel"] +members = ["text_2_sql/text_2_sql_core", "text_2_sql/autogen", "deploy_ai_search", "image_processing", "text_2_sql/semantic_kernel"] [tool.uv.sources] text-2-sql-core = { workspace = true } diff --git a/uv.lock b/uv.lock index 9c6e48ec..f050d273 100644 --- a/uv.lock +++ b/uv.lock @@ -3,69 +3,14 @@ requires-python = ">=3.12" [manifest] members = [ - "adi-function-app", "autogen-text-2-sql", "deploy-ai-search", "dstoolkit-text2sql-and-imageprocessing", + "image-processing", "semantic-kernel-text-2-sql", "text-2-sql-core", ] -[[package]] -name = "adi-function-app" -version = "0.1.0" -source = { virtual = "adi_function_app" } -dependencies = [ - { name = "aiohttp" }, - { name = "azure-ai-documentintelligence" }, - { name = "azure-ai-textanalytics" }, - { name = "azure-ai-vision-imageanalysis" }, - { name = "azure-functions" }, - { name = "azure-identity" }, - { name = "azure-search" }, - { name = "azure-search-documents" }, - { name = "azure-storage-blob" }, - { name = "bs4" }, - { name = "en-core-web-md" }, - { name = "numpy" }, - { name = "openai" }, - { name = "openpyxl" }, - { name = "pandas" }, - { name = "pillow" }, - { name = "pymupdf" }, - { name = "python-dotenv" }, - { name = "regex" }, - { name = "spacy" }, - { name = "tenacity" }, - { name = "tiktoken" }, -] - -[package.metadata] -requires-dist = [ - { name = "aiohttp", specifier = ">=3.11.9" }, - { name = "azure-ai-documentintelligence", specifier = "==1.0.0b4" }, - { name = "azure-ai-textanalytics", specifier = ">=5.3.0" }, - { name = "azure-ai-vision-imageanalysis", specifier = ">=1.0.0" }, - { name = "azure-functions", specifier = ">=1.21.3" }, - { name = "azure-identity", specifier = ">=1.19.0" }, - { name = "azure-search", specifier = ">=1.0.0b2" }, - { name = "azure-search-documents", specifier = ">=11.6.0b8" }, - { name = "azure-storage-blob", specifier = ">=12.24.0" }, - { name = "bs4", specifier = ">=0.0.2" }, - { name = "en-core-web-md", url = "https://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.7.1/en_core_web_md-3.7.1.tar.gz" }, - { name = "numpy", specifier = "<2.0.0" }, - { name = "openai", specifier = ">=1.55.3" }, - { name = "openpyxl", specifier = ">=3.1.5" }, - { name = "pandas", specifier = ">=2.2.3" }, - { name = "pillow", specifier = ">=11.0.0" }, - { name = "pymupdf", specifier = ">=1.24.14" }, - { name = "python-dotenv", specifier = ">=1.0.1" }, - { name = "regex", specifier = ">=2024.11.6" }, - { name = "spacy", specifier = ">=3.7.5" }, - { name = "tenacity", specifier = ">=9.0.0" }, - { name = "tiktoken", specifier = ">=0.8.0" }, -] - [[package]] name = "aioconsole" version = "0.8.1" @@ -436,16 +381,16 @@ dev = [ [[package]] name = "azure-ai-documentintelligence" -version = "1.0.0b4" +version = "1.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "azure-core" }, { name = "isodate" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/18/3a/1a8f5cb7df48eeb456bb3498bf49f236316095267be4df82ae09a562c52a/azure_ai_documentintelligence-1.0.0b4.tar.gz", hash = "sha256:1aa36f0617b0c129fdc82b039b7084fd5b69af08e8e0cb500108b9f6efd61b36", size = 159821 } +sdist = { url = "https://files.pythonhosted.org/packages/ca/fd/cd0d493e9dc93a5ce097db7508f1b2467a73dcc7022c235b409ce48b9679/azure_ai_documentintelligence-1.0.0.tar.gz", hash = "sha256:c8b6efc0fc7e65d7892c9585cfd256f7d8b3f2b46cecf92c75ab82e629eac253", size = 169420 } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/93/282ce2ab36081d33d79b9c825d775ee556713af8137c7af6de1a42ccf5e5/azure_ai_documentintelligence-1.0.0b4-py3-none-any.whl", hash = "sha256:c3a90560b4029e232dbab1334ac2f3dda4cae7c1f60dad277fe21a876dd6bb9f", size = 99481 }, + { url = "https://files.pythonhosted.org/packages/84/a8/c9c66d4d04b8aee06ebdc9a6077736b222b9b2fe92364fed6f9a1c08ece0/azure_ai_documentintelligence-1.0.0-py3-none-any.whl", hash = "sha256:cdedb1a67c075f58f47a413ec5846bf8d532a83a71f0c51ec49ce9b5bfe2a519", size = 105454 }, ] [[package]] @@ -1166,6 +1111,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c6/c8/a5be5b7550c10858fcf9b0ea054baccab474da77d37f1e828ce043a3a5d4/frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3", size = 11901 }, ] +[[package]] +name = "fsspec" +version = "2024.12.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/11/de70dee31455c546fbc88301971ec03c328f3d1138cfba14263f651e9551/fsspec-2024.12.0.tar.gz", hash = "sha256:670700c977ed2fb51e0d9f9253177ed20cbde4a3e5c0283cc5385b5870c8533f", size = 291600 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/86/5486b0188d08aa643e127774a99bac51ffa6cf343e3deb0583956dca5b22/fsspec-2024.12.0-py3-none-any.whl", hash = "sha256:b520aed47ad9804237ff878b504267a3b0b441e97508bd6d2d8774e3db85cee2", size = 183862 }, +] + [[package]] name = "grpcio" version = "1.69.0" @@ -1229,6 +1183,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 }, ] +[[package]] +name = "huggingface-hub" +version = "0.27.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock" }, + { name = "fsspec" }, + { name = "packaging" }, + { name = "pyyaml" }, + { name = "requests" }, + { name = "tqdm" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e1/d2/d6976de7542792fc077b498d64af64882b6d8bb40679284ec0bff77d5929/huggingface_hub-0.27.1.tar.gz", hash = "sha256:c004463ca870283909d715d20f066ebd6968c2207dae9393fdffb3c1d4d8f98b", size = 379407 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6c/3f/50f6b25fafdcfb1c089187a328c95081abf882309afd86f4053951507cd1/huggingface_hub-0.27.1-py3-none-any.whl", hash = "sha256:1c5155ca7d60b60c2e2fc38cbb3ffb7f7c3adf48f824015b219af9061771daec", size = 450658 }, +] + [[package]] name = "identify" version = "2.6.5" @@ -1247,6 +1219,87 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, ] +[[package]] +name = "image-processing" +version = "0.1.0" +source = { virtual = "image_processing" } +dependencies = [ + { name = "aiohttp" }, + { name = "azure-ai-documentintelligence" }, + { name = "azure-ai-textanalytics" }, + { name = "azure-ai-vision-imageanalysis" }, + { name = "azure-functions" }, + { name = "azure-identity" }, + { name = "azure-search" }, + { name = "azure-search-documents" }, + { name = "azure-storage-blob" }, + { name = "bs4" }, + { name = "en-core-web-md" }, + { name = "model2vec" }, + { name = "numpy" }, + { name = "openai" }, + { name = "openpyxl" }, + { name = "pandas" }, + { name = "pillow" }, + { name = "pydantic" }, + { name = "pymupdf" }, + { name = "python-dotenv" }, + { name = "regex" }, + { name = "spacy" }, + { name = "tenacity" }, + { name = "tiktoken" }, +] + +[package.dev-dependencies] +dev = [ + { name = "black" }, + { name = "ipykernel" }, + { name = "jupyter" }, + { name = "pre-commit" }, + { name = "pygments" }, + { name = "python-dotenv" }, + { name = "ruff" }, +] + +[package.metadata] +requires-dist = [ + { name = "aiohttp", specifier = ">=3.11.9" }, + { name = "azure-ai-documentintelligence", specifier = "==1.0.0" }, + { name = "azure-ai-textanalytics", specifier = ">=5.3.0" }, + { name = "azure-ai-vision-imageanalysis", specifier = ">=1.0.0" }, + { name = "azure-functions", specifier = ">=1.21.3" }, + { name = "azure-identity", specifier = ">=1.19.0" }, + { name = "azure-search", specifier = ">=1.0.0b2" }, + { name = "azure-search-documents", specifier = ">=11.6.0b8" }, + { name = "azure-storage-blob", specifier = ">=12.24.0" }, + { name = "bs4", specifier = ">=0.0.2" }, + { name = "en-core-web-md", url = "https://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.7.1/en_core_web_md-3.7.1.tar.gz" }, + { name = "model2vec", specifier = ">=0.3.5" }, + { name = "numpy", specifier = "<2.0.0" }, + { name = "openai", specifier = ">=1.55.3" }, + { name = "openpyxl", specifier = ">=3.1.5" }, + { name = "pandas", specifier = ">=2.2.3" }, + { name = "pillow", specifier = ">=11.0.0" }, + { name = "pydantic", specifier = ">=2.10.5" }, + { name = "pymupdf", specifier = ">=1.24.14" }, + { name = "python-dotenv", specifier = ">=1.0.1" }, + { name = "regex", specifier = ">=2024.11.6" }, + { name = "spacy", specifier = ">=3.7.5" }, + { name = "tenacity", specifier = ">=9.0.0" }, + { name = "tiktoken", specifier = ">=0.8.0" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "black", specifier = ">=24.10.0" }, + { name = "ipykernel", specifier = ">=6.29.5" }, + { name = "jupyter", specifier = ">=1.1.1" }, + { name = "pre-commit", specifier = ">=4.0.1" }, + { name = "pygments", specifier = ">=2.18.0" }, + { name = "python-dotenv", specifier = ">=1.0.1" }, + { name = "ruff", specifier = ">=0.8.1" }, +] + [[package]] name = "importlib-metadata" version = "8.4.0" @@ -1479,14 +1532,14 @@ wheels = [ [[package]] name = "jsonschema-specifications" -version = "2023.12.1" +version = "2024.10.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "referencing" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f8/b9/cc0cc592e7c195fb8a650c1d5990b10175cf13b4c97465c72ec841de9e4b/jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc", size = 13983 } +sdist = { url = "https://files.pythonhosted.org/packages/10/db/58f950c996c793472e336ff3655b13fbcf1e3b359dcf52dcf3ed3b52c352/jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272", size = 15561 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ee/07/44bd408781594c4d0a027666ef27fab1e441b109dc3b76b4f836f8fd04fe/jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c", size = 18482 }, + { url = "https://files.pythonhosted.org/packages/d1/0f/8910b19ac0670a0f80ce1008e5e751c4a57e14d2c4c13a482aa6079fa9d6/jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf", size = 18459 }, ] [[package]] @@ -1856,6 +1909,25 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b4/b3/743ffc3f59da380da504d84ccd1faf9a857a1445991ff19bf2ec754163c2/mistune-3.1.0-py3-none-any.whl", hash = "sha256:b05198cf6d671b3deba6c87ec6cf0d4eb7b72c524636eddb6dbf13823b52cee1", size = 53694 }, ] +[[package]] +name = "model2vec" +version = "0.3.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jinja2" }, + { name = "joblib" }, + { name = "numpy" }, + { name = "rich" }, + { name = "safetensors" }, + { name = "setuptools" }, + { name = "tokenizers" }, + { name = "tqdm" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/0a/8b7874ca692e7d1eabb7b723d87309914b5f2a251945d21fcfa3f242dbd4/model2vec-0.3.5.tar.gz", hash = "sha256:437b13febcffac6d12ea50baa96f4e166f01e1dc487508d75a4a61e2774aa02e", size = 2305705 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/4d/b04cb7c65910ec5b224d56323376753220cc1a81015f084b913df6af2c50/model2vec-0.3.5-py3-none-any.whl", hash = "sha256:f6596dc0660c4bffa492cbd8445b1925b6bda04c12b7c4cc825d195325322748", size = 27515 }, +] + [[package]] name = "more-itertools" version = "10.5.0" @@ -2126,7 +2198,7 @@ wheels = [ [[package]] name = "openai" -version = "1.59.4" +version = "1.59.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -2138,9 +2210,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/38/db/0e1376bdee3de8c16d91647d47dc47a26d2d6036931c76844e7d3e3fb989/openai-1.59.4.tar.gz", hash = "sha256:b946dc5a2308dc1e03efbda80bf1cd64b6053b536851ad519f57ee44401663d2", size = 344405 } +sdist = { url = "https://files.pythonhosted.org/packages/f9/d5/25cf04789c7929b476c4d9ef711f8979091db63d30bfc093828fe4bf5c72/openai-1.59.7.tar.gz", hash = "sha256:043603def78c00befb857df9f0a16ee76a3af5984ba40cb7ee5e2f40db4646bf", size = 345007 } wheels = [ - { url = "https://files.pythonhosted.org/packages/99/01/1eefc235bb79174826b2fa0cad05bc2eab90eae97bf78c765887d7430e46/openai-1.59.4-py3-none-any.whl", hash = "sha256:82113498699998e98104f87c19a890e82df9b01251a0395484360575d3a1d98a", size = 454810 }, + { url = "https://files.pythonhosted.org/packages/6d/47/7b92f1731c227f4139ef0025b5996062e44f9a749c54315c8bdb34bad5ec/openai-1.59.7-py3-none-any.whl", hash = "sha256:cfa806556226fa96df7380ab2e29814181d56fea44738c2b0e581b462c268692", size = 454844 }, ] [[package]] @@ -2164,16 +2236,16 @@ wheels = [ [[package]] name = "openapi-schema-validator" -version = "0.6.2" +version = "0.6.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonschema" }, { name = "jsonschema-specifications" }, { name = "rfc3339-validator" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5c/b2/7d5bdf2b26b6a95ebf4fbec294acaf4306c713f3a47c2453962511110248/openapi_schema_validator-0.6.2.tar.gz", hash = "sha256:11a95c9c9017912964e3e5f2545a5b11c3814880681fcacfb73b1759bb4f2804", size = 11860 } +sdist = { url = "https://files.pythonhosted.org/packages/8b/f3/5507ad3325169347cd8ced61c232ff3df70e2b250c49f0fe140edb4973c6/openapi_schema_validator-0.6.3.tar.gz", hash = "sha256:f37bace4fc2a5d96692f4f8b31dc0f8d7400fd04f3a937798eaf880d425de6ee", size = 11550 } wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/dc/9aefae8891454130968ff079ece851d1ae9ccf6fb7965761f47c50c04853/openapi_schema_validator-0.6.2-py3-none-any.whl", hash = "sha256:c4887c1347c669eb7cded9090f4438b710845cd0f90d1fb9e1b3303fb37339f8", size = 8750 }, + { url = "https://files.pythonhosted.org/packages/21/c6/ad0fba32775ae749016829dace42ed80f4407b171da41313d1a3a5f102e4/openapi_schema_validator-0.6.3-py3-none-any.whl", hash = "sha256:f3b9870f4e556b5a62a1c39da72a6b4b16f3ad9c73dc80084b1b11e74ba148a3", size = 8755 }, ] [[package]] @@ -2324,11 +2396,11 @@ wheels = [ [[package]] name = "pathable" -version = "0.4.3" +version = "0.4.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9d/ed/e0e29300253b61dea3b7ec3a31f5d061d577c2a6fd1e35c5cfd0e6f2cd6d/pathable-0.4.3.tar.gz", hash = "sha256:5c869d315be50776cc8a993f3af43e0c60dc01506b399643f919034ebf4cdcab", size = 8679 } +sdist = { url = "https://files.pythonhosted.org/packages/67/93/8f2c2075b180c12c1e9f6a09d1a985bc2036906b13dff1d8917e395f2048/pathable-0.4.4.tar.gz", hash = "sha256:6905a3cd17804edfac7875b5f6c9142a218c7caef78693c2dbbbfbac186d88b2", size = 8124 } wheels = [ - { url = "https://files.pythonhosted.org/packages/5b/0a/acfb251ba01009d3053f04f4661e96abf9d485266b04a0a4deebc702d9cb/pathable-0.4.3-py3-none-any.whl", hash = "sha256:cdd7b1f9d7d5c8b8d3315dbf5a86b2596053ae845f056f57d97c0eefff84da14", size = 9587 }, + { url = "https://files.pythonhosted.org/packages/7d/eb/b6260b31b1a96386c0a880edebe26f89669098acea8e0318bff6adb378fd/pathable-0.4.4-py3-none-any.whl", hash = "sha256:5ae9e94793b6ef5a4cbe0a7ce9dbbefc1eec38df253763fd0aeeacf2762dbbc2", size = 9592 }, ] [[package]] @@ -2620,16 +2692,16 @@ wheels = [ [[package]] name = "pydantic" -version = "2.10.4" +version = "2.10.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, { name = "pydantic-core" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/70/7e/fb60e6fee04d0ef8f15e4e01ff187a196fa976eb0f0ab524af4599e5754c/pydantic-2.10.4.tar.gz", hash = "sha256:82f12e9723da6de4fe2ba888b5971157b3be7ad914267dea8f05f82b28254f06", size = 762094 } +sdist = { url = "https://files.pythonhosted.org/packages/6a/c7/ca334c2ef6f2e046b1144fe4bb2a5da8a4c574e7f2ebf7e16b34a6a2fa92/pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff", size = 761287 } wheels = [ - { url = "https://files.pythonhosted.org/packages/f3/26/3e1bbe954fde7ee22a6e7d31582c642aad9e84ffe4b5fb61e63b87cd326f/pydantic-2.10.4-py3-none-any.whl", hash = "sha256:597e135ea68be3a37552fb524bc7d0d66dcf93d395acd93a00682f1efcb8ee3d", size = 431765 }, + { url = "https://files.pythonhosted.org/packages/58/26/82663c79010b28eddf29dcdd0ea723439535fa917fce5905885c0e9ba562/pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53", size = 431426 }, ] [[package]] @@ -3092,27 +3164,49 @@ wheels = [ [[package]] name = "ruff" -version = "0.8.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/da/00/089db7890ea3be5709e3ece6e46408d6f1e876026ec3fd081ee585fef209/ruff-0.8.6.tar.gz", hash = "sha256:dcad24b81b62650b0eb8814f576fc65cfee8674772a6e24c9b747911801eeaa5", size = 3473116 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d7/28/aa07903694637c2fa394a9f4fe93cf861ad8b09f1282fa650ef07ff9fe97/ruff-0.8.6-py3-none-linux_armv6l.whl", hash = "sha256:defed167955d42c68b407e8f2e6f56ba52520e790aba4ca707a9c88619e580e3", size = 10628735 }, - { url = "https://files.pythonhosted.org/packages/2b/43/827bb1448f1fcb0fb42e9c6edf8fb067ca8244923bf0ddf12b7bf949065c/ruff-0.8.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:54799ca3d67ae5e0b7a7ac234baa657a9c1784b48ec954a094da7c206e0365b1", size = 10386758 }, - { url = "https://files.pythonhosted.org/packages/df/93/fc852a81c3cd315b14676db3b8327d2bb2d7508649ad60bfdb966d60738d/ruff-0.8.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e88b8f6d901477c41559ba540beeb5a671e14cd29ebd5683903572f4b40a9807", size = 10007808 }, - { url = "https://files.pythonhosted.org/packages/94/e9/e0ed4af1794335fb280c4fac180f2bf40f6a3b859cae93a5a3ada27325ae/ruff-0.8.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0509e8da430228236a18a677fcdb0c1f102dd26d5520f71f79b094963322ed25", size = 10861031 }, - { url = "https://files.pythonhosted.org/packages/82/68/da0db02f5ecb2ce912c2bef2aa9fcb8915c31e9bc363969cfaaddbc4c1c2/ruff-0.8.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:91a7ddb221779871cf226100e677b5ea38c2d54e9e2c8ed847450ebbdf99b32d", size = 10388246 }, - { url = "https://files.pythonhosted.org/packages/ac/1d/b85383db181639019b50eb277c2ee48f9f5168f4f7c287376f2b6e2a6dc2/ruff-0.8.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:248b1fb3f739d01d528cc50b35ee9c4812aa58cc5935998e776bf8ed5b251e75", size = 11424693 }, - { url = "https://files.pythonhosted.org/packages/ac/b7/30bc78a37648d31bfc7ba7105b108cb9091cd925f249aa533038ebc5a96f/ruff-0.8.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:bc3c083c50390cf69e7e1b5a5a7303898966be973664ec0c4a4acea82c1d4315", size = 12141921 }, - { url = "https://files.pythonhosted.org/packages/60/b3/ee0a14cf6a1fbd6965b601c88d5625d250b97caf0534181e151504498f86/ruff-0.8.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52d587092ab8df308635762386f45f4638badb0866355b2b86760f6d3c076188", size = 11692419 }, - { url = "https://files.pythonhosted.org/packages/ef/d6/c597062b2931ba3e3861e80bd2b147ca12b3370afc3889af46f29209037f/ruff-0.8.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:61323159cf21bc3897674e5adb27cd9e7700bab6b84de40d7be28c3d46dc67cf", size = 12981648 }, - { url = "https://files.pythonhosted.org/packages/68/84/21f578c2a4144917985f1f4011171aeff94ab18dfa5303ac632da2f9af36/ruff-0.8.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ae4478b1471fc0c44ed52a6fb787e641a2ac58b1c1f91763bafbc2faddc5117", size = 11251801 }, - { url = "https://files.pythonhosted.org/packages/6c/aa/1ac02537c8edeb13e0955b5db86b5c050a1dcba54f6d49ab567decaa59c1/ruff-0.8.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0c000a471d519b3e6cfc9c6680025d923b4ca140ce3e4612d1a2ef58e11f11fe", size = 10849857 }, - { url = "https://files.pythonhosted.org/packages/eb/00/020cb222252d833956cb3b07e0e40c9d4b984fbb2dc3923075c8f944497d/ruff-0.8.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9257aa841e9e8d9b727423086f0fa9a86b6b420fbf4bf9e1465d1250ce8e4d8d", size = 10470852 }, - { url = "https://files.pythonhosted.org/packages/00/56/e6d6578202a0141cd52299fe5acb38b2d873565f4670c7a5373b637cf58d/ruff-0.8.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:45a56f61b24682f6f6709636949ae8cc82ae229d8d773b4c76c09ec83964a95a", size = 10972997 }, - { url = "https://files.pythonhosted.org/packages/be/31/dd0db1f4796bda30dea7592f106f3a67a8f00bcd3a50df889fbac58e2786/ruff-0.8.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:496dd38a53aa173481a7d8866bcd6451bd934d06976a2505028a50583e001b76", size = 11317760 }, - { url = "https://files.pythonhosted.org/packages/d4/70/cfcb693dc294e034c6fed837fa2ec98b27cc97a26db5d049345364f504bf/ruff-0.8.6-py3-none-win32.whl", hash = "sha256:e169ea1b9eae61c99b257dc83b9ee6c76f89042752cb2d83486a7d6e48e8f764", size = 8799729 }, - { url = "https://files.pythonhosted.org/packages/60/22/ae6bcaa0edc83af42751bd193138bfb7598b2990939d3e40494d6c00698c/ruff-0.8.6-py3-none-win_amd64.whl", hash = "sha256:f1d70bef3d16fdc897ee290d7d20da3cbe4e26349f62e8a0274e7a3f4ce7a905", size = 9673857 }, - { url = "https://files.pythonhosted.org/packages/91/f8/3765e053acd07baa055c96b2065c7fab91f911b3c076dfea71006666f5b0/ruff-0.8.6-py3-none-win_arm64.whl", hash = "sha256:7d7fc2377a04b6e04ffe588caad613d0c460eb2ecba4c0ccbbfe2bc973cbc162", size = 9149556 }, +version = "0.9.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/67/3e/e89f736f01aa9517a97e2e7e0ce8d34a4d8207087b3cfdec95133fee13b5/ruff-0.9.1.tar.gz", hash = "sha256:fd2b25ecaf907d6458fa842675382c8597b3c746a2dde6717fe3415425df0c17", size = 3498844 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/05/c3a2e0feb3d5d394cdfd552de01df9d3ec8a3a3771bbff247fab7e668653/ruff-0.9.1-py3-none-linux_armv6l.whl", hash = "sha256:84330dda7abcc270e6055551aca93fdde1b0685fc4fd358f26410f9349cf1743", size = 10645241 }, + { url = "https://files.pythonhosted.org/packages/dd/da/59f0a40e5f88ee5c054ad175caaa2319fc96571e1d29ab4730728f2aad4f/ruff-0.9.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3cae39ba5d137054b0e5b472aee3b78a7c884e61591b100aeb544bcd1fc38d4f", size = 10391066 }, + { url = "https://files.pythonhosted.org/packages/b7/fe/85e1c1acf0ba04a3f2d54ae61073da030f7a5dc386194f96f3c6ca444a78/ruff-0.9.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:50c647ff96f4ba288db0ad87048257753733763b409b2faf2ea78b45c8bb7fcb", size = 10012308 }, + { url = "https://files.pythonhosted.org/packages/6f/9b/780aa5d4bdca8dcea4309264b8faa304bac30e1ce0bcc910422bfcadd203/ruff-0.9.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0c8b149e9c7353cace7d698e1656ffcf1e36e50f8ea3b5d5f7f87ff9986a7ca", size = 10881960 }, + { url = "https://files.pythonhosted.org/packages/12/f4/dac4361afbfe520afa7186439e8094e4884ae3b15c8fc75fb2e759c1f267/ruff-0.9.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:beb3298604540c884d8b282fe7625651378e1986c25df51dec5b2f60cafc31ce", size = 10414803 }, + { url = "https://files.pythonhosted.org/packages/f0/a2/057a3cb7999513cb78d6cb33a7d1cc6401c82d7332583786e4dad9e38e44/ruff-0.9.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:39d0174ccc45c439093971cc06ed3ac4dc545f5e8bdacf9f067adf879544d969", size = 11464929 }, + { url = "https://files.pythonhosted.org/packages/eb/c6/1ccfcc209bee465ced4874dcfeaadc88aafcc1ea9c9f31ef66f063c187f0/ruff-0.9.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:69572926c0f0c9912288915214ca9b2809525ea263603370b9e00bed2ba56dbd", size = 12170717 }, + { url = "https://files.pythonhosted.org/packages/84/97/4a524027518525c7cf6931e9fd3b2382be5e4b75b2b61bec02681a7685a5/ruff-0.9.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:937267afce0c9170d6d29f01fcd1f4378172dec6760a9f4dface48cdabf9610a", size = 11708921 }, + { url = "https://files.pythonhosted.org/packages/a6/a4/4e77cf6065c700d5593b25fca6cf725b1ab6d70674904f876254d0112ed0/ruff-0.9.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:186c2313de946f2c22bdf5954b8dd083e124bcfb685732cfb0beae0c47233d9b", size = 13058074 }, + { url = "https://files.pythonhosted.org/packages/f9/d6/fcb78e0531e863d0a952c4c5600cc5cd317437f0e5f031cd2288b117bb37/ruff-0.9.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f94942a3bb767675d9a051867c036655fe9f6c8a491539156a6f7e6b5f31831", size = 11281093 }, + { url = "https://files.pythonhosted.org/packages/e4/3b/7235bbeff00c95dc2d073cfdbf2b871b5bbf476754c5d277815d286b4328/ruff-0.9.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:728d791b769cc28c05f12c280f99e8896932e9833fef1dd8756a6af2261fd1ab", size = 10882610 }, + { url = "https://files.pythonhosted.org/packages/2a/66/5599d23257c61cf038137f82999ca8f9d0080d9d5134440a461bef85b461/ruff-0.9.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2f312c86fb40c5c02b44a29a750ee3b21002bd813b5233facdaf63a51d9a85e1", size = 10489273 }, + { url = "https://files.pythonhosted.org/packages/78/85/de4aa057e2532db0f9761e2c2c13834991e087787b93e4aeb5f1cb10d2df/ruff-0.9.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ae017c3a29bee341ba584f3823f805abbe5fe9cd97f87ed07ecbf533c4c88366", size = 11003314 }, + { url = "https://files.pythonhosted.org/packages/00/42/afedcaa089116d81447347f76041ff46025849fedb0ed2b187d24cf70fca/ruff-0.9.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5dc40a378a0e21b4cfe2b8a0f1812a6572fc7b230ef12cd9fac9161aa91d807f", size = 11342982 }, + { url = "https://files.pythonhosted.org/packages/39/c6/fe45f3eb27e3948b41a305d8b768e949bf6a39310e9df73f6c576d7f1d9f/ruff-0.9.1-py3-none-win32.whl", hash = "sha256:46ebf5cc106cf7e7378ca3c28ce4293b61b449cd121b98699be727d40b79ba72", size = 8819750 }, + { url = "https://files.pythonhosted.org/packages/38/8d/580db77c3b9d5c3d9479e55b0b832d279c30c8f00ab0190d4cd8fc67831c/ruff-0.9.1-py3-none-win_amd64.whl", hash = "sha256:342a824b46ddbcdddd3abfbb332fa7fcaac5488bf18073e841236aadf4ad5c19", size = 9701331 }, + { url = "https://files.pythonhosted.org/packages/b2/94/0498cdb7316ed67a1928300dd87d659c933479f44dec51b4f62bfd1f8028/ruff-0.9.1-py3-none-win_arm64.whl", hash = "sha256:1cd76c7f9c679e6e8f2af8f778367dca82b95009bc7b1a85a47f1521ae524fa7", size = 9145708 }, +] + +[[package]] +name = "safetensors" +version = "0.5.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f4/4f/2ef9ef1766f8c194b01b67a63a444d2e557c8fe1d82faf3ebd85f370a917/safetensors-0.5.2.tar.gz", hash = "sha256:cb4a8d98ba12fa016f4241932b1fc5e702e5143f5374bba0bbcf7ddc1c4cf2b8", size = 66957 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/d1/017e31e75e274492a11a456a9e7c171f8f7911fe50735b4ec6ff37221220/safetensors-0.5.2-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:45b6092997ceb8aa3801693781a71a99909ab9cc776fbc3fa9322d29b1d3bef2", size = 427067 }, + { url = "https://files.pythonhosted.org/packages/24/84/e9d3ff57ae50dd0028f301c9ee064e5087fe8b00e55696677a0413c377a7/safetensors-0.5.2-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:6d0d6a8ee2215a440e1296b843edf44fd377b055ba350eaba74655a2fe2c4bae", size = 408856 }, + { url = "https://files.pythonhosted.org/packages/f1/1d/fe95f5dd73db16757b11915e8a5106337663182d0381811c81993e0014a9/safetensors-0.5.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86016d40bcaa3bcc9a56cd74d97e654b5f4f4abe42b038c71e4f00a089c4526c", size = 450088 }, + { url = "https://files.pythonhosted.org/packages/cf/21/e527961b12d5ab528c6e47b92d5f57f33563c28a972750b238b871924e49/safetensors-0.5.2-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:990833f70a5f9c7d3fc82c94507f03179930ff7d00941c287f73b6fcbf67f19e", size = 458966 }, + { url = "https://files.pythonhosted.org/packages/a5/8b/1a037d7a57f86837c0b41905040369aea7d8ca1ec4b2a77592372b2ec380/safetensors-0.5.2-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dfa7c2f3fe55db34eba90c29df94bcdac4821043fc391cb5d082d9922013869", size = 509915 }, + { url = "https://files.pythonhosted.org/packages/61/3d/03dd5cfd33839df0ee3f4581a20bd09c40246d169c0e4518f20b21d5f077/safetensors-0.5.2-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:46ff2116150ae70a4e9c490d2ab6b6e1b1b93f25e520e540abe1b81b48560c3a", size = 527664 }, + { url = "https://files.pythonhosted.org/packages/c5/dc/8952caafa9a10a3c0f40fa86bacf3190ae7f55fa5eef87415b97b29cb97f/safetensors-0.5.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ab696dfdc060caffb61dbe4066b86419107a24c804a4e373ba59be699ebd8d5", size = 461978 }, + { url = "https://files.pythonhosted.org/packages/60/da/82de1fcf1194e3dbefd4faa92dc98b33c06bed5d67890e0962dd98e18287/safetensors-0.5.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:03c937100f38c9ff4c1507abea9928a6a9b02c9c1c9c3609ed4fb2bf413d4975", size = 491253 }, + { url = "https://files.pythonhosted.org/packages/5a/9a/d90e273c25f90c3ba1b0196a972003786f04c39e302fbd6649325b1272bb/safetensors-0.5.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:a00e737948791b94dad83cf0eafc09a02c4d8c2171a239e8c8572fe04e25960e", size = 628644 }, + { url = "https://files.pythonhosted.org/packages/70/3c/acb23e05aa34b4f5edd2e7f393f8e6480fbccd10601ab42cd03a57d4ab5f/safetensors-0.5.2-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:d3a06fae62418ec8e5c635b61a8086032c9e281f16c63c3af46a6efbab33156f", size = 721648 }, + { url = "https://files.pythonhosted.org/packages/71/45/eaa3dba5253a7c6931230dc961641455710ab231f8a89cb3c4c2af70f8c8/safetensors-0.5.2-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:1506e4c2eda1431099cebe9abf6c76853e95d0b7a95addceaa74c6019c65d8cf", size = 659588 }, + { url = "https://files.pythonhosted.org/packages/b0/71/2f9851164f821064d43b481ddbea0149c2d676c4f4e077b178e7eeaa6660/safetensors-0.5.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5c5b5d9da594f638a259fca766046f44c97244cc7ab8bef161b3e80d04becc76", size = 632533 }, + { url = "https://files.pythonhosted.org/packages/00/f1/5680e2ef61d9c61454fad82c344f0e40b8741a9dbd1e31484f0d31a9b1c3/safetensors-0.5.2-cp38-abi3-win32.whl", hash = "sha256:fe55c039d97090d1f85277d402954dd6ad27f63034fa81985a9cc59655ac3ee2", size = 291167 }, + { url = "https://files.pythonhosted.org/packages/86/ca/aa489392ec6fb59223ffce825461e1f811a3affd417121a2088be7a5758b/safetensors-0.5.2-cp38-abi3-win_amd64.whl", hash = "sha256:78abdddd03a406646107f973c7843276e7b64e5e32623529dc17f3d94a20f589", size = 303756 }, ] [[package]] @@ -3189,11 +3283,11 @@ wheels = [ [[package]] name = "setuptools" -version = "75.7.0" +version = "75.8.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ac/57/e6f0bde5a2c333a32fbcce201f906c1fd0b3a7144138712a5e9d9598c5ec/setuptools-75.7.0.tar.gz", hash = "sha256:886ff7b16cd342f1d1defc16fc98c9ce3fde69e087a4e1983d7ab634e5f41f4f", size = 1338616 } +sdist = { url = "https://files.pythonhosted.org/packages/92/ec/089608b791d210aec4e7f97488e67ab0d33add3efccb83a056cbafe3a2a6/setuptools-75.8.0.tar.gz", hash = "sha256:c5afc8f407c626b8313a86e10311dd3f661c6cd9c09d4bf8c15c0e11f9f2b0e6", size = 1343222 } wheels = [ - { url = "https://files.pythonhosted.org/packages/4e/6e/abdfaaf5c294c553e7a81cf5d801fbb4f53f5c5b6646de651f92a2667547/setuptools-75.7.0-py3-none-any.whl", hash = "sha256:84fb203f278ebcf5cd08f97d3fb96d3fbed4b629d500b29ad60d11e00769b183", size = 1224467 }, + { url = "https://files.pythonhosted.org/packages/69/8a/b9dc7678803429e4a3bc9ba462fa3dd9066824d3c607490235c6a796be5a/setuptools-75.8.0-py3-none-any.whl", hash = "sha256:e3982f444617239225d675215d51f6ba05f845d4eec313da4418fdbb56fb27e3", size = 1228782 }, ] [[package]] @@ -3338,11 +3432,11 @@ wheels = [ [[package]] name = "sqlglot" -version = "26.0.1" +version = "26.1.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/99/39/35cee255a3de5a4bfbe8780d200761423bb1949249ff541ba81420eebbf5/sqlglot-26.0.1.tar.gz", hash = "sha256:588cde7739029fda310fb7dd49afdc0a20b79e760e4cd6d5e1cd083e7e458b90", size = 19785413 } +sdist = { url = "https://files.pythonhosted.org/packages/1b/02/60d542ff60b98ed444176f655a43ecd8c06e9d1f1d38abac3266a41a7eec/sqlglot-26.1.3.tar.gz", hash = "sha256:01fe1a31786e6c7b1ce02470942dfd5fbfd403b7c2d78d9fc4e8aad9eddba2ef", size = 19858552 } wheels = [ - { url = "https://files.pythonhosted.org/packages/62/ac/7cf4f8c133cd2cec68937c87322a5052987f3995f21b87e3d545b4d4aa02/sqlglot-26.0.1-py3-none-any.whl", hash = "sha256:ced4967ce3a4a713d35e2037492fbe1a5187936fdfbd72d7b9ace7815c2d2225", size = 437917 }, + { url = "https://files.pythonhosted.org/packages/71/fe/4521660e276a69f23f7773f52107a1c5ca079cdfaac7c09fb602b60a73c0/sqlglot-26.1.3-py3-none-any.whl", hash = "sha256:e64d696eedb917a0770a10bc0f2a0ce4dffdf95c4fd36cd66e44da3bf2c298c1", size = 439637 }, ] [package.optional-dependencies] @@ -3352,20 +3446,30 @@ rs = [ [[package]] name = "sqlglotrs" -version = "0.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/56/56/745df1a83ead916eb26314a81d3ae8860d9cee30e7d686d8d041aac41ed2/sqlglotrs-0.3.0.tar.gz", hash = "sha256:e77deb4ad2a94024e07ad9c1a15ad573b5503cacc9a948b0f5fd2d6df32156de", size = 9397 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/f0/77184812348969ad269eaf4552db687f13526c29e1db4250dc2489d0a81a/sqlglotrs-0.3.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b722831fd3de500d3c32169317878fede01880e3f1b6cfae926d60d6fbbde6b1", size = 296583 }, - { url = "https://files.pythonhosted.org/packages/01/36/7e262a2904df9217ec1bea3c34f39e9a59f099248cdd639782e27aeee3a6/sqlglotrs-0.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4eeedf2d77c9a44d75e641fa659da1cf69dfcdc27d4fe23d0ee45666122605ce", size = 284942 }, - { url = "https://files.pythonhosted.org/packages/87/06/aa7a7f466bc3399ee2b1f0ba0215e3b5d1c394a3a70861240e789e5a0fc4/sqlglotrs-0.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36878452de1c785dcf11792d9c9bd0810f523be02c23406dbeb6eef05c97e515", size = 321587 }, - { url = "https://files.pythonhosted.org/packages/6e/9c/d2bd1d1f05f68d0b5cc26612b6c5fb08c5b470fb34ec5428545635c11707/sqlglotrs-0.3.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b3e2771b7c6ac9f3f871751e90f4d864c9c689622a3591d932497bd6f1475677", size = 329519 }, - { url = "https://files.pythonhosted.org/packages/7f/c3/98a90459389a3d604a9f10ef25042053fa51aaeed5fa06fa096c71cee3bc/sqlglotrs-0.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5f14e501797e04711a13f766abb31871bc1044ec74e131cabebd7f7757f1cd3f", size = 370422 }, - { url = "https://files.pythonhosted.org/packages/6b/65/e68863bd22395e7060fddd54dcede89f8e65e1d9bc4295c3f5bf051bcd05/sqlglotrs-0.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19bc0293fc586d7c0b5b210f011765cb4378e8f3d77ef93d1937bdd5971d6425", size = 373844 }, - { url = "https://files.pythonhosted.org/packages/ba/e2/01c627f82328cbe252d3cf105522bc6b1bb2a8577fafca0790aa5a2d8107/sqlglotrs-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd5bdc463afe95f00bc9f52e412ea1d52bd958648428e552ecbab5b21d8f93c9", size = 327922 }, - { url = "https://files.pythonhosted.org/packages/cd/52/73d8b502de28b73a9bfadb096ffb2f61c2ac6bd274e9accb0d85751968d7/sqlglotrs-0.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ecacb017d414b21b495e0868ca76b958dbae193ca0e158e0adcaa61b633c0315", size = 346575 }, - { url = "https://files.pythonhosted.org/packages/3d/bb/34d13f76025728d24242675c916f9b84d568c76eab03fa2974b1c722a675/sqlglotrs-0.3.0-cp312-none-win32.whl", hash = "sha256:48d510f5c9704899262ee6b2189eb8eb5639e6474e8141453e93fe10364bde2c", size = 177274 }, - { url = "https://files.pythonhosted.org/packages/6b/ed/8bc1d54387434f4c1b99a54721691444e9e249bb728a0da47b3150c756d6/sqlglotrs-0.3.0-cp312-none-win_amd64.whl", hash = "sha256:b9f308732f12331f06c53fcb1d7c2b135a43aa22486b4c88c26d42710f329448", size = 190557 }, +version = "0.3.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/55/9f/65c61093912e171601729af04cf06163a0275bd60dec5a73c2be2343c38c/sqlglotrs-0.3.4.tar.gz", hash = "sha256:74aebb4b2a8f4795488ac23b3ae2083f0984a8923b5ea151f34495cbe42ff1b9", size = 15326 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/0f/e8e2e84fa71841d7cffae554a07ffacdfe28dbc8be16dbf05293a1dfd956/sqlglotrs-0.3.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:660b505575dbade7a42eb5595c7cc42efccfb478a1ea4bf1200be7da78afe07a", size = 296791 }, + { url = "https://files.pythonhosted.org/packages/2b/fe/6f830db0d200cb67620710e886a15d1a4536cf87f53fb761e7a0615992a8/sqlglotrs-0.3.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1378a817535d36334814b404f0611d949d3f971c6c308c2e301da5ef6a750ee6", size = 285105 }, + { url = "https://files.pythonhosted.org/packages/bb/bd/080acb80984e624f31f22cdd8b6205ae62d83ae5e5f5dccf78860fd5fdf9/sqlglotrs-0.3.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7928dace33305f02fa99d568955ec4e3802834e76998db2695293ea0358fd3d", size = 323586 }, + { url = "https://files.pythonhosted.org/packages/9e/54/db7bdf5f3facfc9223b6c2c041488e91556ce5b41fd2c5c8592eaae23d11/sqlglotrs-0.3.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dd9a6064bbfbb3634831eada051678dcffad7e6b939b5ad481a02f2a1ed7243d", size = 333368 }, + { url = "https://files.pythonhosted.org/packages/21/11/bb33f0844ac8dd3ce5b12124233f501664dded9ecc8ed955bb6466c4238b/sqlglotrs-0.3.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cc43e5385238fbcf5f2cffe01007856732d51f651ae92021535851ba1529352", size = 372484 }, + { url = "https://files.pythonhosted.org/packages/08/f8/005c8797e710c6a2b2590a0400a191e980282d29380fcd719bfd188418f5/sqlglotrs-0.3.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5306cee54099fbd65a87e589aa827b2741088f3e18ae4c3057aca3f78f484fd5", size = 379553 }, + { url = "https://files.pythonhosted.org/packages/0d/36/e138813825f6d698ce5687bce4456bd0e9c8bf80468bf4bec6b8db5b3884/sqlglotrs-0.3.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d6bc103b23cf33d396ad8d6abd649d36855ebdee93b684f0383c2a907486e11", size = 329609 }, + { url = "https://files.pythonhosted.org/packages/6f/f0/49cfaa4fe297a3824992a88d61ea952d17b92d10592feb6d4bf35a369bc9/sqlglotrs-0.3.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4986b2d09f9c844cfb79b9e4e6da027869ac9550727d58a03cf17a99a7a79d07", size = 350040 }, + { url = "https://files.pythonhosted.org/packages/fe/fc/7d75ec43959e4751942b83fe26fe215a9a7d3e820eb3c8ac6cf32359b2a7/sqlglotrs-0.3.4-cp312-cp312-win32.whl", hash = "sha256:99f4b835aa48c51455389254a14ded5d371ac79fbd77ce9b734e6bf31a390e4f", size = 178183 }, + { url = "https://files.pythonhosted.org/packages/ef/c3/9e079adf1c426cb95b374e2c197ef40ad496167db1d5af99e427aeae0269/sqlglotrs-0.3.4-cp312-cp312-win_amd64.whl", hash = "sha256:e0d3aa68b7bc008d6a183a45cdbc573ded8b66727d700de9050d2bf0703cbf6b", size = 190403 }, + { url = "https://files.pythonhosted.org/packages/ea/63/5e9141e7304e4554bcb0edb0d272650609ce6a770e08bc656d0ac2bd7c40/sqlglotrs-0.3.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7a3e6b86c1f12adb96ce4bbfe11b00ec53b3dee07a9da68eb5bcc7ef9b544c11", size = 296316 }, + { url = "https://files.pythonhosted.org/packages/1a/83/020df139cd29f737fcfc544337a63c8354325c2218dadd15891f73bc4f3e/sqlglotrs-0.3.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:779ee5e0e2d3dc9dfa09d8fe0cf1635524335ef00e03f0d6b173733a911f5623", size = 284551 }, + { url = "https://files.pythonhosted.org/packages/c6/94/5bfecd4198cde739f0234d23cc90c8086104d08714d0e9430fb658b3573f/sqlglotrs-0.3.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:038aa86bfa3b9ee20ec26a1d348f69b6443c6435289802c3828bb63e3cd11bd1", size = 323243 }, + { url = "https://files.pythonhosted.org/packages/fb/9e/34f23308de53ddc9a4a2a29eefe3d6a9cf181f3ecc0e7fc0d65234814b3c/sqlglotrs-0.3.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03f28a4cc3076b878a6fc8f7413d1ede9d226ee5ac3cc416b7323fbdd53e24f5", size = 332791 }, + { url = "https://files.pythonhosted.org/packages/8b/e4/1879c97f237f7f2684273ac132200d5f5f6c6722df0b1131423d9e57a95a/sqlglotrs-0.3.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d62749aad9a6c0d085adf5dc4d70449c2fd763c6c4bba75f623151a3cb47dc20", size = 371936 }, + { url = "https://files.pythonhosted.org/packages/aa/ba/7e9956e4ae9db6970ff78a6c9fa56ed93a42ac205e65258ab31c61274809/sqlglotrs-0.3.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:000c6d4b13c69b7caa84fae7e72064c27892985a0bc987f7df9bed08428af7dc", size = 379162 }, + { url = "https://files.pythonhosted.org/packages/d9/f6/6cd6b37c73683f9a1ca29ae49a1d75455124711bffe15cdeb2efa3af073d/sqlglotrs-0.3.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:010dd22a9d1b7b54ef91b64d94e5459cf7e3a7ac35114fa4f9e31db7df50c246", size = 329209 }, + { url = "https://files.pythonhosted.org/packages/f8/39/0b3bbea3c7fc1dc69a73d7615b65de9e87c9888e7bee3368938573e15600/sqlglotrs-0.3.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a16069aaeba079cb14350b3d67b472137f1e465808d901d78f305b76fa433da4", size = 349283 }, + { url = "https://files.pythonhosted.org/packages/80/38/eb0f6ffcff012a736ffe5fcd4a8d15f8e68c37d49af3ed032518169b88b9/sqlglotrs-0.3.4-cp313-cp313-win32.whl", hash = "sha256:cb5a57e0f0f7b7c504f992a64bb75f486e2006cb2ee283cef3bb9a2cee8009ab", size = 177853 }, + { url = "https://files.pythonhosted.org/packages/78/f6/69c316471fd4d6488b1848be785187714ff6ad4c05a11d1fcfeb07e3572e/sqlglotrs-0.3.4-cp313-cp313-win_amd64.whl", hash = "sha256:60720696872538b1210f5ae150bac69fe9b506a29d98f8f87002185190bbee51", size = 190036 }, ] [[package]] @@ -3603,6 +3707,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289", size = 26610 }, ] +[[package]] +name = "tokenizers" +version = "0.21.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "huggingface-hub" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/20/41/c2be10975ca37f6ec40d7abd7e98a5213bb04f284b869c1a24e6504fd94d/tokenizers-0.21.0.tar.gz", hash = "sha256:ee0894bf311b75b0c03079f33859ae4b2334d675d4e93f5a4132e1eae2834fe4", size = 343021 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/5c/8b09607b37e996dc47e70d6a7b6f4bdd4e4d5ab22fe49d7374565c7fefaf/tokenizers-0.21.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:3c4c93eae637e7d2aaae3d376f06085164e1660f89304c0ab2b1d08a406636b2", size = 2647461 }, + { url = "https://files.pythonhosted.org/packages/22/7a/88e58bb297c22633ed1c9d16029316e5b5ac5ee44012164c2edede599a5e/tokenizers-0.21.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:f53ea537c925422a2e0e92a24cce96f6bc5046bbef24a1652a5edc8ba975f62e", size = 2563639 }, + { url = "https://files.pythonhosted.org/packages/f7/14/83429177c19364df27d22bc096d4c2e431e0ba43e56c525434f1f9b0fd00/tokenizers-0.21.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b177fb54c4702ef611de0c069d9169f0004233890e0c4c5bd5508ae05abf193", size = 2903304 }, + { url = "https://files.pythonhosted.org/packages/7e/db/3433eab42347e0dc5452d8fcc8da03f638c9accffefe5a7c78146666964a/tokenizers-0.21.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6b43779a269f4629bebb114e19c3fca0223296ae9fea8bb9a7a6c6fb0657ff8e", size = 2804378 }, + { url = "https://files.pythonhosted.org/packages/57/8b/7da5e6f89736c2ade02816b4733983fca1c226b0c42980b1ae9dc8fcf5cc/tokenizers-0.21.0-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9aeb255802be90acfd363626753fda0064a8df06031012fe7d52fd9a905eb00e", size = 3095488 }, + { url = "https://files.pythonhosted.org/packages/4d/f6/5ed6711093dc2c04a4e03f6461798b12669bc5a17c8be7cce1240e0b5ce8/tokenizers-0.21.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d8b09dbeb7a8d73ee204a70f94fc06ea0f17dcf0844f16102b9f414f0b7463ba", size = 3121410 }, + { url = "https://files.pythonhosted.org/packages/81/42/07600892d48950c5e80505b81411044a2d969368cdc0d929b1c847bf6697/tokenizers-0.21.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:400832c0904f77ce87c40f1a8a27493071282f785724ae62144324f171377273", size = 3388821 }, + { url = "https://files.pythonhosted.org/packages/22/06/69d7ce374747edaf1695a4f61b83570d91cc8bbfc51ccfecf76f56ab4aac/tokenizers-0.21.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84ca973b3a96894d1707e189c14a774b701596d579ffc7e69debfc036a61a04", size = 3008868 }, + { url = "https://files.pythonhosted.org/packages/c8/69/54a0aee4d576045b49a0eb8bffdc495634309c823bf886042e6f46b80058/tokenizers-0.21.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:eb7202d231b273c34ec67767378cd04c767e967fda12d4a9e36208a34e2f137e", size = 8975831 }, + { url = "https://files.pythonhosted.org/packages/f7/f3/b776061e4f3ebf2905ba1a25d90380aafd10c02d406437a8ba22d1724d76/tokenizers-0.21.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:089d56db6782a73a27fd8abf3ba21779f5b85d4a9f35e3b493c7bbcbbf0d539b", size = 8920746 }, + { url = "https://files.pythonhosted.org/packages/d8/ee/ce83d5ec8b6844ad4c3ecfe3333d58ecc1adc61f0878b323a15355bcab24/tokenizers-0.21.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:c87ca3dc48b9b1222d984b6b7490355a6fdb411a2d810f6f05977258400ddb74", size = 9161814 }, + { url = "https://files.pythonhosted.org/packages/18/07/3e88e65c0ed28fa93aa0c4d264988428eef3df2764c3126dc83e243cb36f/tokenizers-0.21.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4145505a973116f91bc3ac45988a92e618a6f83eb458f49ea0790df94ee243ff", size = 9357138 }, + { url = "https://files.pythonhosted.org/packages/15/b0/dc4572ca61555fc482ebc933f26cb407c6aceb3dc19c301c68184f8cad03/tokenizers-0.21.0-cp39-abi3-win32.whl", hash = "sha256:eb1702c2f27d25d9dd5b389cc1f2f51813e99f8ca30d9e25348db6585a97e24a", size = 2202266 }, + { url = "https://files.pythonhosted.org/packages/44/69/d21eb253fa91622da25585d362a874fa4710be600f0ea9446d8d0217cec1/tokenizers-0.21.0-cp39-abi3-win_amd64.whl", hash = "sha256:87841da5a25a3a5f70c102de371db120f41873b854ba65e52bccd57df5a3780c", size = 2389192 }, +] + [[package]] name = "tomlkit" version = "0.13.2" @@ -3816,38 +3945,41 @@ wheels = [ [[package]] name = "wrapt" -version = "1.17.0" +version = "1.17.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/24/a1/fc03dca9b0432725c2e8cdbf91a349d2194cf03d8523c124faebe581de09/wrapt-1.17.0.tar.gz", hash = "sha256:16187aa2317c731170a88ef35e8937ae0f533c402872c1ee5e6d079fcf320801", size = 55542 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/85/82/518605474beafff11f1a34759f6410ab429abff9f7881858a447e0d20712/wrapt-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:89fc28495896097622c3fc238915c79365dd0ede02f9a82ce436b13bd0ab7569", size = 38904 }, - { url = "https://files.pythonhosted.org/packages/80/6c/17c3b2fed28edfd96d8417c865ef0b4c955dc52c4e375d86f459f14340f1/wrapt-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:875d240fdbdbe9e11f9831901fb8719da0bd4e6131f83aa9f69b96d18fae7504", size = 88622 }, - { url = "https://files.pythonhosted.org/packages/4a/11/60ecdf3b0fd3dca18978d89acb5d095a05f23299216e925fcd2717c81d93/wrapt-1.17.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ed16d95fd142e9c72b6c10b06514ad30e846a0d0917ab406186541fe68b451", size = 80920 }, - { url = "https://files.pythonhosted.org/packages/d2/50/dbef1a651578a3520d4534c1e434989e3620380c1ad97e309576b47f0ada/wrapt-1.17.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18b956061b8db634120b58f668592a772e87e2e78bc1f6a906cfcaa0cc7991c1", size = 89170 }, - { url = "https://files.pythonhosted.org/packages/44/a2/78c5956bf39955288c9e0dd62e807b308c3aa15a0f611fbff52aa8d6b5ea/wrapt-1.17.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:daba396199399ccabafbfc509037ac635a6bc18510ad1add8fd16d4739cdd106", size = 86748 }, - { url = "https://files.pythonhosted.org/packages/99/49/2ee413c78fc0bdfebe5bee590bf3becdc1fab0096a7a9c3b5c9666b2415f/wrapt-1.17.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4d63f4d446e10ad19ed01188d6c1e1bb134cde8c18b0aa2acfd973d41fcc5ada", size = 79734 }, - { url = "https://files.pythonhosted.org/packages/c0/8c/4221b7b270e36be90f0930fe15a4755a6ea24093f90b510166e9ed7861ea/wrapt-1.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8a5e7cc39a45fc430af1aefc4d77ee6bad72c5bcdb1322cfde852c15192b8bd4", size = 87552 }, - { url = "https://files.pythonhosted.org/packages/4c/6b/1aaccf3efe58eb95e10ce8e77c8909b7a6b0da93449a92c4e6d6d10b3a3d/wrapt-1.17.0-cp312-cp312-win32.whl", hash = "sha256:0a0a1a1ec28b641f2a3a2c35cbe86c00051c04fffcfcc577ffcdd707df3f8635", size = 36647 }, - { url = "https://files.pythonhosted.org/packages/b3/4f/243f88ac49df005b9129194c6511b3642818b3e6271ddea47a15e2ee4934/wrapt-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:3c34f6896a01b84bab196f7119770fd8466c8ae3dfa73c59c0bb281e7b588ce7", size = 38830 }, - { url = "https://files.pythonhosted.org/packages/67/9c/38294e1bb92b055222d1b8b6591604ca4468b77b1250f59c15256437644f/wrapt-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:714c12485aa52efbc0fc0ade1e9ab3a70343db82627f90f2ecbc898fdf0bb181", size = 38904 }, - { url = "https://files.pythonhosted.org/packages/78/b6/76597fb362cbf8913a481d41b14b049a8813cd402a5d2f84e57957c813ae/wrapt-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da427d311782324a376cacb47c1a4adc43f99fd9d996ffc1b3e8529c4074d393", size = 88608 }, - { url = "https://files.pythonhosted.org/packages/bc/69/b500884e45b3881926b5f69188dc542fb5880019d15c8a0df1ab1dfda1f7/wrapt-1.17.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba1739fb38441a27a676f4de4123d3e858e494fac05868b7a281c0a383c098f4", size = 80879 }, - { url = "https://files.pythonhosted.org/packages/52/31/f4cc58afe29eab8a50ac5969963010c8b60987e719c478a5024bce39bc42/wrapt-1.17.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e711fc1acc7468463bc084d1b68561e40d1eaa135d8c509a65dd534403d83d7b", size = 89119 }, - { url = "https://files.pythonhosted.org/packages/aa/9c/05ab6bf75dbae7a9d34975fb6ee577e086c1c26cde3b6cf6051726d33c7c/wrapt-1.17.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:140ea00c87fafc42739bd74a94a5a9003f8e72c27c47cd4f61d8e05e6dec8721", size = 86778 }, - { url = "https://files.pythonhosted.org/packages/0e/6c/4b8d42e3db355603d35fe5c9db79c28f2472a6fd1ccf4dc25ae46739672a/wrapt-1.17.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:73a96fd11d2b2e77d623a7f26e004cc31f131a365add1ce1ce9a19e55a1eef90", size = 79793 }, - { url = "https://files.pythonhosted.org/packages/69/23/90e3a2ee210c0843b2c2a49b3b97ffcf9cad1387cb18cbeef9218631ed5a/wrapt-1.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0b48554952f0f387984da81ccfa73b62e52817a4386d070c75e4db7d43a28c4a", size = 87606 }, - { url = "https://files.pythonhosted.org/packages/5f/06/3683126491ca787d8d71d8d340e775d40767c5efedb35039d987203393b7/wrapt-1.17.0-cp313-cp313-win32.whl", hash = "sha256:498fec8da10e3e62edd1e7368f4b24aa362ac0ad931e678332d1b209aec93045", size = 36651 }, - { url = "https://files.pythonhosted.org/packages/f1/bc/3bf6d2ca0d2c030d324ef9272bea0a8fdaff68f3d1fa7be7a61da88e51f7/wrapt-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd136bb85f4568fffca995bd3c8d52080b1e5b225dbf1c2b17b66b4c5fa02838", size = 38835 }, - { url = "https://files.pythonhosted.org/packages/ce/b5/251165c232d87197a81cd362eeb5104d661a2dd3aa1f0b33e4bf61dda8b8/wrapt-1.17.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:17fcf043d0b4724858f25b8826c36e08f9fb2e475410bece0ec44a22d533da9b", size = 40146 }, - { url = "https://files.pythonhosted.org/packages/89/33/1e1bdd3e866eeb73d8c4755db1ceb8a80d5bd51ee4648b3f2247adec4e67/wrapt-1.17.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4a557d97f12813dc5e18dad9fa765ae44ddd56a672bb5de4825527c847d6379", size = 113444 }, - { url = "https://files.pythonhosted.org/packages/9f/7c/94f53b065a43f5dc1fbdd8b80fd8f41284315b543805c956619c0b8d92f0/wrapt-1.17.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0229b247b0fc7dee0d36176cbb79dbaf2a9eb7ecc50ec3121f40ef443155fb1d", size = 101246 }, - { url = "https://files.pythonhosted.org/packages/62/5d/640360baac6ea6018ed5e34e6e80e33cfbae2aefde24f117587cd5efd4b7/wrapt-1.17.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8425cfce27b8b20c9b89d77fb50e368d8306a90bf2b6eef2cdf5cd5083adf83f", size = 109320 }, - { url = "https://files.pythonhosted.org/packages/e3/cf/6c7a00ae86a2e9482c91170aefe93f4ccda06c1ac86c4de637c69133da59/wrapt-1.17.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9c900108df470060174108012de06d45f514aa4ec21a191e7ab42988ff42a86c", size = 110193 }, - { url = "https://files.pythonhosted.org/packages/cd/cc/aa718df0d20287e8f953ce0e2f70c0af0fba1d3c367db7ee8bdc46ea7003/wrapt-1.17.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:4e547b447073fc0dbfcbff15154c1be8823d10dab4ad401bdb1575e3fdedff1b", size = 100460 }, - { url = "https://files.pythonhosted.org/packages/f7/16/9f3ac99fe1f6caaa789d67b4e3c562898b532c250769f5255fa8b8b93983/wrapt-1.17.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:914f66f3b6fc7b915d46c1cc424bc2441841083de01b90f9e81109c9759e43ab", size = 106347 }, - { url = "https://files.pythonhosted.org/packages/64/85/c77a331b2c06af49a687f8b926fc2d111047a51e6f0b0a4baa01ff3a673a/wrapt-1.17.0-cp313-cp313t-win32.whl", hash = "sha256:a4192b45dff127c7d69b3bdfb4d3e47b64179a0b9900b6351859f3001397dabf", size = 37971 }, - { url = "https://files.pythonhosted.org/packages/05/9b/b2469f8be9efed24283fd7b9eeb8e913e9bc0715cf919ea8645e428ab7af/wrapt-1.17.0-cp313-cp313t-win_amd64.whl", hash = "sha256:4f643df3d4419ea3f856c5c3f40fec1d65ea2e89ec812c83f7767c8730f9827a", size = 40755 }, - { url = "https://files.pythonhosted.org/packages/4b/d9/a8ba5e9507a9af1917285d118388c5eb7a81834873f45df213a6fe923774/wrapt-1.17.0-py3-none-any.whl", hash = "sha256:d2c63b93548eda58abf5188e505ffed0229bf675f7c3090f8e36ad55b8cbc371", size = 23592 }, +sdist = { url = "https://files.pythonhosted.org/packages/c8/dd/35c573cc2b4b8d65ea96bba0247d05710f284857d30e2266d1874f1c727d/wrapt-1.17.1.tar.gz", hash = "sha256:16b2fdfa09a74a3930175b6d9d7d008022aa72a4f02de2b3eecafcc1adfd3cfe", size = 55552 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ea/40/7fb607aa889b107ab7417f633f1893f48be4fd8bd12ec89c6355d26560a8/wrapt-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b1a4c8edd038fee0ce67bf119b16eaa45d22a52bbaf7d0a17d2312eb0003b1bb", size = 38820 }, + { url = "https://files.pythonhosted.org/packages/ce/24/9e8b8b670c5ebab2c05e51ad7403c5317985c53071d0ce4bb85684b9dce1/wrapt-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:181a844005c9818792212a32e004cb4c6bd8e35cae8e97b1a39a1918d95cef58", size = 38921 }, + { url = "https://files.pythonhosted.org/packages/d7/00/c07c9893e6761ee60d59ec319b33b2d3c5b68da674cbbf8ebf6c54cba146/wrapt-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21ffcf16f5c243a626b0f8da637948e3d5984e3bc0c1bc500ad990e88e974e3b", size = 88720 }, + { url = "https://files.pythonhosted.org/packages/d6/09/d3962a902a6be1d5a66b04ec10189618796a5a9b3fb87d0873294661289d/wrapt-1.17.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0eb33799b7582bb73787b9903b70595f8eff67eecc9455f668ed01adf53f9eea", size = 80899 }, + { url = "https://files.pythonhosted.org/packages/e2/fc/92d37def794c3626fb3c3aa112aa629544ba21f6c565034dae0e587f03c0/wrapt-1.17.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57e932ad1908b53e9ad67a746432f02bc8473a9ee16e26a47645a2b224fba5fd", size = 89222 }, + { url = "https://files.pythonhosted.org/packages/cd/4f/e0921cb71ed320508cbcf0e450449642c4b892f64bc5b2696ca725427dea/wrapt-1.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b8bd35c15bc82c5cbe397e8196fa57a17ce5d3f30e925a6fd39e4c5bb02fdcff", size = 86707 }, + { url = "https://files.pythonhosted.org/packages/85/16/f61d6afe9c3c9932f8699a62e4e594bcac87fdffc7dbd8f603939c44cfa5/wrapt-1.17.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:93018dbb956e0ad99ea2fa2c3c22f033549dcb1f56ad9f4555dfe25e49688c5d", size = 79685 }, + { url = "https://files.pythonhosted.org/packages/95/1d/a1940ce270fa7793044e7131d48528b7d4a6ab2e038142a7c82d722aa5c1/wrapt-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e5bd9186d52cf3d36bf1823be0e85297e4dbad909bc6dd495ce0d272806d84a7", size = 87568 }, + { url = "https://files.pythonhosted.org/packages/f0/ca/d1292891bfdda05a77b0bdc2ecdca4a9484b02d64a65e2afddfcb5ac17e1/wrapt-1.17.1-cp312-cp312-win32.whl", hash = "sha256:d609f0ab0603bbcbf2de906b366b9f9bec75c32b4493550a940de658cc2ce512", size = 36672 }, + { url = "https://files.pythonhosted.org/packages/63/0f/0d52bff5074392586eb754609bc0877cea5340a2152f946166002b70ed07/wrapt-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:2c160bb8815787646b27a0c8575a26a4d6bf6abd7c5eb250ad3f2d38b29cb2cb", size = 38866 }, + { url = "https://files.pythonhosted.org/packages/0e/16/82d25dd10e97eabb561d491487ff111ac272a4024f40df098bd61c96840b/wrapt-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:99e544e6ce26f89ad5acc6f407bc4daf7c1d42321e836f5c768f834100bdf35c", size = 38821 }, + { url = "https://files.pythonhosted.org/packages/08/e2/c79dd3c9712988156ea86cd507a81f2b3f045eb84af2d0f7aedb42c709f9/wrapt-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:78da796b74f2c8e0af021ee99feb3bff7cb46f8e658fe25c20e66be1080db4a2", size = 38920 }, + { url = "https://files.pythonhosted.org/packages/4d/d8/bc2bb9797543b31ef7311074583c83addbfc21f1bead66ca7c9d637de6fd/wrapt-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f1bc359f6c52e53565e7af24b423e7a1eea97d155f38ac9e90e95303514710b", size = 88691 }, + { url = "https://files.pythonhosted.org/packages/e7/d3/8d64b5ced10eb0ef856ae864c806292de4891c4945db3444188d45a17b43/wrapt-1.17.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cbead724daa13cae46e8ab3bb24938d8514d123f34345535b184f3eb1b7ad717", size = 80862 }, + { url = "https://files.pythonhosted.org/packages/65/22/ee8e9a7014f7c011edac4a9babea4d0aa73a363dd618afc9b31669e478a8/wrapt-1.17.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdf7b0e3d3713331c0bb9daac47cd10e5aa60d060e53696f50de4e560bd5617f", size = 89174 }, + { url = "https://files.pythonhosted.org/packages/fd/10/3d1610d0c220a9f09317d7c9c216889b9dd67329e23d2fcf1017f2d67fc9/wrapt-1.17.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f17e8d926f63aed65ff949682c922f96d00f65c2e852c24272232313fa7823d5", size = 86721 }, + { url = "https://files.pythonhosted.org/packages/3c/c1/2f4b20057afcfbfad4886138a702ae2ffd79abbb43884b31e2388895e367/wrapt-1.17.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9e04f3bd30e0b23c0ca7e1d4084e7d28b6d7d2feb8b7bc69b496fe881280579b", size = 79761 }, + { url = "https://files.pythonhosted.org/packages/f2/c9/c6bde0a10a7108da0ffaa0a8337221e66636199b367e7d6f1d035e0b306a/wrapt-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5660e470edfa15ae7ef407272c642d29e9962777a6b30bfa8fc0da2173dc9afd", size = 87586 }, + { url = "https://files.pythonhosted.org/packages/2a/ad/956a2db1196bde82088f5576eb1d7a290c4ffc0dec00bfc9d29fca440fff/wrapt-1.17.1-cp313-cp313-win32.whl", hash = "sha256:a992f9e019145e84616048556546edeaba68e05e1c1ffbe8391067a63cdadb0c", size = 36678 }, + { url = "https://files.pythonhosted.org/packages/d7/3a/8bf805ab213f7830b5998027ada2a3fae8e93529df7b0c446946d7f8e9e9/wrapt-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:5c2e24ba455af4b0a237a890ea6ed9bafd01fac2c47095f87c53ea3344215d43", size = 38873 }, + { url = "https://files.pythonhosted.org/packages/d7/76/878e3891ea25875608c5075b81240a4060e48eec786ff354b2a5d3eb87f1/wrapt-1.17.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88623fd957ba500d8bb0f7427a76496d99313ca2f9e932481c0882e034cf1add", size = 40060 }, + { url = "https://files.pythonhosted.org/packages/76/4b/fdde9124f6f61a56e1982cd0f7f0bc8fe2ababb876a50da3308e9ea462a0/wrapt-1.17.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:162d5f15bdd3b8037e06540902227ef9e0f298496c0afaadd9e2875851446693", size = 40154 }, + { url = "https://files.pythonhosted.org/packages/17/f2/e3d909ded67bd7d15b7f02f9cb05e111d2fef9499c1dc0f43690391b8c53/wrapt-1.17.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bb82447ddae4e3d9b51f40c494f66e6cbd8fb0e8e8b993678416535c67f9a0d", size = 113469 }, + { url = "https://files.pythonhosted.org/packages/6f/96/2ba3bd9b2d81b139a5784bf997bffc54979b561c272a953af3a69c242e02/wrapt-1.17.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ce4cff3922707048d754e365c4ebf41a3bcbf29b329349bf85d51873c7c7e9e", size = 101207 }, + { url = "https://files.pythonhosted.org/packages/eb/9a/c8e0275eeef83f0b8bf685034244fb0bf21d2e759fd7a6d54005de6b887f/wrapt-1.17.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fdc4e73a3fa0c25eed4d836d9732226f0326957cb075044a7f252b465299433", size = 109341 }, + { url = "https://files.pythonhosted.org/packages/4b/e3/346259c335b04d342beddba6a97030932b53a8ae35d7ff8a319ab2204270/wrapt-1.17.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:bca1c0824f824bcd97b4b179dd55dcad1dab419252be2b2faebbcacefa3b27b2", size = 110232 }, + { url = "https://files.pythonhosted.org/packages/c3/aa/9611db2f50359b0b091e501405bc2497b7369185b342cae7bb2218a986e8/wrapt-1.17.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:6d44b14f3a2f6343a07c90344850b7af5515538ce3a5d01f9c87d8bae9bd8724", size = 100474 }, + { url = "https://files.pythonhosted.org/packages/33/c2/edbcad020deeb742bce83647a7d13e47c35fafcab4fba4a89ec006ad0385/wrapt-1.17.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:169033329022739c6f0d8cd3031a113953b0ba500f3d5978904bdd40baec4568", size = 106377 }, + { url = "https://files.pythonhosted.org/packages/4f/bf/e2aa032cea63737cbabd4069c86d6aa4ba075ee19c44a165e1362a5b403b/wrapt-1.17.1-cp313-cp313t-win32.whl", hash = "sha256:52f0907287d9104112dbebda46af4db0793fcc4c64c8a867099212d116b6db64", size = 37987 }, + { url = "https://files.pythonhosted.org/packages/77/fb/439f032c1b52a1750c304ff85253edfec3a50d4e39fa9a338ab0f837acb4/wrapt-1.17.1-cp313-cp313t-win_amd64.whl", hash = "sha256:7966f98fa36933333d8a1c3d8552aa3d0735001901a4aabcfbd5a502b4ef14fe", size = 40751 }, + { url = "https://files.pythonhosted.org/packages/94/47/299f204e352655c117b9dec03fc585866df7eea72660515208ec67c185c4/wrapt-1.17.1-py3-none-any.whl", hash = "sha256:f3117feb1fc479eaf84b549d3f229d5d2abdb823f003bc2a1c6dd70072912fa0", size = 23589 }, ] [[package]] From 0ebfdf985797369a1bf6386e6c01b1152f0806cd Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Mon, 13 Jan 2025 18:23:22 +0000 Subject: [PATCH 02/64] Update image processing --- image_processing/.env.example | 12 + image_processing/adi_2_ai_search.py | 645 ---------------------- image_processing/key_phrase_extraction.py | 167 ------ image_processing/storage_account.py | 117 ---- 4 files changed, 12 insertions(+), 929 deletions(-) create mode 100644 image_processing/.env.example delete mode 100644 image_processing/adi_2_ai_search.py delete mode 100644 image_processing/key_phrase_extraction.py delete mode 100644 image_processing/storage_account.py diff --git a/image_processing/.env.example b/image_processing/.env.example new file mode 100644 index 00000000..eb0ec417 --- /dev/null +++ b/image_processing/.env.example @@ -0,0 +1,12 @@ +FunctionApp__ClientId= +IdentityType= # system_assigned or user_assigned or key +OpenAI__ApiKey= +OpenAI__Endpoint= +OpenAI__MultiModalDeployment= +OpenAI__ApiVersion= +AIService__DocumentIntelligence__Endpoint= +AIService__DocumentIntelligence__Key= +AIService__Language__Endpoint= +AIService__Language__Key= +StorageAccount__Endpoint= +StorageAccount__ConnectionString= diff --git a/image_processing/adi_2_ai_search.py b/image_processing/adi_2_ai_search.py deleted file mode 100644 index 154b63b2..00000000 --- a/image_processing/adi_2_ai_search.py +++ /dev/null @@ -1,645 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -from azure.identity import DefaultAzureCredential, get_bearer_token_provider -import base64 -from azure.core.credentials import AzureKeyCredential -from azure.ai.documentintelligence.aio import DocumentIntelligenceClient -from azure.ai.documentintelligence.models import ( - AnalyzeResult, - ContentFormat, - AnalyzeOutputOption, -) -import os -import re -import asyncio -import logging -from storage_account import StorageAccountHelper -import json -from openai import AsyncAzureOpenAI -from typing import Union -import openai -from environment import IdentityType, get_identity_type - - -async def build_and_clean_markdown_for_response( - markdown_text: str, - page_no: int = None, - remove_irrelevant_figures=False, -): - """Clean Markdown text extracted by the Azure Document Intelligence service. - - Args: - ----- - markdown_text (str): The original Markdown text. - remove_irrelevant_figures (bool): Whether to remove all figures or just irrelevant ones. - - Returns: - -------- - str: The cleaned Markdown text. - """ - - # Pattern to match the comment start `` - # Matches opening `|\<)" - - # Using re.sub to remove comments - cleaned_text = re.sub( - f"{comment_start_pattern}.*?{comment_end_pattern}", "", markdown_text - ) - - # Remove irrelevant figures - if remove_irrelevant_figures: - irrelevant_figure_pattern = r"]*>.*?Irrelevant Image.*?" - cleaned_text = re.sub( - irrelevant_figure_pattern, "", cleaned_text, flags=re.DOTALL - ) - - logging.info(f"Cleaned Text: {cleaned_text}") - - # add page number when chunk by page is enabled - if page_no is not None: - output_dict = {} - output_dict["content"] = cleaned_text - output_dict["pageNumber"] = page_no - return output_dict - else: - return cleaned_text - - -def update_figure_description( - md_content: str, figure_id: str, img_description: str, offset: int, length: int -): - """ - Updates the figure description in the Markdown content. - - Args: - md_content (str): The original Markdown content. - img_description (str): The new description for the image. - offset (int): Position offset in the text. - length (int): Length of the original figure in the text. - - Returns: - str: The updated Markdown content with the new figure description. - """ - - # Define the new string to replace the old content - new_string = f"""""" - - # Calculate the end index of the content to be replaced - end_index = offset + length - - # Ensure that the end_index does not exceed the length of the Markdown content - if end_index > len(md_content): - end_index = len(md_content) - - # Replace the old string with the new string - new_md_content = md_content[:offset] + new_string + md_content[end_index:] - - return new_md_content, len(new_string) - - -async def understand_image_with_gptv(image_base64, caption, tries_left=3): - """ - Generates a description for an image using the GPT-4V model. - - Parameters: - - image_base64 (str): image file. - - caption (str): The caption for the image. - - Returns: - - img_description (str): The generated description for the image. - """ - - MAX_TOKENS = 2000 - api_version = os.environ["OpenAI__ApiVersion"] - model = os.environ["OpenAI__MultiModalDeployment"] - - if get_identity_type() == IdentityType.SYSTEM_ASSIGNED: - token_provider = get_bearer_token_provider( - DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" - ) - api_key = None - elif get_identity_type() == IdentityType.USER_ASSIGNED: - token_provider = get_bearer_token_provider( - DefaultAzureCredential( - managed_identity_client_id=os.environ["FunctionApp__ClientId"] - ), - "https://cognitiveservices.azure.com/.default", - ) - api_key = None - else: - token_provider = None - api_key = os.environ["OpenAI__ApiKey"] - - system_prompt = """You are an expert in technical image analysis. Your task is to provided analysis of images. You should FOCUS on what info can be inferred from the image and the meaning of the data inside the image. Draw actionable insights and conclusions from the image. Do not describe the image in a general way or describe the image in a way that is not useful for decision-making. - - If the image is a chart for instance, you should describe the data trends, patterns, and insights that can be drawn from the chart. For example, you could describe the increase or decrease in sales over time, the peak sales period, or the sales performance of a particular product. - - If the image is a map, you should describe the geographical features, landmarks, and any other relevant information that can be inferred from the map. - - If the image is a diagram, you should describe the components, relationships, and any other relevant information that can be inferred from the diagram. - - Include any data points, labels, and other relevant information that can be inferred from the image. - - Provide a well-structured, detailed, and actionable analysis of the image. Focus on extracting data and information that can be inferred from the image. - - IMPORTANT: If the provided image is a logo or photograph, simply return 'Irrelevant Image'.""" - - user_input = "Perform technical analysis on this image. Provide a well-structured, description." - - if caption is not None and len(caption) > 0: - user_input += f" (note: it has the following caption: {caption})" - - try: - async with AsyncAzureOpenAI( - api_key=api_key, - api_version=api_version, - azure_ad_token_provider=token_provider, - azure_endpoint=os.environ.get("OpenAI__Endpoint"), - ) as client: - # We send both image caption and the image body to GPTv for better understanding - response = await client.chat.completions.create( - model=model, - messages=[ - { - "role": "system", - "content": system_prompt, - }, - { - "role": "user", - "content": [ - { - "type": "text", - "text": user_input, - }, - { - "type": "image_url", - "image_url": { - "url": f"data:image/png;base64,{image_base64}" - }, - }, - ], - }, - ], - max_tokens=MAX_TOKENS, - ) - - logging.info(f"Response: {response}") - - img_description = response.choices[0].message.content - - logging.info(f"Image Description: {img_description}") - - return img_description - except openai.RateLimitError as e: - logging.error("OpenAI Rate Limit Error: %s", e) - - if tries_left > 0: - logging.info( - "Retrying understanding of image with %s tries left.", tries_left - ) - remaining_tries = tries_left - 1 - backoff = 20 ** (3 - remaining_tries) - await asyncio.sleep(backoff) - return await understand_image_with_gptv( - image_base64, caption, tries_left=remaining_tries - ) - else: - raise Exception("OpenAI Rate Limit Error: No retries left.") from e - except (openai.OpenAIError, openai.APIConnectionError) as e: - logging.error("OpenAI Error: %s", e) - - raise Exception("OpenAI Connection Error: No retries left.") from e - - -async def download_figure_image( - model_id: str, operation_id: str, figure_id: str -) -> bytearray: - """Download the image associated with a figure extracted by the Azure Document Intelligence service. - - Args: - ----- - model_id (str): The model ID used for the analysis. - operation_id (str): The operation ID of the analysis. - figure_id (str): The ID of the figure to download. - - Returns: - -------- - bytes: The image associated with the figure.""" - document_intelligence_client = await get_document_intelligence_client() - async with document_intelligence_client: - response = await document_intelligence_client.get_analyze_result_figure( - model_id=model_id, result_id=operation_id, figure_id=figure_id - ) - - full_bytes = bytearray() - async for chunk in response: - full_bytes.extend(chunk) - - return full_bytes - - -async def process_figures_from_extracted_content( - result: AnalyzeResult, - operation_id: str, - container_and_blob: str, - markdown_content: str, - page_number: None | int = None, - page_offset: int = 0, -) -> Union[str, dict]: - """Process the figures extracted from the content using ADI and send them for analysis. - - Args: - ----- - result (AnalyzeResult): The result of the document analysis. - operation_id (str): The operation ID of the analysis. - container_and_blob (str): The container and blob of the document. - markdown_content (str): The extracted content in Markdown format. - page_number (int): The page number to process. If None, all pages are processed. - page_offset (int): The offset of the page. - - Returns: - -------- - str: The updated Markdown content with the figure descriptions. - dict: A mapping of the FigureId to the stored Uri in blob storage.""" - - figure_processing_datas = [] - download_image_tasks = [] - figure_understanding_tasks = [] - figure_upload_tasks = [] - - if result.figures: - for figure in result.figures: - if figure.id is None: - continue - - for region in figure.bounding_regions: - if page_number is not None and region.page_number != page_number: - continue - - logging.info(f"Figure ID: {figure.id}") - download_image_tasks.append( - download_figure_image( - model_id=result.model_id, - operation_id=operation_id, - figure_id=figure.id, - ) - ) - - container, blob = container_and_blob - image_blob = f"{blob}/{figure.id}.png" - - caption = figure.caption.content if figure.caption is not None else None - - logging.info(f"Figure Caption: {caption}") - - figure_processing_datas.append( - (figure.id, container, image_blob, caption, figure.spans[0]) - ) - - break - - logging.info("Running image download tasks") - image_responses = await asyncio.gather(*download_image_tasks) - logging.info("Finished image download tasks") - - storage_account_helper = await get_storage_account_helper() - - for figure_processing_data, response in zip( - figure_processing_datas, image_responses - ): - _, container, image_blob, caption, _ = figure_processing_data - base_64_image = base64.b64encode(response).decode("utf-8") - - logging.info(f"Image Blob: {image_blob}") - - figure_understanding_tasks.append( - understand_image_with_gptv(base_64_image, caption) - ) - - image_data = base64.b64decode(base_64_image) - - figure_upload_tasks.append( - storage_account_helper.upload_blob( - container, image_blob, image_data, "image/png" - ) - ) - - logging.info("Running image understanding tasks") - figure_descriptions = await asyncio.gather(*figure_understanding_tasks) - logging.info("Finished image understanding tasks") - logging.info(f"Image Descriptions: {figure_descriptions}") - - logging.info("Running image upload tasks") - await asyncio.gather(*figure_upload_tasks) - logging.info("Finished image upload tasks") - - running_offset = 0 - for figure_processing_data, figure_description in zip( - figure_processing_datas, figure_descriptions - ): - figure_id, _, _, _, figure_span = figure_processing_data - starting_offset = figure_span.offset + running_offset - page_offset - markdown_content, desc_offset = update_figure_description( - markdown_content, - figure_id, - figure_description, - starting_offset, - figure_span.length, - ) - running_offset += desc_offset - - return markdown_content - - -def create_page_wise_content(result: AnalyzeResult) -> list: - """Create a list of page-wise content extracted by the Azure Document Intelligence service. - - Args: - ----- - result (AnalyzeResult): The result of the document analysis. - - Returns: - -------- - list: A list of page-wise content extracted by the Azure Document Intelligence service. - """ - - page_wise_content = [] - page_numbers = [] - page_offsets = [] - - for page in result.pages: - page_content = result.content[ - page.spans[0]["offset"] : page.spans[0]["offset"] + page.spans[0]["length"] - ] - page_wise_content.append(page_content) - page_numbers.append(page.page_number) - page_offsets.append(page.spans[0]["offset"]) - - return page_wise_content, page_numbers, page_offsets - - -async def get_document_intelligence_client() -> DocumentIntelligenceClient: - """Get the Azure Document Intelligence client. - - Returns: - -------- - DocumentIntelligenceClient: The Azure Document Intelligence client.""" - if get_identity_type() == IdentityType.SYSTEM_ASSIGNED: - credential = DefaultAzureCredential() - elif get_identity_type() == IdentityType.USER_ASSIGNED: - credential = DefaultAzureCredential( - managed_identity_client_id=os.environ["FunctionApp__ClientId"] - ) - else: - credential = AzureKeyCredential( - os.environ["AIService__DocumentIntelligence__Key"] - ) - - return DocumentIntelligenceClient( - endpoint=os.environ["AIService__DocumentIntelligence__Endpoint"], - credential=credential, - ) - - -async def get_storage_account_helper() -> StorageAccountHelper: - """Get the Storage Account Helper. - - Returns: - -------- - StorageAccountHelper: The Storage Account Helper.""" - - return StorageAccountHelper() - - -async def analyse_document(file_path: str) -> tuple[AnalyzeResult, str]: - """Analyse a document using the Azure Document Intelligence service. - - Args: - ----- - file_path (str): The path to the document to analyse. - - Returns: - -------- - AnalyzeResult: The result of the document analysis. - str: The operation ID of the analysis. - """ - with open(file_path, "rb") as f: - file_read = f.read() - - document_intelligence_client = await get_document_intelligence_client() - async with document_intelligence_client: - poller = await document_intelligence_client.begin_analyze_document( - model_id="prebuilt-layout", - analyze_request=file_read, - output_content_format=ContentFormat.MARKDOWN, - output=[AnalyzeOutputOption.FIGURES], - content_type="application/octet-stream", - ) - - result = await poller.result() - - operation_id = poller.details["operation_id"] - - if result is None or result.content is None or result.pages is None: - raise ValueError( - "Failed to analyze the document with Azure Document Intelligence." - ) - - return result, operation_id - - -async def process_adi_2_ai_search(record: dict, chunk_by_page: bool = False) -> dict: - """Process the extracted content from the Azure Document Intelligence service and prepare it for Azure Search. - - Args: - ----- - record (dict): The record containing the extracted content. - chunk_by_page (bool): Whether to chunk the content by page. - - Returns: - -------- - dict: The processed content ready for Azure Search.""" - logging.info("Python HTTP trigger function processed a request.") - - storage_account_helper = await get_storage_account_helper() - - try: - source = record["data"]["source"] - logging.info(f"Request Body: {record}") - except KeyError: - return { - "recordId": record["recordId"], - "data": {}, - "errors": [ - { - "message": "Failed to extract data with ADI. Pass a valid source in the request body.", - } - ], - "warnings": None, - } - else: - logging.info(f"Source: {source}") - - try: - source_parts = source.split("/") - blob = "/".join(source_parts[4:]) - logging.info(f"Blob: {blob}") - - container = source_parts[3] - - container_and_blob = (container, blob) - - file_extension = blob.split(".")[-1] - target_file_name = f"{record['recordId']}.{file_extension}" - - temp_file_path, _ = await storage_account_helper.download_blob_to_temp_dir( - blob, container, target_file_name - ) - logging.info(temp_file_path) - except Exception as e: - logging.error(f"Failed to download the blob: {e}") - return { - "recordId": record["recordId"], - "data": {}, - "errors": [ - { - "message": f"Failed to download the blob. Check the source and try again. {e}", - } - ], - "warnings": None, - } - - try: - result, operation_id = await analyse_document(temp_file_path) - except Exception as e: - logging.error(e) - logging.info("Sleeping for 10 seconds and retrying") - await asyncio.sleep(10) - try: - result, operation_id = await analyse_document(temp_file_path) - except ValueError as inner_e: - logging.error(inner_e) - logging.error( - "Failed to analyse %s with Azure Document Intelligence.", blob - ) - await storage_account_helper.add_metadata_to_blob( - blob, container, {"AzureSearch_Skip": "true"} - ) - return { - "recordId": record["recordId"], - "data": {}, - "errors": [ - { - "message": f"Failed to analyze the document with Azure Document Intelligence. This blob will now be skipped {inner_e}", - } - ], - "warnings": None, - } - except Exception as inner_e: - logging.error(inner_e) - logging.error( - "Failed to analyse %s with Azure Document Intelligence.", blob - ) - return { - "recordId": record["recordId"], - "data": {}, - "errors": [ - { - "message": f"Failed to analyze the document with Azure Document Intelligence. Check the logs and try again. {inner_e}", - } - ], - "warnings": None, - } - - try: - if chunk_by_page: - cleaned_result = [] - markdown_content, page_numbers, page_offsets = create_page_wise_content( - result - ) - content_with_figures_tasks = [ - process_figures_from_extracted_content( - result, - operation_id, - container_and_blob, - page_content, - page_number=page_number, - page_offset=page_offset, - ) - for page_content, page_number, page_offset in zip( - markdown_content, page_numbers, page_offsets - ) - ] - content_with_figures = await asyncio.gather(*content_with_figures_tasks) - - build_and_clean_markdown_for_response_tasks = [] - - for extracted_page_content, page_number in zip( - content_with_figures, page_numbers - ): - build_and_clean_markdown_for_response_tasks.append( - build_and_clean_markdown_for_response( - extracted_page_content, - page_number, - True, - ) - ) - - build_and_clean_markdown_for_response_results = await asyncio.gather( - *build_and_clean_markdown_for_response_tasks - ) - - for result in build_and_clean_markdown_for_response_results: - if len(result["content"]) == 0: - logging.error( - "No content found in the cleaned result for slide %s.", - result["pageNumber"], - ) - else: - cleaned_result.append(result) - - else: - markdown_content = result.content - - (extracted_content) = await process_figures_from_extracted_content( - result, - operation_id, - container_and_blob, - markdown_content, - page_offset=0, - page_number=None, - ) - - cleaned_result = await build_and_clean_markdown_for_response( - extracted_content, remove_irrelevant_figures=True - ) - except Exception as e: - logging.error(e) - logging.error(f"Failed to process the extracted content: {e}") - return { - "recordId": record["recordId"], - "data": {}, - "errors": [ - { - "message": f"Failed to process the extracted content. Check the logs and try again. {e}", - } - ], - "warnings": None, - } - - logging.info("Document Extracted") - logging.info(f"Result: {cleaned_result}") - - src = { - "recordId": record["recordId"], - "data": {"extracted_content": cleaned_result}, - } - - json_str = json.dumps(src, indent=4) - - logging.info(f"final output: {json_str}") - - return src diff --git a/image_processing/key_phrase_extraction.py b/image_processing/key_phrase_extraction.py deleted file mode 100644 index 78b03279..00000000 --- a/image_processing/key_phrase_extraction.py +++ /dev/null @@ -1,167 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -import logging -import json -import os -from azure.ai.textanalytics.aio import TextAnalyticsClient -from azure.core.exceptions import HttpResponseError -from azure.identity import DefaultAzureCredential -from tenacity import retry -from tenacity.stop import stop_after_attempt -from tenacity.wait import wait_exponential -import asyncio - -MAX_TEXT_ELEMENTS = 5120 - - -def split_document(document, max_size): - """Split a document into chunks of max_size and filter out any empty strings - - Args: - document (str): The document to split. - max_size (int): The maximum size of each chunk. - - Returns: - list: The list of document chunks.""" - return [ - document[i : i + max_size] - for i in range(0, len(document), max_size) - if len(document[i : i + max_size]) > 0 - ] - - -@retry( - reraise=True, - stop=stop_after_attempt(3), - wait=wait_exponential(multiplier=1, min=1, max=10), -) -async def extract_key_phrases_from_batch( - batch_data: list[str], max_key_phrase_count: int -) -> list[str]: - """Extract key phrases from text using Azure AI services. - - Args: - batch_data (list[str]): The list of text to process. - max_key_phrase_count(int): no of keywords to return - - Returns: - list: The list of key phrases.""" - - key_phrase_list = [] - - text_analytics_client = TextAnalyticsClient( - endpoint=os.environ["AIService__Services__Endpoint"], - credential=DefaultAzureCredential( - managed_identity_client_id=os.environ.get("FunctionApp__ClientId") - ), - ) - - async with text_analytics_client: - try: - result = await text_analytics_client.extract_key_phrases(batch_data) - for doc in result: - if not doc.is_error: - key_phrase_list.extend(doc.key_phrases[:max_key_phrase_count]) - else: - raise Exception(f"Document error: {doc.error}") - except HttpResponseError as e: - logging.error("An error occurred: %s", e) - raise e - - return key_phrase_list - - -async def extract_key_phrases_from_text( - data: list[str], max_key_phrase_count: int -) -> list[str]: - """Extract key phrases from text using Azure AI services. - - Args: - data (list[str]): The list of text to process. - max_key_phrase_count(int): no of keywords to return""" - logging.info("Python HTTP trigger function processed a request.") - key_phrase_list = [] - - split_documents = [] - for doc in data: - if len(doc) > MAX_TEXT_ELEMENTS: - split_documents.extend(split_document(doc, MAX_TEXT_ELEMENTS)) - elif len(doc) > 0: - split_documents.append(doc) - - # Filter out any empty documents - split_documents = [doc for doc in split_documents if len(doc) > 0] - - for i in range(0, len(split_documents), 10): - key_phrase_list.extend( - await extract_key_phrases_from_batch( - split_documents[i : i + 10], max_key_phrase_count - ) - ) - - if len(key_phrase_list) > max_key_phrase_count: - key_phrase_list = key_phrase_list[:max_key_phrase_count] - break - - return key_phrase_list - - -async def process_key_phrase_extraction( - record: dict, max_key_phrase_count: int = 5 -) -> dict: - """Extract key phrases using azure ai services. - - Args: - record (dict): The record to process. - max_key_phrase_count(int): no of keywords to return - - Returns: - dict: extracted key words.""" - - try: - json_str = json.dumps(record, indent=4) - - logging.info(f"key phrase extraction Input: {json_str}") - extracted_record = { - "recordId": record["recordId"], - "data": {}, - "errors": None, - "warnings": None, - } - extracted_record["data"]["keyPhrases"] = await extract_key_phrases_from_text( - [record["data"]["text"]], max_key_phrase_count - ) - except Exception as e: - logging.error("key phrase extraction Error: %s", e) - await asyncio.sleep(10) - try: - extracted_record = { - "recordId": record["recordId"], - "data": {}, - "errors": None, - "warnings": None, - } - extracted_record["data"][ - "keyPhrases" - ] = await extract_key_phrases_from_text( - [record["data"]["text"]], max_key_phrase_count - ) - except Exception as inner_e: - logging.error("key phrase extraction Error: %s", inner_e) - logging.error( - "Failed to extract key phrase. Check function app logs for more details of exact failure." - ) - return { - "recordId": record["recordId"], - "data": {}, - "errors": [ - { - "message": "Failed to extract key phrase. Check function app logs for more details of exact failure." - } - ], - "warnings": None, - } - json_str = json.dumps(extracted_record, indent=4) - - logging.info(f"key phrase extraction output: {json_str}") - return extracted_record diff --git a/image_processing/storage_account.py b/image_processing/storage_account.py deleted file mode 100644 index 015a144f..00000000 --- a/image_processing/storage_account.py +++ /dev/null @@ -1,117 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -import logging -import os -import tempfile -from azure.storage.blob.aio import BlobServiceClient -from azure.identity import DefaultAzureCredential -import urllib -from environment import IdentityType, get_identity_type - - -class StorageAccountHelper: - """Helper class for interacting with Azure Blob Storage.""" - - async def get_client(self): - """Get the BlobServiceClient object.""" - if get_identity_type() == IdentityType.SYSTEM_ASSIGNED: - endpoint = os.environ.get("StorageAccount__Endpoint") - credential = DefaultAzureCredential() - return BlobServiceClient(account_url=endpoint, credential=credential) - elif get_identity_type() == IdentityType.USER_ASSIGNED: - endpoint = os.environ.get("StorageAccount__Endpoint") - credential = DefaultAzureCredential( - managed_identity_client_id=os.environ.get("FunctionApp__ClientId") - ) - return BlobServiceClient(account_url=endpoint, credential=credential) - else: - endpoint = os.environ.get("StorageAccount__ConnectionString") - return BlobServiceClient(account_url=endpoint) - - async def add_metadata_to_blob( - self, source: str, container: str, metadata: dict - ) -> None: - """Add metadata to the blob. - - Args - source (str): The source of the blob. - container (str): The container of the blob. - metadata (dict): The metadata to add to the blob.""" - - blob = urllib.parse.unquote_plus(source) - - blob_service_client = await self.get_client() - async with blob_service_client: - async with blob_service_client.get_blob_client( - container=container, blob=blob - ) as blob_client: - await blob_client.set_blob_metadata(metadata) - - logging.info("Metadata Added") - - async def upload_blob( - self, container: str, blob: str, data, content_type: str - ) -> str: - """Upload the file to the Azure Blob Storage. - - Args: - container (str): The container of the blob. - blob (str): The blob name. - data (bytes): The data to upload. - - Returns: - str: url of the uploaded blob.""" - - logging.info("Uploading Blob...") - logging.info(f"Container: {container}") - logging.info(f"Blob: {blob}") - - blob_service_client = await self.get_client() - async with blob_service_client: - async with blob_service_client.get_blob_client( - container=container, blob=blob - ) as blob_client: - await blob_client.upload_blob( - data, - overwrite=True, - blob_type="BlockBlob", - content_type=content_type, - ) - - return blob_client.url - - async def download_blob_to_temp_dir( - self, source: str, container: str, target_file_name - ) -> tuple[str, dict]: - """Download the file from the Azure Blob Storage. - - Args: - source (str): The source of the blob. - container (str): The container of the blob. - target_file_name (str): The target file name.""" - - blob = urllib.parse.unquote_plus(source) - - blob_service_client = await self.get_client() - async with blob_service_client: - async with blob_service_client.get_blob_client( - container=container, blob=blob - ) as blob_client: - blob_download = await blob_client.download_blob() - blob_contents = await blob_download.readall() - - blob_properties = await blob_client.get_blob_properties() - - logging.info("Blob Downloaded") - # Get the temporary directory - temp_dir = tempfile.gettempdir() - - # Define the temporary file path - temp_file_path = os.path.join(temp_dir, target_file_name) - - # Write the blob contents to the temporary file - with open(temp_file_path, "wb") as temp_file: - temp_file.write(blob_contents) - - return temp_file_path, blob_properties.metadata From aa0cdfd0623c9e401616e23a604a9b9787a9da93 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Mon, 13 Jan 2025 18:31:38 +0000 Subject: [PATCH 03/64] Update function app --- image_processing/function_app.py | 123 ++++++++++++++++++------------- 1 file changed, 73 insertions(+), 50 deletions(-) diff --git a/image_processing/function_app.py b/image_processing/function_app.py index 8bc9482a..9dfff2f6 100644 --- a/image_processing/function_app.py +++ b/image_processing/function_app.py @@ -5,44 +5,106 @@ import json import asyncio -from adi_2_ai_search import process_adi_2_ai_search +from figure_analysis import FigureAnalysis +from layout_and_figure_merger import LayoutAndFigureMerger +from layout_analysis import process_layout_analysis from image_processing.mark_up_cleaner import process_mark_up_cleaner -from key_phrase_extraction import process_key_phrase_extraction from semantic_text_chunker import process_semantic_text_chunker, SemanticTextChunker logging.basicConfig(level=logging.DEBUG) app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION) -@app.route(route="adi_2_ai_search", methods=[func.HttpMethod.POST]) -async def adi_2_ai_search(req: func.HttpRequest) -> func.HttpResponse: - """Extract the content from a document using ADI.""" - +@app.route(route="layout_analysis", methods=[func.HttpMethod.POST]) +async def layout_analysis(req: func.HttpRequest) -> func.HttpResponse: try: req_body = req.get_json() values = req_body.get("values") adi_config = req.headers - chunk_by_page = adi_config.get("chunk_by_page", "False").lower() == "true" - logging.info(f"Chunk by Page: {chunk_by_page}") + page_wise = adi_config.get("page_wise", "False").lower() == "true" + extract_figures = adi_config.get("extract_figures", "True").lower() == "true" + logging.info(f"Chunk by Page: {page_wise}") except ValueError: return func.HttpResponse( "Please valid Custom Skill Payload in the request body", status_code=400 ) else: - logging.debug("Input Values: %s", values) + logging.info("Input Values: %s", values) record_tasks = [] for value in values: record_tasks.append( asyncio.create_task( - process_adi_2_ai_search(value, chunk_by_page=chunk_by_page) + process_layout_analysis( + value, page_wise=page_wise, extract_figures=extract_figures + ) ) ) results = await asyncio.gather(*record_tasks) - logging.debug("Results: %s", results) + logging.info("Results: %s", results) + + return func.HttpResponse( + json.dumps({"values": results}), + status_code=200, + mimetype="application/json", + ) + + +@app.route(route="figure_analysis", methods=[func.HttpMethod.POST]) +async def main(req: func.HttpRequest) -> func.HttpResponse: + try: + req_body = req.get_json() + values = req_body.get("values") + except ValueError: + return func.HttpResponse( + "Please valid Custom Skill Payload in the request body", status_code=400 + ) + else: + logging.info("Input Values: %s", values) + + record_tasks = [] + + figure_analysis = FigureAnalysis() + + for value in values: + record_tasks.append(asyncio.create_task(figure_analysis.analyse(value))) + + results = await asyncio.gather(*record_tasks) + logging.info("Results: %s", results) + + return func.HttpResponse( + json.dumps({"values": results}), + status_code=200, + mimetype="application/json", + ) + + +@app.route(route="layout_and_figure_merger", methods=[func.HttpMethod.POST]) +async def layout_and_figure_merger(req: func.HttpRequest) -> func.HttpResponse: + try: + req_body = req.get_json() + values = req_body.get("values") + except ValueError: + return func.HttpResponse( + "Please valid Custom Skill Payload in the request body", status_code=400 + ) + else: + logging.info("Input Values: %s", values) + + record_tasks = [] + + layout_and_figure_merger = LayoutAndFigureMerger() + + for value in values: + record_tasks.append( + asyncio.create_task(layout_and_figure_merger.merge(value)) + ) + + results = await asyncio.gather(*record_tasks) + logging.info("Results: %s", results) return func.HttpResponse( json.dumps({"values": results}), @@ -142,42 +204,3 @@ async def semantic_text_chunker(req: func.HttpRequest) -> func.HttpResponse: return func.HttpResponse( json.dump(cleaned_tasks), status_code=200, mimetype="application/json" ) - - -@app.route(route="key_phrase_extractor", methods=[func.HttpMethod.POST]) -async def key_phrase_extractor(req: func.HttpRequest) -> func.HttpResponse: - """HTTP trigger for data cleanup function. - - Args: - req (func.HttpRequest): The HTTP request object. - - Returns: - func.HttpResponse: The HTTP response object.""" - logging.info("Python HTTP trigger data cleanup function processed a request.") - - try: - req_body = req.get_json() - values = req_body.get("values") - logging.info(req_body) - except ValueError: - return func.HttpResponse( - "Please valid Custom Skill Payload in the request body", status_code=400 - ) - else: - logging.debug("Input Values: %s", values) - - record_tasks = [] - - for value in values: - record_tasks.append( - asyncio.create_task(process_key_phrase_extraction(value)) - ) - - results = await asyncio.gather(*record_tasks) - logging.debug("Results: %s", results) - - return func.HttpResponse( - json.dumps({"values": results}), - status_code=200, - mimetype="application/json", - ) From a3d84c02fb918fb0f9a653d56e955f29b3653d52 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Mon, 13 Jan 2025 18:35:24 +0000 Subject: [PATCH 04/64] Update code --- image_processing/.env.example | 11 ++----- image_processing/environment.py | 30 ------------------- .../{ => src/image_processing}/.funcignore | 0 .../image_processing}/figure_analysis.py | 4 +-- .../image_processing}/function_app.py | 0 .../{ => src/image_processing}/host.json | 0 .../image_processing}/layout_analysis.py | 4 +-- .../layout_and_figure_merger.py | 0 .../image_processing}/layout_holders.py | 0 .../image_processing}/local.settings.json | 0 .../image_processing}/mark_up_cleaner.py | 0 .../semantic_text_chunker.py | 0 12 files changed, 6 insertions(+), 43 deletions(-) delete mode 100644 image_processing/environment.py rename image_processing/{ => src/image_processing}/.funcignore (100%) rename image_processing/{ => src/image_processing}/figure_analysis.py (98%) rename image_processing/{ => src/image_processing}/function_app.py (100%) rename image_processing/{ => src/image_processing}/host.json (100%) rename image_processing/{ => src/image_processing}/layout_analysis.py (99%) rename image_processing/{ => src/image_processing}/layout_and_figure_merger.py (100%) rename image_processing/{ => src/image_processing}/layout_holders.py (100%) rename image_processing/{ => src/image_processing}/local.settings.json (100%) rename image_processing/{ => src/image_processing}/mark_up_cleaner.py (100%) rename image_processing/{ => src/image_processing}/semantic_text_chunker.py (100%) diff --git a/image_processing/.env.example b/image_processing/.env.example index eb0ec417..6338146c 100644 --- a/image_processing/.env.example +++ b/image_processing/.env.example @@ -1,12 +1,5 @@ -FunctionApp__ClientId= -IdentityType= # system_assigned or user_assigned or key -OpenAI__ApiKey= OpenAI__Endpoint= -OpenAI__MultiModalDeployment= +OpenAI__CompletionDeployment= OpenAI__ApiVersion= AIService__DocumentIntelligence__Endpoint= -AIService__DocumentIntelligence__Key= -AIService__Language__Endpoint= -AIService__Language__Key= -StorageAccount__Endpoint= -StorageAccount__ConnectionString= +StorageAccount__Name= diff --git a/image_processing/environment.py b/image_processing/environment.py deleted file mode 100644 index 232254ee..00000000 --- a/image_processing/environment.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -import os -from enum import Enum - - -class IdentityType(Enum): - """The type of the indexer""" - - USER_ASSIGNED = "user_assigned" - SYSTEM_ASSIGNED = "system_assigned" - KEY = "key" - - -def get_identity_type() -> IdentityType: - """This function returns the identity type. - - Returns: - IdentityType: The identity type - """ - identity = os.environ.get("IdentityType") - - if identity == "user_assigned": - return IdentityType.USER_ASSIGNED - elif identity == "system_assigned": - return IdentityType.SYSTEM_ASSIGNED - elif identity == "key": - return IdentityType.KEY - else: - raise ValueError("Invalid identity type") diff --git a/image_processing/.funcignore b/image_processing/src/image_processing/.funcignore similarity index 100% rename from image_processing/.funcignore rename to image_processing/src/image_processing/.funcignore diff --git a/image_processing/figure_analysis.py b/image_processing/src/image_processing/figure_analysis.py similarity index 98% rename from image_processing/figure_analysis.py rename to image_processing/src/image_processing/figure_analysis.py index 0a674285..db746187 100644 --- a/image_processing/figure_analysis.py +++ b/image_processing/src/image_processing/figure_analysis.py @@ -35,8 +35,8 @@ async def understand_image_with_gptv(self, figure: FigureHolder) -> dict: """ MAX_TOKENS = 2000 - api_version = os.environ["AZURE_OPENAI_API_VERSION"] - model = os.environ["OPENAI_MAIN_DEPLOYMENT_NAME"] + api_version = os.environ["OpenAI__ApiVersion"] + model = os.environ["OpenAI__CompletionDeployment"] token_provider = get_bearer_token_provider( DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" diff --git a/image_processing/function_app.py b/image_processing/src/image_processing/function_app.py similarity index 100% rename from image_processing/function_app.py rename to image_processing/src/image_processing/function_app.py diff --git a/image_processing/host.json b/image_processing/src/image_processing/host.json similarity index 100% rename from image_processing/host.json rename to image_processing/src/image_processing/host.json diff --git a/image_processing/layout_analysis.py b/image_processing/src/image_processing/layout_analysis.py similarity index 99% rename from image_processing/layout_analysis.py rename to image_processing/src/image_processing/layout_analysis.py index a7c7a645..cf78c561 100644 --- a/image_processing/layout_analysis.py +++ b/image_processing/src/image_processing/layout_analysis.py @@ -34,7 +34,7 @@ class StorageAccountHelper: @property def account_url(self) -> str: """Get the account URL of the Azure Blob Storage.""" - storage_account_name = os.environ.get("DATA_STORAGE_ACCOUNT_NAME") + storage_account_name = os.environ.get("StorageAccount__Name") return f"https://{storage_account_name}.blob.core.windows.net" async def get_client(self): @@ -345,7 +345,7 @@ async def get_document_intelligence_client(self) -> DocumentIntelligenceClient: credential = DefaultAzureCredential() return DocumentIntelligenceClient( - endpoint=os.environ["COGNITIVE_SERVICES_ENDPOINT"], + endpoint=os.environ["AIService__DocumentIntelligence__Endpoint"], credential=credential, ) diff --git a/image_processing/layout_and_figure_merger.py b/image_processing/src/image_processing/layout_and_figure_merger.py similarity index 100% rename from image_processing/layout_and_figure_merger.py rename to image_processing/src/image_processing/layout_and_figure_merger.py diff --git a/image_processing/layout_holders.py b/image_processing/src/image_processing/layout_holders.py similarity index 100% rename from image_processing/layout_holders.py rename to image_processing/src/image_processing/layout_holders.py diff --git a/image_processing/local.settings.json b/image_processing/src/image_processing/local.settings.json similarity index 100% rename from image_processing/local.settings.json rename to image_processing/src/image_processing/local.settings.json diff --git a/image_processing/mark_up_cleaner.py b/image_processing/src/image_processing/mark_up_cleaner.py similarity index 100% rename from image_processing/mark_up_cleaner.py rename to image_processing/src/image_processing/mark_up_cleaner.py diff --git a/image_processing/semantic_text_chunker.py b/image_processing/src/image_processing/semantic_text_chunker.py similarity index 100% rename from image_processing/semantic_text_chunker.py rename to image_processing/src/image_processing/semantic_text_chunker.py From c92037754be4147ae14225229d173b2077114407 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Mon, 13 Jan 2025 18:44:20 +0000 Subject: [PATCH 05/64] Remove entry points --- .../src/image_processing/figure_analysis.py | 31 --------------- .../src/image_processing/layout_analysis.py | 39 ------------------- 2 files changed, 70 deletions(-) diff --git a/image_processing/src/image_processing/figure_analysis.py b/image_processing/src/image_processing/figure_analysis.py index db746187..f91c177b 100644 --- a/image_processing/src/image_processing/figure_analysis.py +++ b/image_processing/src/image_processing/figure_analysis.py @@ -1,12 +1,9 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -import json import logging import os -import azure.functions as func from azure.identity import DefaultAzureCredential, get_bearer_token_provider -import asyncio from openai import ( AsyncAzureOpenAI, OpenAIError, @@ -152,31 +149,3 @@ async def analyse(self, record: dict) -> dict: "errors": None, "warnings": None, } - - -async def main(req: func.HttpRequest) -> func.HttpResponse: - try: - req_body = req.get_json() - values = req_body.get("values") - except ValueError: - return func.HttpResponse( - "Please valid Custom Skill Payload in the request body", status_code=400 - ) - else: - logging.info("Input Values: %s", values) - - record_tasks = [] - - figure_analysis = FigureAnalysis() - - for value in values: - record_tasks.append(asyncio.create_task(figure_analysis.analyse(value))) - - results = await asyncio.gather(*record_tasks) - logging.info("Results: %s", results) - - return func.HttpResponse( - json.dumps({"values": results}), - status_code=200, - mimetype="application/json", - ) diff --git a/image_processing/src/image_processing/layout_analysis.py b/image_processing/src/image_processing/layout_analysis.py index cf78c561..a1f70386 100644 --- a/image_processing/src/image_processing/layout_analysis.py +++ b/image_processing/src/image_processing/layout_analysis.py @@ -2,11 +2,9 @@ # Licensed under the MIT License. # This code originates from: https://github.com/microsoft/dstoolkit-text2sql-and-imageprocessing -import json import logging import os import urllib -import azure.functions as func import tempfile from azure.storage.blob.aio import BlobServiceClient from azure.identity import DefaultAzureCredential @@ -546,40 +544,3 @@ async def process_layout_analysis( ], "warnings": None, } - - -async def main(req: func.HttpRequest) -> func.HttpResponse: - try: - req_body = req.get_json() - values = req_body.get("values") - adi_config = req.headers - - page_wise = adi_config.get("page_wise", "False").lower() == "true" - extract_figures = adi_config.get("extract_figures", "True").lower() == "true" - logging.info(f"Chunk by Page: {page_wise}") - except ValueError: - return func.HttpResponse( - "Please valid Custom Skill Payload in the request body", status_code=400 - ) - else: - logging.info("Input Values: %s", values) - - record_tasks = [] - - for value in values: - record_tasks.append( - asyncio.create_task( - process_layout_analysis( - value, page_wise=page_wise, extract_figures=extract_figures - ) - ) - ) - - results = await asyncio.gather(*record_tasks) - logging.info("Results: %s", results) - - return func.HttpResponse( - json.dumps({"values": results}), - status_code=200, - mimetype="application/json", - ) From f0912adcc7dbb8fec2cf128c6c68d2bd40b489e6 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Mon, 13 Jan 2025 18:50:33 +0000 Subject: [PATCH 06/64] Update cleaner --- .../src/image_processing/layout_holders.py | 2 +- .../src/image_processing/mark_down_cleaner.py | 157 ++++++++++++++++++ .../src/image_processing/mark_up_cleaner.py | 149 ----------------- 3 files changed, 158 insertions(+), 150 deletions(-) create mode 100644 image_processing/src/image_processing/mark_down_cleaner.py delete mode 100644 image_processing/src/image_processing/mark_up_cleaner.py diff --git a/image_processing/src/image_processing/layout_holders.py b/image_processing/src/image_processing/layout_holders.py index 9388c8ba..838c7b3b 100644 --- a/image_processing/src/image_processing/layout_holders.py +++ b/image_processing/src/image_processing/layout_holders.py @@ -27,7 +27,7 @@ def markdown(self) -> str: -------- str: The Markdown string representation of the figure.""" - return f"
{self.description}
" + return f"
{self.description}
" class LayoutHolder(BaseModel): diff --git a/image_processing/src/image_processing/mark_down_cleaner.py b/image_processing/src/image_processing/mark_down_cleaner.py new file mode 100644 index 00000000..048ed7f0 --- /dev/null +++ b/image_processing/src/image_processing/mark_down_cleaner.py @@ -0,0 +1,157 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +import logging +import json +import regex as re + + +class MarkDownCleaner: + def get_sections(self, text: str) -> list: + """ + Returns the section details from the content. + + Args: + text: The input text + + Returns: + list: The sections related to text + """ + # Updated regex pattern to capture markdown headers like ### Header + combined_pattern = r"(?<=\n|^)[#]+\s*(.*?)(?=\n)" + doc_metadata = re.findall(combined_pattern, text, re.DOTALL) + return self.clean_sections(doc_metadata) + + def clean_sections(self, sections: list) -> list: + """ + Cleans the sections by removing special characters and extra white spaces. + """ + cleaned_sections = [re.sub(r"[=#]", "", match).strip() for match in sections] + return cleaned_sections + + def get_figures(self, text: str) -> list: + # Regex pattern to extract FigureIds + pattern = r"FigureId='([^']+)'" + + # Extract FigureIds using findall + figure_ids = re.findall(pattern, text) + + return figure_ids + + def remove_markdown_tags(self, text: str, tag_patterns: dict) -> str: + """ + Remove specified Markdown tags from the text, keeping the contents of the tags. + + Args: + text: The input text containing Markdown tags. + tag_patterns: A dictionary where keys are tags and values are their specific patterns. + + Returns: + str: The text with specified tags removed. + """ + try: + for tag, pattern in tag_patterns.items(): + try: + # Replace the tags using the specific pattern, keeping the content inside the tags + if tag == "header": + text = re.sub( + pattern, r"\2", text, flags=re.DOTALL | re.MULTILINE + ) + else: + text = re.sub(pattern, r"\1", text, flags=re.DOTALL) + except re.error as e: + logging.error(f"Regex error for tag '{tag}': {e}") + except Exception as e: + logging.error(f"An error occurred in remove_markdown_tags: {e}") + return text + + def clean_text_and_extract_metadata(self, src_text: str) -> tuple[str, str]: + """This function performs following cleanup activities on the text, remove all unicode characters + remove line spacing,remove stop words, normalize characters + + Args: + src_text (str): The text to cleanup. + + Returns: + str: The clean text.""" + + return_record = {} + + try: + logging.info(f"Input text: {src_text}") + if len(src_text) == 0: + logging.error("Input text is empty") + raise ValueError("Input text is empty") + + return_record["marked_up_chunk"] = src_text + return_record["sections"] = self.get_sections(src_text) + + logging.info(f"Sections: {return_record['sections']}") + + # Define specific patterns for each tag + tag_patterns = { + "figurecontent": r"", + "figure": r"(.*?)", + "figures": r"\(figures/\d+\)(.*?)\(figures/\d+\)", + "figcaption": r"
(.*?)
", + "header": r"^\s*(#{1,6})\s*(.*?)\s*$", + } + cleaned_text = self.remove_markdown_tags(src_text, tag_patterns) + + logging.info(f"Removed markdown tags: {cleaned_text}") + + # Updated regex to keep Unicode letters, punctuation, whitespace, currency symbols, and percentage signs, + # while also removing non-printable characters + cleaned_text = re.sub(r"[^\p{L}\p{P}\s\p{Sc}%\x20-\x7E]", "", cleaned_text) + + logging.info(f"Cleaned text: {cleaned_text}") + if len(cleaned_text) == 0: + logging.error("Cleaned text is empty") + raise ValueError("Cleaned text is empty") + else: + return_record["cleaned_chunk"] = cleaned_text + except Exception as e: + logging.error(f"An error occurred in clean_text_and_extract_metadata: {e}") + return "" + return return_record + + async def process_mark_up_cleaner(self, record: dict) -> dict: + """Cleanup the data using standard python libraries. + + Args: + record (dict): The record to cleanup. + + Returns: + dict: The clean record.""" + + try: + json_str = json.dumps(record, indent=4) + + logging.info(f"embedding cleaner Input: {json_str}") + + cleaned_record = { + "recordId": record["recordId"], + "data": {}, + "errors": None, + "warnings": None, + } + + cleaned_record["data"] = self.clean_text_and_extract_metadata( + record["data"]["chunk"] + ) + + except Exception as e: + logging.error("string cleanup Error: %s", e) + return { + "recordId": record["recordId"], + "data": {}, + "errors": [ + { + "message": "Failed to cleanup data. Check function app logs for more details of exact failure." + } + ], + "warnings": None, + } + json_str = json.dumps(cleaned_record, indent=4) + + logging.info(f"embedding cleaner output: {json_str}") + return cleaned_record diff --git a/image_processing/src/image_processing/mark_up_cleaner.py b/image_processing/src/image_processing/mark_up_cleaner.py deleted file mode 100644 index 3871644d..00000000 --- a/image_processing/src/image_processing/mark_up_cleaner.py +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -import logging -import json -import regex as re - - -def get_sections(text: str) -> list: - """ - Returns the section details from the content. - - Args: - text: The input text - - Returns: - list: The sections related to text - """ - # Updated regex pattern to capture markdown headers like ### Header - combined_pattern = r"(?<=\n|^)[#]+\s*(.*?)(?=\n)" - doc_metadata = re.findall(combined_pattern, text, re.DOTALL) - return clean_sections(doc_metadata) - - -def clean_sections(sections: list) -> list: - """ - Cleans the sections by removing special characters and extra white spaces. - """ - cleaned_sections = [re.sub(r"[=#]", "", match).strip() for match in sections] - return cleaned_sections - - -def remove_markdown_tags(text: str, tag_patterns: dict) -> str: - """ - Remove specified Markdown tags from the text, keeping the contents of the tags. - - Args: - text: The input text containing Markdown tags. - tag_patterns: A dictionary where keys are tags and values are their specific patterns. - - Returns: - str: The text with specified tags removed. - """ - try: - for tag, pattern in tag_patterns.items(): - try: - # Replace the tags using the specific pattern, keeping the content inside the tags - if tag == "header": - text = re.sub(pattern, r"\2", text, flags=re.DOTALL | re.MULTILINE) - else: - text = re.sub(pattern, r"\1", text, flags=re.DOTALL) - except re.error as e: - logging.error(f"Regex error for tag '{tag}': {e}") - except Exception as e: - logging.error(f"An error occurred in remove_markdown_tags: {e}") - return text - - -def clean_text_and_extract_metadata(src_text: str) -> tuple[str, str]: - """This function performs following cleanup activities on the text, remove all unicode characters - remove line spacing,remove stop words, normalize characters - - Args: - src_text (str): The text to cleanup. - - Returns: - str: The clean text.""" - - return_record = {} - - try: - logging.info(f"Input text: {src_text}") - if len(src_text) == 0: - logging.error("Input text is empty") - raise ValueError("Input text is empty") - - return_record["marked_up_chunk"] = src_text - return_record["sections"] = get_sections(src_text) - - logging.info(f"Sections: {return_record['sections']}") - - # Define specific patterns for each tag - tag_patterns = { - "figurecontent": r"", - "figure": r"(.*?)", - "figures": r"\(figures/\d+\)(.*?)\(figures/\d+\)", - "figcaption": r"
(.*?)
", - "header": r"^\s*(#{1,6})\s*(.*?)\s*$", - } - cleaned_text = remove_markdown_tags(src_text, tag_patterns) - - logging.info(f"Removed markdown tags: {cleaned_text}") - - # Updated regex to keep Unicode letters, punctuation, whitespace, currency symbols, and percentage signs, - # while also removing non-printable characters - cleaned_text = re.sub(r"[^\p{L}\p{P}\s\p{Sc}%\x20-\x7E]", "", cleaned_text) - - logging.info(f"Cleaned text: {cleaned_text}") - if len(cleaned_text) == 0: - logging.error("Cleaned text is empty") - raise ValueError("Cleaned text is empty") - else: - return_record["cleaned_chunk"] = cleaned_text - except Exception as e: - logging.error(f"An error occurred in clean_text_and_extract_metadata: {e}") - return "" - return return_record - - -async def process_mark_up_cleaner(record: dict) -> dict: - """Cleanup the data using standard python libraries. - - Args: - record (dict): The record to cleanup. - - Returns: - dict: The clean record.""" - - try: - json_str = json.dumps(record, indent=4) - - logging.info(f"embedding cleaner Input: {json_str}") - - cleaned_record = { - "recordId": record["recordId"], - "data": {}, - "errors": None, - "warnings": None, - } - - cleaned_record["data"] = clean_text_and_extract_metadata( - record["data"]["chunk"] - ) - - except Exception as e: - logging.error("string cleanup Error: %s", e) - return { - "recordId": record["recordId"], - "data": {}, - "errors": [ - { - "message": "Failed to cleanup data. Check function app logs for more details of exact failure." - } - ], - "warnings": None, - } - json_str = json.dumps(cleaned_record, indent=4) - - logging.info(f"embedding cleaner output: {json_str}") - return cleaned_record From 02f0bbaa2d804bf129585b32e4e3576748a04c3e Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Mon, 13 Jan 2025 18:56:07 +0000 Subject: [PATCH 07/64] Update local settings --- .../src/image_processing/local.settings.json | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/image_processing/src/image_processing/local.settings.json b/image_processing/src/image_processing/local.settings.json index 7bac6ecb..0c7e1812 100644 --- a/image_processing/src/image_processing/local.settings.json +++ b/image_processing/src/image_processing/local.settings.json @@ -2,16 +2,10 @@ "IsEncrypted": false, "Values": { "AIService__DocumentIntelligence__Endpoint": "", - "AIService__DocumentIntelligence__Key": "", - "AIService__Language__Endpoint": "", - "AIService__Language__Key": "", - "FunctionApp__ClientId": "", - "IdentityType": " # system_assigned or user_assigned or key", "OpenAI__ApiKey": "", "OpenAI__ApiVersion": "", + "OpenAI__CompletionDeployment": "", "OpenAI__Endpoint": "", - "OpenAI__MultiModalDeployment": "", - "StorageAccount__ConnectionString": "", - "StorageAccount__Endpoint": "" + "StorageAccount__Name": "" } } From 127d1616d0102f3bfa4fadb33e391b6b70e7cc97 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Tue, 14 Jan 2025 16:29:30 +0000 Subject: [PATCH 08/64] Update readme --- README.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0e0622fc..f872d60b 100644 --- a/README.md +++ b/README.md @@ -16,13 +16,9 @@ It is intended that the plugins and skills provided in this repository, are adap The above components have been successfully used on production RAG projects to increase the quality of responses. -_The code provided in this repo is a sample of the implementation and should be adjusted before being used in production._ - -## High Level Implementation - -The following diagram shows a workflow for how the Text2SQL and AI Search plugin would be incorporated into a RAG application. Using the plugins available, alongside the Function Calling capabilities of LLMs, the LLM can do Chain of Thought reasoning to determine the steps needed to answer the question. This allows the LLM to recognise intent and therefore pick appropriate data sources based on the intent of the question, or a combination of both. - -![High level workflow for a plugin driven RAG application](./images/Plugin%20Based%20RAG%20Flow.png "High Level Workflow") +> [!WARNING] +> +> - The code provided in this repo is a accelerator of the implementation and should be review / adjusted before being used in production. ## Contributing From 77c4094bee573130d16203c7fec6bd45e9e37ee4 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Tue, 14 Jan 2025 19:04:38 +0000 Subject: [PATCH 09/64] Update rag documents --- .../src/deploy_ai_search/rag_documents.py | 47 +++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/deploy_ai_search/src/deploy_ai_search/rag_documents.py b/deploy_ai_search/src/deploy_ai_search/rag_documents.py index 7d638562..1ab65110 100644 --- a/deploy_ai_search/src/deploy_ai_search/rag_documents.py +++ b/deploy_ai_search/src/deploy_ai_search/rag_documents.py @@ -107,11 +107,50 @@ def get_index_fields(self) -> list[SearchableField]: collection=True, searchable=False, ), - SearchableField( - name="FigureUri", + SimpleField( + name="Container", type=SearchFieldDataType.String, - collection=True, - searchable=False, + filterable=True, + ), + SimpleField( + name="ImageBlob", + type=SearchFieldDataType.String, + filterable=True, + ), + SimpleField( + name="Caption", + type=SearchFieldDataType.String, + filterable=True, + ), + SimpleField( + name="Offset", + type=SearchFieldDataType.Int64, + filterable=True, + ), + SimpleField( + name="Length", + type=SearchFieldDataType.Int64, + filterable=True, + ), + SimpleField( + name="PageNumber", + type=SearchFieldDataType.Int64, + filterable=True, + ), + SimpleField( + name="Uri", + type=SearchFieldDataType.String, + filterable=True, + ), + SimpleField( + name="Description", + type=SearchFieldDataType.String, + filterable=True, + ), + SimpleField( + name="Data", + type=SearchFieldDataType.String, + filterable=True, ), ], ), From b3e3c040d82993693a728c14dcfb8d7607f5ce0a Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Tue, 14 Jan 2025 19:18:17 +0000 Subject: [PATCH 10/64] Update layout holders --- .../src/image_processing/layout_holders.py | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/image_processing/src/image_processing/layout_holders.py b/image_processing/src/image_processing/layout_holders.py index 838c7b3b..dc4b7bf3 100644 --- a/image_processing/src/image_processing/layout_holders.py +++ b/image_processing/src/image_processing/layout_holders.py @@ -6,18 +6,19 @@ class FigureHolder(BaseModel): + """A class to hold the figure extracted from the document.""" - figure_id: str - container: str - image_blob: str - caption: Optional[str] = Field(default=None) - offset: int - length: int - page_number: Optional[int] = Field(default=None) - uri: str - description: Optional[str] = Field(default="") - data: Optional[str] = Field(default=None) + figure_id: str = Field(alias="FigureId") + container: str = Field(default="Container") + image_blob: str = Field(default="ImageBlob") + caption: Optional[str] = Field(default=None, alias="Caption") + offset: int = Field(alias="Offset") + length: int = Field(alias="Length") + page_number: Optional[int] = Field(default=None, alias="PageNumber") + uri: str = Field(alias="Uri") + description: Optional[str] = Field(default="", alias="Description") + data: Optional[str] = Field(default=None, alias="Data") @property def markdown(self) -> str: From 8e6b61d00bf3a60256a1f4eafb083c5744e5fd59 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Tue, 14 Jan 2025 19:37:56 +0000 Subject: [PATCH 11/64] Update ai search --- .../src/deploy_ai_search/ai_search.py | 177 +++++++++++------- .../src/deploy_ai_search/rag_documents.py | 33 +--- .../src/image_processing/layout_analysis.py | 8 +- .../src/image_processing/layout_holders.py | 20 +- ...ark_down_cleaner.py => mark_up_cleaner.py} | 0 5 files changed, 130 insertions(+), 108 deletions(-) rename image_processing/src/image_processing/{mark_down_cleaner.py => mark_up_cleaner.py} (100%) diff --git a/deploy_ai_search/src/deploy_ai_search/ai_search.py b/deploy_ai_search/src/deploy_ai_search/ai_search.py index 3da8f43b..e82575b3 100644 --- a/deploy_ai_search/src/deploy_ai_search/ai_search.py +++ b/deploy_ai_search/src/deploy_ai_search/ai_search.py @@ -322,8 +322,10 @@ def get_text_split_skill( return semantic_text_chunker_skill - def get_adi_skill(self, chunk_by_page=False) -> WebApiSkill: - """Get the custom skill for adi. + def get_layout_analysis_skill( + self, chunk_by_page=False, extract_figures=True + ) -> WebApiSkill: + """Get the custom skill for layout analysis. Args: ----- @@ -343,25 +345,24 @@ def get_adi_skill(self, chunk_by_page=False) -> WebApiSkill: if chunk_by_page: output = [ - OutputFieldMappingEntry(name="extracted_content", target_name="chunks") + OutputFieldMappingEntry(name="layout", target_name="page_wise_layout") ] else: - output = [ - OutputFieldMappingEntry( - name="extracted_content", target_name="extracted_content" - ) - ] + output = [OutputFieldMappingEntry(name="layout", target_name="layout")] - adi_skill = WebApiSkill( - name="ADI Skill", + layout_analysis_skill = WebApiSkill( + name="Layout Analysis Skill", description="Skill to generate ADI", context="/document", - uri=self.environment.get_custom_skill_function_url("adi"), + uri=self.environment.get_custom_skill_function_url("layout_analysis"), timeout="PT230S", batch_size=batch_size, degree_of_parallelism=degree_of_parallelism, http_method="POST", - http_headers={"chunk_by_page": chunk_by_page}, + http_headers={ + "chunk_by_page": chunk_by_page, + "extract_figures": extract_figures, + }, inputs=[ InputFieldMappingEntry( name="source", source="/document/metadata_storage_path" @@ -371,100 +372,150 @@ def get_adi_skill(self, chunk_by_page=False) -> WebApiSkill: ) if self.environment.identity_type != IdentityType.KEY: - adi_skill.auth_identity = ( + layout_analysis_skill.auth_identity = ( self.environment.function_app_app_registration_resource_id ) if self.environment.identity_type == IdentityType.USER_ASSIGNED: - adi_skill.auth_identity = self.environment.ai_search_user_assigned_identity + layout_analysis_skill.auth_identity = ( + self.environment.ai_search_user_assigned_identity + ) - return adi_skill + return layout_analysis_skill - def get_vector_skill( - self, context, source, target_name="vector" - ) -> AzureOpenAIEmbeddingSkill: - """Get the vector skill for the indexer. + def get_figure_analysis_skill(self, figure_source) -> WebApiSkill: + """Get the custom skill for figure analysis. + + Args: + ----- + chunk_by_page (bool, optional): Whether to chunk by page. Defaults to False. Returns: - AzureOpenAIEmbeddingSkill: The vector skill for the indexer""" + -------- + WebApiSkill: The custom skill for adi""" - embedding_skill_inputs = [ - InputFieldMappingEntry(name="text", source=source), - ] - embedding_skill_outputs = [ - OutputFieldMappingEntry(name="embedding", target_name=target_name) + if self.test: + batch_size = 1 + degree_of_parallelism = 4 + else: + # Depending on your GPT Token limit, you may need to adjust the batch size and degree of parallelism + batch_size = 1 + degree_of_parallelism = 8 + + output = [ + OutputFieldMappingEntry(name="updated_figure", target_name="updated_figure") ] - vector_skill = AzureOpenAIEmbeddingSkill( - name="Vector Skill", - description="Skill to generate embeddings", - context=context, - deployment_name=self.environment.open_ai_embedding_deployment, - model_name=self.environment.open_ai_embedding_model, - resource_url=self.environment.open_ai_endpoint, - inputs=embedding_skill_inputs, - outputs=embedding_skill_outputs, - dimensions=self.environment.open_ai_embedding_dimensions, + figure_analysis_skill = WebApiSkill( + name="Figure Analysis Skill", + description="Skill to generate figure analysis", + context=figure_source, + uri=self.environment.get_custom_skill_function_url("figure_analysis"), + timeout="PT230S", + batch_size=batch_size, + degree_of_parallelism=degree_of_parallelism, + http_method="POST", + inputs=[InputFieldMappingEntry(name="figure", source=figure_source)], + outputs=output, ) - if self.environment.identity_type == IdentityType.KEY: - vector_skill.api_key = self.environment.open_ai_api_key - elif self.environment.identity_type == IdentityType.USER_ASSIGNED: - vector_skill.auth_identity = ( + if self.environment.identity_type != IdentityType.KEY: + figure_analysis_skill.auth_identity = ( + self.environment.function_app_app_registration_resource_id + ) + + if self.environment.identity_type == IdentityType.USER_ASSIGNED: + figure_analysis_skill.auth_identity = ( self.environment.ai_search_user_assigned_identity ) - return vector_skill + return figure_analysis_skill - def get_key_phrase_extraction_skill(self, context, source) -> WebApiSkill: - """Get the key phrase extraction skill. + def get_layout_and_figure_merger_skill(self, figure_source) -> WebApiSkill: + """Get the custom skill for layout and figure merger. Args: ----- - context (str): The context of the skill - source (str): The source of the skill + chunk_by_page (bool, optional): Whether to chunk by page. Defaults to False. Returns: -------- - WebApiSkill: The key phrase extraction skill""" + WebApiSkill: The custom skill for adi""" if self.test: - batch_size = 4 + batch_size = 1 degree_of_parallelism = 4 else: - batch_size = 16 - degree_of_parallelism = 16 + # Depending on your GPT Token limit, you may need to adjust the batch size and degree of parallelism + batch_size = 1 + degree_of_parallelism = 8 - key_phrase_extraction_skill_inputs = [ - InputFieldMappingEntry(name="text", source=source), - ] - key_phrase_extraction__skill_outputs = [ - OutputFieldMappingEntry(name="key_phrases", target_name="keywords") + output = [ + OutputFieldMappingEntry(name="updated_figure", target_name="updated_figure") ] - key_phrase_extraction_skill = WebApiSkill( - name="Key phrase extraction API", - description="Skill to extract keyphrases", - context=context, - uri=self.environment.get_custom_skill_function_url("key_phrase_extraction"), + + figure_analysis_skill = WebApiSkill( + name="Layout and Figure Merger Skill", + description="Skill to merge layout and figure analysis", + context=figure_source, + uri=self.environment.get_custom_skill_function_url( + "layout_and_figure_merger" + ), timeout="PT230S", batch_size=batch_size, degree_of_parallelism=degree_of_parallelism, http_method="POST", - inputs=key_phrase_extraction_skill_inputs, - outputs=key_phrase_extraction__skill_outputs, + inputs=[InputFieldMappingEntry(name="figure", source=figure_source)], + outputs=output, ) if self.environment.identity_type != IdentityType.KEY: - key_phrase_extraction_skill.auth_identity = ( + figure_analysis_skill.auth_identity = ( self.environment.function_app_app_registration_resource_id ) if self.environment.identity_type == IdentityType.USER_ASSIGNED: - key_phrase_extraction_skill.auth_identity = ( + figure_analysis_skill.auth_identity = ( + self.environment.ai_search_user_assigned_identity + ) + + return figure_analysis_skill + + def get_vector_skill( + self, context, source, target_name="vector" + ) -> AzureOpenAIEmbeddingSkill: + """Get the vector skill for the indexer. + + Returns: + AzureOpenAIEmbeddingSkill: The vector skill for the indexer""" + + embedding_skill_inputs = [ + InputFieldMappingEntry(name="text", source=source), + ] + embedding_skill_outputs = [ + OutputFieldMappingEntry(name="embedding", target_name=target_name) + ] + + vector_skill = AzureOpenAIEmbeddingSkill( + name="Vector Skill", + description="Skill to generate embeddings", + context=context, + deployment_name=self.environment.open_ai_embedding_deployment, + model_name=self.environment.open_ai_embedding_model, + resource_url=self.environment.open_ai_endpoint, + inputs=embedding_skill_inputs, + outputs=embedding_skill_outputs, + dimensions=self.environment.open_ai_embedding_dimensions, + ) + + if self.environment.identity_type == IdentityType.KEY: + vector_skill.api_key = self.environment.open_ai_api_key + elif self.environment.identity_type == IdentityType.USER_ASSIGNED: + vector_skill.auth_identity = ( self.environment.ai_search_user_assigned_identity ) - return key_phrase_extraction_skill + return vector_skill def get_vector_search(self) -> VectorSearch: """Get the vector search configuration for compass. diff --git a/deploy_ai_search/src/deploy_ai_search/rag_documents.py b/deploy_ai_search/src/deploy_ai_search/rag_documents.py index 1ab65110..ef6910b5 100644 --- a/deploy_ai_search/src/deploy_ai_search/rag_documents.py +++ b/deploy_ai_search/src/deploy_ai_search/rag_documents.py @@ -98,7 +98,7 @@ def get_index_fields(self) -> list[SearchableField]: facetable=True, ), ComplexField( - name="Figures", + name="ChunkFigures", collection=True, fields=[ SearchableField( @@ -107,31 +107,11 @@ def get_index_fields(self) -> list[SearchableField]: collection=True, searchable=False, ), - SimpleField( - name="Container", - type=SearchFieldDataType.String, - filterable=True, - ), - SimpleField( - name="ImageBlob", - type=SearchFieldDataType.String, - filterable=True, - ), SimpleField( name="Caption", type=SearchFieldDataType.String, filterable=True, ), - SimpleField( - name="Offset", - type=SearchFieldDataType.Int64, - filterable=True, - ), - SimpleField( - name="Length", - type=SearchFieldDataType.Int64, - filterable=True, - ), SimpleField( name="PageNumber", type=SearchFieldDataType.Int64, @@ -258,16 +238,7 @@ def get_index_projections(self) -> SearchIndexerIndexProjection: ), InputFieldMappingEntry( name="Figures", - source_context="/document/chunks/*/figures/*", - inputs=[ - InputFieldMappingEntry( - name="FigureId", source="/document/chunks/*/figures/*/figure_id" - ), - InputFieldMappingEntry( - name="FigureUri", - source="/document/chunks/*/figures/*/figure_uri", - ), - ], + source_context="/document/chunks/*/chunk_figures/*", ), InputFieldMappingEntry( name="DateLastModified", source="/document/DateLastModified" diff --git a/image_processing/src/image_processing/layout_analysis.py b/image_processing/src/image_processing/layout_analysis.py index a1f70386..c959bd0a 100644 --- a/image_processing/src/image_processing/layout_analysis.py +++ b/image_processing/src/image_processing/layout_analysis.py @@ -247,7 +247,7 @@ async def process_figures_from_extracted_content( ) ) - image_blob = f"{self.blob}/{figure.id}.png" + blob = f"{self.blob}/{figure.id}.png" caption = ( figure.caption.content if figure.caption is not None else None @@ -257,7 +257,7 @@ async def process_figures_from_extracted_content( uri = "{}/{}/{}".format( storage_account_helper.account_url, self.images_container, - image_blob, + blob, ) offset = figure.spans[0].offset - text_holder.page_offsets @@ -265,7 +265,7 @@ async def process_figures_from_extracted_content( image_processing_data = FigureHolder( figure_id=figure.id, container=self.images_container, - image_blob=image_blob, + blob=blob, caption=caption, offset=offset, length=figure.spans[0].length, @@ -293,7 +293,7 @@ async def process_figures_from_extracted_content( figure_upload_tasks.append( storage_account_helper.upload_blob( figure_processing_data.container, - figure_processing_data.image_blob, + figure_processing_data.blob, image_data, "image/png", ) diff --git a/image_processing/src/image_processing/layout_holders.py b/image_processing/src/image_processing/layout_holders.py index dc4b7bf3..6b8e5b7f 100644 --- a/image_processing/src/image_processing/layout_holders.py +++ b/image_processing/src/image_processing/layout_holders.py @@ -9,16 +9,16 @@ class FigureHolder(BaseModel): """A class to hold the figure extracted from the document.""" - figure_id: str = Field(alias="FigureId") - container: str = Field(default="Container") - image_blob: str = Field(default="ImageBlob") - caption: Optional[str] = Field(default=None, alias="Caption") - offset: int = Field(alias="Offset") - length: int = Field(alias="Length") - page_number: Optional[int] = Field(default=None, alias="PageNumber") - uri: str = Field(alias="Uri") - description: Optional[str] = Field(default="", alias="Description") - data: Optional[str] = Field(default=None, alias="Data") + figure_id: str + container: str = Field(exclude=True) + blob: str = Field(exclude=True) + caption: Optional[str] = Field(default=None) + offset: int + length: int + page_number: Optional[int] = Field(default=None) + uri: str + description: Optional[str] = Field(default="") + data: Optional[str] = Field(default=None) @property def markdown(self) -> str: diff --git a/image_processing/src/image_processing/mark_down_cleaner.py b/image_processing/src/image_processing/mark_up_cleaner.py similarity index 100% rename from image_processing/src/image_processing/mark_down_cleaner.py rename to image_processing/src/image_processing/mark_up_cleaner.py From 0b9370fa5ebc0f29d251b45d6c4708cf52ded975 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Thu, 16 Jan 2025 18:47:18 +0000 Subject: [PATCH 12/64] Update image processing work --- image_processing/.env.example | 2 +- image_processing/README.md | 6 +- .../src/image_processing/figure_analysis.py | 144 ++++++++++++++---- .../src/image_processing/layout_analysis.py | 40 +++-- 4 files changed, 145 insertions(+), 47 deletions(-) diff --git a/image_processing/.env.example b/image_processing/.env.example index 6338146c..a51185d3 100644 --- a/image_processing/.env.example +++ b/image_processing/.env.example @@ -1,5 +1,5 @@ OpenAI__Endpoint= -OpenAI__CompletionDeployment= +OpenAI__MiniCompletionDeployment= OpenAI__ApiVersion= AIService__DocumentIntelligence__Endpoint= StorageAccount__Name= diff --git a/image_processing/README.md b/image_processing/README.md index 9b43e508..8b8e36a1 100644 --- a/image_processing/README.md +++ b/image_processing/README.md @@ -1,6 +1,6 @@ # AI Search Indexing with Azure Document Intelligence -This portion of the repo contains code for linking Azure Document Intelligence with AI Search to process complex documents with charts and images, and uses multi-modal models (gpt4o) to interpret and understand these. +This portion of the repo contains code for linking Azure Document Intelligence with AI Search to process complex documents with charts and images, and uses multi-modal models (gpt-4o-mini) to interpret and understand these. The implementation in Python, although it can easily be adapted for C# or another language. The code is designed to run in an Azure Function App inside the tenant. @@ -22,7 +22,7 @@ Instead of using OCR to extract the contents of the document, ADIv4 is used to a Once the Markdown is obtained, several steps are carried out: -1. **Extraction of images / charts**. The figures identified are extracted from the original document and passed to a multi-modal model (gpt4o in this case) for analysis. We obtain a description and summary of the chart / image to infer the meaning of the figure. This allows us to index and perform RAG analysis the information that is visually obtainable from a chart, without it being explicitly mentioned in the text surrounding. The information is added back into the original chart. +1. **Extraction of images / charts**. The figures identified are extracted from the original document and passed to a multi-modal model (gpt-4o-mini in this case) for analysis. We obtain a description and summary of the chart / image to infer the meaning of the figure. This allows us to index and perform RAG analysis the information that is visually obtainable from a chart, without it being explicitly mentioned in the text surrounding. The information is added back into the original chart. 2. **Chunking**. The obtained content is chunked accordingly depending on the chunking strategy. This function app supports two chunking methods, **page wise** and **semantic chunking**. The page wise chunking is performed natively by Azure Document Intelligence. For a Semantic Chunking, we include a customer chunker that splits the text with the following strategy: @@ -82,7 +82,7 @@ You can then test the chunking by sending a AI Search JSON format to the `/seman ### Deployment Steps 1. Update `.env` file with the associated values. Not all values are required dependent on whether you are using System / User Assigned Identities or a Key based authentication. Use this template to update the environment variables in the function app. -2. Make sure the infra and required identities are setup. This setup requires Azure Document Intelligence and GPT4o. +2. Make sure the infra and required identities are setup. This setup requires Azure Document Intelligence and gpt-4o-mini. 3. [Deploy your function app](https://learn.microsoft.com/en-us/azure/azure-functions/functions-deployment-technologies?tabs=windows) and test with a HTTP request. ### Code Files diff --git a/image_processing/src/image_processing/figure_analysis.py b/image_processing/src/image_processing/figure_analysis.py index f91c177b..0e324cbd 100644 --- a/image_processing/src/image_processing/figure_analysis.py +++ b/image_processing/src/image_processing/figure_analysis.py @@ -10,12 +10,35 @@ APIError, APIStatusError, BadRequestError, + RateLimitError, ) -from tenacity import retry, stop_after_attempt, wait_exponential +from tenacity import retry, stop_after_attempt, wait_exponential, RetryError from layout_holders import FigureHolder +from PIL import Image +import io +import base64 class FigureAnalysis: + def get_image_size(self, figure: FigureHolder) -> tuple[int, int]: + """Get the size of the image from the binary data. + + Parameters: + - figure (FigureHolder): The figure object containing the image data. + + Returns: + - width (int): The width of the image. + - height (int): The height of the image.""" + # Create a BytesIO object from the binary data + image_data = base64.b64decode(figure.data) + image_stream = io.BytesIO(image_data) + + # Open the image using PIL + with Image.open(image_stream) as img: + # Get the size of the image + width, height = img.size + return width, height + @retry( stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=1, max=10) ) @@ -31,45 +54,86 @@ async def understand_image_with_gptv(self, figure: FigureHolder) -> dict: - img_description (str): The generated description for the image. """ + # Open figure and check if below minimum size + width, height = self.get_image_size(figure) + + if width < 75 and height < 75: + logging.info( + "Image is too small to be analysed. Width: %i, Height: %i", + width, + height, + ) + figure.description = "Irrelevant Image" + + return figure + MAX_TOKENS = 2000 api_version = os.environ["OpenAI__ApiVersion"] - model = os.environ["OpenAI__CompletionDeployment"] + model_name = "gpt-4o-mini" + deployment_id = os.environ["OpenAI__MiniCompletionDeployment"] + azure_endpoint = os.environ["OpenAI__Endpoint"] token_provider = get_bearer_token_provider( DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default" ) - system_prompt = """You are an expert in technical image analysis. Your task is to provided analysis of images. You should FOCUS on what info can be inferred from the image and the meaning of the data inside the image. Draw actionable insights and conclusions from the image. Do not describe the image in a general way or describe the image in a way that is not useful for decision-making. + system_prompt = """You are an expert in technical image description and analysis for search and retrieval. Your task is to describe the key details, themes, and practical applications of the image, focusing on how the image could be used and what it helps the user achieve. Additionally, provide a brief explanation of what can be inferred from the image, such as trends, relationships, or insights. + + It is essential to include all visible labels, data points, and annotations in your description. Use natural terms and phrases that users might search for to locate the image. + + Charts and Graphs: + - Identify the type of chart and describe the data points, trends, and labels present. + - Explain how the chart can be used (e.g., for analyzing trends, tracking performance, or comparing metrics). + - Describe what can be inferred, such as patterns over time, correlations, or key insights from the data. + + Maps: + - Highlight geographical features, landmarks, and any text labels or annotations, such as street names or distances. + - Explain how the map can be used (e.g., for navigation, travel planning, or understanding a region). + - Describe what can be inferred, such as proximity between locations, accessibility of areas, or regional layouts. - If the image is a chart for instance, you should describe the data trends, patterns, and insights that can be drawn from the chart. For example, you could describe the increase or decrease in sales over time, the peak sales period, or the sales performance of a particular product. + Diagrams: + - Describe the components, relationships, and purpose of the diagram. + - Explain how the diagram can be used (e.g., for understanding a process, visualizing a system, or explaining a concept). + - Describe what can be inferred, such as how components interact, dependencies, or the overall system structure. - If the image is a map, you should describe the geographical features, landmarks, and any other relevant information that can be inferred from the map. + Photographs or Logos: + - Return 'Irrelevant Image' if the image is not suitable for actionable purposes like analysis or decision-making e.g. a logo, a personal photo, or a generic landscape. - If the image is a diagram, you should describe the components, relationships, and any other relevant information that can be inferred from the diagram. - Include any data points, labels, and other relevant information that can be inferred from the image. + Guidelines: + - Include all labels, text, and annotations to ensure a complete and accurate description. + - Clearly state both the potential use of the image and what insights or information can be inferred from it. + - Think about what the user might need from the image and describe it accordingly. + - Make sure to consider if the image will be useful for analysis later on. If nothing valuable for analysis, decision making or information retrieval, would be able to be inferred from the image, return 'Irrelevant Image'. - Provide a well-structured, detailed, and actionable analysis of the image. Focus on extracting data and information that can be inferred from the image. + Example: + Input: + - A bar chart showing monthly sales for 2024, with the x-axis labeled "Month" (January to December) and the y-axis labeled "Revenue in USD." The chart shows a steady increase from January to December, with a sharp spike in November. + Output: + - This bar chart shows monthly sales revenue for 2024, with the x-axis labeled 'Month' (January to December) and the y-axis labeled 'Revenue in USD.' It can be used to track sales performance over the year and identify periods of high or low revenue. From the chart, it can be inferred that sales steadily increased throughout the year, with a notable spike in November, possibly due to seasonal promotions or events. - IMPORTANT: If the provided image is a logo or photograph, simply return 'Irrelevant Image'.""" + Input: + - A photograph of a mountain landscape with snow-capped peaks, a winding river, and a dense forest in the foreground. The image captures the natural beauty of the region and the diverse ecosystems present. + Output: + - Irrelevant Image""" - user_input = "Perform technical analysis on this image. Provide a well-structured, description." + user_input = "Generate a description for the image provided that can be used for search purposes." if figure.caption is not None and len(figure.caption) > 0: - user_input += " (note: it has the following caption: {})".format( - figure.caption - ) + user_input += f""" (note: it has the following caption: { + figure.caption})""" try: async with AsyncAzureOpenAI( api_key=None, api_version=api_version, azure_ad_token_provider=token_provider, - azure_endpoint=os.environ.get("AZURE_OPENAI_ENDPOINT"), + azure_endpoint=azure_endpoint, + azure_deployment=deployment_id, ) as client: # We send both image caption and the image body to GPTv for better understanding response = await client.chat.completions.create( - model=model, + model=model_name, messages=[ { "role": "system", @@ -93,7 +157,13 @@ async def understand_image_with_gptv(self, figure: FigureHolder) -> dict: ], max_tokens=MAX_TOKENS, ) - except (OpenAIError, APIError, APIStatusError, BadRequestError) as e: + except ( + OpenAIError, + APIError, + APIStatusError, + BadRequestError, + RateLimitError, + ) as e: logging.error(f"Failed to analyse image. Error: {e}") if "ResponsibleAIPolicyViolation" in e.message: @@ -108,6 +178,10 @@ async def understand_image_with_gptv(self, figure: FigureHolder) -> dict: figure.description = response.choices[0].message.content + if len(figure.description) == 0: + logging.info("No description generated for image.") + figure.description = "Irrelevant Image" + logging.info(f"Image Description: {figure.description}") return figure @@ -128,20 +202,34 @@ async def analyse(self, record: dict) -> dict: try: updated_data = await self.understand_image_with_gptv(figure) - logging.info(f"Updated Data: {updated_data}") - except Exception as e: + logging.info(f"Updated Figure Data: {updated_data}") + except RetryError as e: logging.error(f"Failed to analyse image. Error: {e}") logging.error(f"Failed input: {record}") - return { - "recordId": record["recordId"], - "data": {}, - "errors": [ - { - "message": "Failed to analyse image. Pass a valid source in the request body.", - } - ], - "warnings": None, - } + root_cause = e.last_attempt.exception() + + if isinstance(root_cause, RateLimitError): + return { + "recordId": record["recordId"], + "data": None, + "errors": [ + { + "message": "Failed to analyse image due to rate limit error. Please try again later.", + } + ], + "warnings": None, + } + else: + return { + "recordId": record["recordId"], + "data": None, + "errors": [ + { + "message": "Failed to analyse image. Check the logs for more details.", + } + ], + "warnings": None, + } else: return { "recordId": record["recordId"], diff --git a/image_processing/src/image_processing/layout_analysis.py b/image_processing/src/image_processing/layout_analysis.py index c959bd0a..fc280a98 100644 --- a/image_processing/src/image_processing/layout_analysis.py +++ b/image_processing/src/image_processing/layout_analysis.py @@ -1,6 +1,5 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -# This code originates from: https://github.com/microsoft/dstoolkit-text2sql-and-imageprocessing import logging import os @@ -32,7 +31,7 @@ class StorageAccountHelper: @property def account_url(self) -> str: """Get the account URL of the Azure Blob Storage.""" - storage_account_name = os.environ.get("StorageAccount__Name") + storage_account_name = os.environ["StorageAccount__Name"] return f"https://{storage_account_name}.blob.core.windows.net" async def get_client(self): @@ -42,7 +41,7 @@ async def get_client(self): return BlobServiceClient(account_url=self.account_url, credential=credential) async def add_metadata_to_blob( - self, source: str, container: str, metadata: dict + self, source: str, container: str, metadata: dict, upsert: bool = False ) -> None: """Add metadata to the blob. @@ -51,14 +50,24 @@ async def add_metadata_to_blob( container (str): The container of the blob. metadata (dict): The metadata to add to the blob.""" - blob = urllib.parse.unquote_plus(source) + logging.info("Adding Metadata") + + blob = urllib.parse.unquote(source, encoding="utf-8") blob_service_client = await self.get_client() async with blob_service_client: async with blob_service_client.get_blob_client( container=container, blob=blob ) as blob_client: - await blob_client.set_blob_metadata(metadata) + blob_properties = await blob_client.get_blob_properties() + + if upsert: + updated_metadata = blob_properties.metadata + updated_metadata.update(metadata) + else: + updated_metadata = metadata + + await blob_client.set_blob_metadata(updated_metadata) logging.info("Metadata Added") @@ -103,7 +112,7 @@ async def download_blob_to_temp_dir( container (str): The container of the blob. target_file_name (str): The target file name.""" - blob = urllib.parse.unquote_plus(source) + blob = urllib.parse.unquote(source) blob_service_client = await self.get_client() async with blob_service_client: @@ -254,11 +263,9 @@ async def process_figures_from_extracted_content( ) logging.info(f"Figure Caption: {caption}") - uri = "{}/{}/{}".format( - storage_account_helper.account_url, - self.images_container, - blob, - ) + + uri = f"""{ + storage_account_helper.account_url}/{self.images_container}/{blob}""" offset = figure.spans[0].offset - text_holder.page_offsets @@ -414,7 +421,7 @@ async def analyse(self): logging.error(f"Failed to download the blob: {e}") return { "recordId": self.record_id, - "data": {}, + "data": None, "errors": [ { "message": f"Failed to download the blob. Check the source and try again. {e}", @@ -430,9 +437,12 @@ async def analyse(self): logging.error( "Failed to analyse %s with Azure Document Intelligence.", self.blob ) + await storage_account_helper.add_metadata_to_blob( + self.blob, self.container, {"AzureSearch_Skip": "true"}, upsert=True + ) return { "recordId": self.record_id, - "data": {}, + "data": None, "errors": [ { "message": f"Failed to analyze the document with Azure Document Intelligence. Check the logs and try again. {e}", @@ -484,7 +494,7 @@ async def analyse(self): logging.error(f"Failed to process the extracted content: {e}") return { "recordId": self.record_id, - "data": {}, + "data": None, "errors": [ { "message": f"Failed to process the extracted content. Check the logs and try again. {e}", @@ -536,7 +546,7 @@ async def process_layout_analysis( except KeyError: return { "recordId": record["recordId"], - "data": {}, + "data": None, "errors": [ { "message": "Failed to extract data with ADI. Pass a valid source in the request body.", From eef8b6f3a6ff1c3c77a88bdeb8f4eb9ee18a4938 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Thu, 16 Jan 2025 19:04:31 +0000 Subject: [PATCH 13/64] Update precommit --- .pre-commit-config.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4871ce1b..54ac7d9d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -51,3 +51,12 @@ repos: hooks: # Update the uv lockfile - id: uv-lock + + - repo: local + hooks: + - id: compile-image-processing-requirements + name: compile-image-processing-requirements + language: system + entry: bash -c 'cd image_processing && exec uv pip compile' + pass_filenames: false + files: ^image_processing/ From b47ccf8a626aa2835f0574eb5646c175518118c8 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Thu, 16 Jan 2025 19:20:26 +0000 Subject: [PATCH 14/64] Update code --- .pre-commit-config.yaml | 4 ++-- deploy_ai_search/src/deploy_ai_search/rag_documents.py | 5 ++--- image_processing/src/image_processing/function_app.py | 6 ++++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 54ac7d9d..b539a4c9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -57,6 +57,6 @@ repos: - id: compile-image-processing-requirements name: compile-image-processing-requirements language: system - entry: bash -c 'cd image_processing && exec uv pip compile' + entry: bash -c 'cd image_processing && exec uv pip compile --all-extras pyproject.toml' pass_filenames: false - files: ^image_processing/ + files: ^image_processing/ diff --git a/deploy_ai_search/src/deploy_ai_search/rag_documents.py b/deploy_ai_search/src/deploy_ai_search/rag_documents.py index ef6910b5..bf5cdf70 100644 --- a/deploy_ai_search/src/deploy_ai_search/rag_documents.py +++ b/deploy_ai_search/src/deploy_ai_search/rag_documents.py @@ -101,11 +101,10 @@ def get_index_fields(self) -> list[SearchableField]: name="ChunkFigures", collection=True, fields=[ - SearchableField( + SimpleField( name="FigureId", type=SearchFieldDataType.String, - collection=True, - searchable=False, + filterable=True, ), SimpleField( name="Caption", diff --git a/image_processing/src/image_processing/function_app.py b/image_processing/src/image_processing/function_app.py index 9dfff2f6..2960116e 100644 --- a/image_processing/src/image_processing/function_app.py +++ b/image_processing/src/image_processing/function_app.py @@ -8,7 +8,7 @@ from figure_analysis import FigureAnalysis from layout_and_figure_merger import LayoutAndFigureMerger from layout_analysis import process_layout_analysis -from image_processing.mark_up_cleaner import process_mark_up_cleaner +from image_processing.mark_up_cleaner import MarkUpCleaner from semantic_text_chunker import process_semantic_text_chunker, SemanticTextChunker logging.basicConfig(level=logging.DEBUG) @@ -136,8 +136,10 @@ async def mark_up_cleaner(req: func.HttpRequest) -> func.HttpResponse: record_tasks = [] + mark_up_cleaner = MarkUpCleaner() + for value in values: - record_tasks.append(asyncio.create_task(process_mark_up_cleaner(value))) + record_tasks.append(asyncio.create_task(mark_up_cleaner.clean(value))) results = await asyncio.gather(*record_tasks) logging.debug("Results: %s", results) From b120adf0b703c98cdf0c9d0ad1cc719a22cd1ea8 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Thu, 16 Jan 2025 19:22:36 +0000 Subject: [PATCH 15/64] Update directory --- .pre-commit-config.yaml | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b539a4c9..c7893acc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -52,11 +52,18 @@ repos: # Update the uv lockfile - id: uv-lock - - repo: local + - repo: https://github.com/astral-sh/uv-pre-commit + # uv version. + rev: 0.5.8 hooks: - - id: compile-image-processing-requirements - name: compile-image-processing-requirements - language: system - entry: bash -c 'cd image_processing && exec uv pip compile --all-extras pyproject.toml' - pass_filenames: false - files: ^image_processing/ + - id: uv-export + args: [--all-extras --directory, image_processing] + + # - repo: local + # hooks: + # - id: compile-image-processing-requirements + # name: compile-image-processing-requirements + # language: system + # entry: bash -c 'cd image_processing && exec uv pip compile --all-extras pyproject.toml' + # pass_filenames: false + # files: ^image_processing/ From 54aec5d679c0af1c5d3d8587942d0e1de4126e13 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Thu, 16 Jan 2025 19:23:35 +0000 Subject: [PATCH 16/64] Try new export --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c7893acc..c9ee227e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -57,7 +57,7 @@ repos: rev: 0.5.8 hooks: - id: uv-export - args: [--all-extras --directory, image_processing] + args: [--all-extras, --directory, image_processing] # - repo: local # hooks: From 600ae3b6b7787e923056633f456e55e87c8021eb Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Thu, 16 Jan 2025 19:24:53 +0000 Subject: [PATCH 17/64] Update pre commit --- .pre-commit-config.yaml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c9ee227e..e80b1687 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -59,11 +59,10 @@ repos: - id: uv-export args: [--all-extras, --directory, image_processing] - # - repo: local - # hooks: - # - id: compile-image-processing-requirements - # name: compile-image-processing-requirements - # language: system - # entry: bash -c 'cd image_processing && exec uv pip compile --all-extras pyproject.toml' - # pass_filenames: false - # files: ^image_processing/ + - repo: local + hooks: + - id: compile-image-processing-requirements + name: compile-image-processing-requirements + language: system + entry: bash -c 'cd image_processing && exec uv export --all-extras' + pass_filenames: false From 6a47d39c4cd8410b375b111cb179489f4d943e95 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Thu, 16 Jan 2025 19:25:37 +0000 Subject: [PATCH 18/64] Update req --- image_processing/requirements.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 image_processing/requirements.txt diff --git a/image_processing/requirements.txt b/image_processing/requirements.txt new file mode 100644 index 00000000..e69de29b From c357ddd7419c95d289da90345f23226aed93ace0 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Thu, 16 Jan 2025 19:37:18 +0000 Subject: [PATCH 19/64] Update requirements --- .pre-commit-config.yaml | 11 +- image_processing/requirements.txt | 1238 +++++++++++++++++++++++++++++ 2 files changed, 1240 insertions(+), 9 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e80b1687..236c4e3b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -47,22 +47,15 @@ repos: - repo: https://github.com/astral-sh/uv-pre-commit # uv version. - rev: 0.5.5 + rev: 0.5.20 hooks: # Update the uv lockfile - id: uv-lock - - repo: https://github.com/astral-sh/uv-pre-commit - # uv version. - rev: 0.5.8 - hooks: - - id: uv-export - args: [--all-extras, --directory, image_processing] - - repo: local hooks: - id: compile-image-processing-requirements name: compile-image-processing-requirements language: system - entry: bash -c 'cd image_processing && exec uv export --all-extras' + entry: bash -c 'cd image_processing && exec uv export --all-extras > requirements.txt' pass_filenames: false diff --git a/image_processing/requirements.txt b/image_processing/requirements.txt index e69de29b..a75053a4 100644 --- a/image_processing/requirements.txt +++ b/image_processing/requirements.txt @@ -0,0 +1,1238 @@ +# This file was autogenerated by uv via the following command: +# uv export --all-extras +aiohappyeyeballs==2.4.4 \ + --hash=sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745 \ + --hash=sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8 +aiohttp==3.11.11 \ + --hash=sha256:0882c2820fd0132240edbb4a51eb8ceb6eef8181db9ad5291ab3332e0d71df5f \ + --hash=sha256:0b7fb429ab1aafa1f48578eb315ca45bd46e9c37de11fe45c7f5f4138091e2f1 \ + --hash=sha256:1e69966ea6ef0c14ee53ef7a3d68b564cc408121ea56c0caa2dc918c1b2f553d \ + --hash=sha256:3499c7ffbfd9c6a3d8d6a2b01c26639da7e43d47c7b4f788016226b1e711caa8 \ + --hash=sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2 \ + --hash=sha256:541d823548ab69d13d23730a06f97460f4238ad2e5ed966aaf850d7c369782d9 \ + --hash=sha256:620598717fce1b3bd14dd09947ea53e1ad510317c85dda2c9c65b622edc96b12 \ + --hash=sha256:6fba278063559acc730abf49845d0e9a9e1ba74f85f0ee6efd5803f08b285853 \ + --hash=sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c \ + --hash=sha256:8e2bf8029dbf0810c7bfbc3e594b51c4cc9101fbffb583a3923aea184724203c \ + --hash=sha256:929f3ed33743a49ab127c58c3e0a827de0664bfcda566108989a14068f820194 \ + --hash=sha256:92fc484e34b733704ad77210c7957679c5c3877bd1e6b6d74b185e9320cc716e \ + --hash=sha256:9d73ee3725b7a737ad86c2eac5c57a4a97793d9f442599bea5ec67ac9f4bdc3d \ + --hash=sha256:9f5b3c1ed63c8fa937a920b6c1bec78b74ee09593b3f5b979ab2ae5ef60d7600 \ + --hash=sha256:a344d5dc18074e3872777b62f5f7d584ae4344cd6006c17ba12103759d407af3 \ + --hash=sha256:a8f5f7515f3552d899c61202d99dcb17d6e3b0de777900405611cd747cecd1b8 \ + --hash=sha256:a9b7371665d4f00deb8f32208c7c5e652059b0fda41cf6dbcac6114a041f1cc2 \ + --hash=sha256:aa54f8ef31d23c506910c21163f22b124facb573bff73930735cf9fe38bf7dff \ + --hash=sha256:b6212a60e5c482ef90f2d788835387070a88d52cf6241d3916733c9176d39eab \ + --hash=sha256:b63de12e44935d5aca7ed7ed98a255a11e5cb47f83a9fded7a5e41c40277d104 \ + --hash=sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e \ + --hash=sha256:bd7227b87a355ce1f4bf83bfae4399b1f5bb42e0259cb9405824bd03d2f4336a \ + --hash=sha256:bf8d9bfee991d8acc72d060d53860f356e07a50f0e0d09a8dfedea1c554dd0d5 \ + --hash=sha256:c341c7d868750e31961d6d8e60ff040fb9d3d3a46d77fd85e1ab8e76c3e9a5c4 \ + --hash=sha256:c7a06301c2fb096bdb0bd25fe2011531c1453b9f2c163c8031600ec73af1cc99 \ + --hash=sha256:d119fafe7b634dbfa25a8c597718e69a930e4847f0b88e172744be24515140da \ + --hash=sha256:d40f9da8cabbf295d3a9dae1295c69975b86d941bc20f0a087f0477fa0a66231 \ + --hash=sha256:de8d38f1c2810fa2a4f1d995a2e9c70bb8737b18da04ac2afbf3971f65781d87 \ + --hash=sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886 \ + --hash=sha256:ed9ee95614a71e87f1a70bc81603f6c6760128b140bc4030abe6abaa988f1c3d \ + --hash=sha256:ffb3dc385f6bb1568aa974fe65da84723210e5d9707e360e9ecb51f59406cd2e +aiosignal==1.3.2 \ + --hash=sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5 \ + --hash=sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54 +annotated-types==0.7.0 \ + --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ + --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 +anyio==4.8.0 \ + --hash=sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a \ + --hash=sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a +appnope==0.1.4 ; sys_platform == 'darwin' \ + --hash=sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee \ + --hash=sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c +argon2-cffi==23.1.0 \ + --hash=sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08 \ + --hash=sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea +argon2-cffi-bindings==21.2.0 \ + --hash=sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c \ + --hash=sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082 \ + --hash=sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f \ + --hash=sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d \ + --hash=sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f \ + --hash=sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae \ + --hash=sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3 \ + --hash=sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86 \ + --hash=sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367 \ + --hash=sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93 \ + --hash=sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e +arrow==1.3.0 \ + --hash=sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80 \ + --hash=sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85 +asttokens==3.0.0 \ + --hash=sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7 \ + --hash=sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2 +async-lru==2.0.4 \ + --hash=sha256:b8a59a5df60805ff63220b2a0c5b5393da5521b113cd5465a44eb037d81a5627 \ + --hash=sha256:ff02944ce3c288c5be660c42dbcca0742b32c3b279d6dceda655190240b99224 +attrs==24.3.0 \ + --hash=sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff \ + --hash=sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308 +azure-ai-documentintelligence==1.0.0 \ + --hash=sha256:c8b6efc0fc7e65d7892c9585cfd256f7d8b3f2b46cecf92c75ab82e629eac253 \ + --hash=sha256:cdedb1a67c075f58f47a413ec5846bf8d532a83a71f0c51ec49ce9b5bfe2a519 +azure-ai-textanalytics==5.3.0 \ + --hash=sha256:4f7d067d5bb08422599ca6175510d39b0911c711301647e5f18e904a5027bf58 \ + --hash=sha256:69bb736d93de81060e9075d42b6f0b92c25be0fb106da5cb6a6d30e772168221 +azure-ai-vision-imageanalysis==1.0.0 \ + --hash=sha256:9a7e4aed611d8b4b5fbe528e4e56257d3543b26affe98914f5fd2c53381c264d \ + --hash=sha256:a79bbbb9c6992fef3be53395d339c9db850719583ef96ac64e054b00b545b3b6 +azure-common==1.1.28 \ + --hash=sha256:4ac0cd3214e36b6a1b6a442686722a5d8cc449603aa833f3f0f40bda836704a3 \ + --hash=sha256:5c12d3dcf4ec20599ca6b0d3e09e86e146353d443e7fcc050c9a19c1f9df20ad +azure-core==1.32.0 \ + --hash=sha256:22b3c35d6b2dae14990f6c1be2912bf23ffe50b220e708a28ab1bb92b1c730e5 \ + --hash=sha256:eac191a0efb23bfa83fddf321b27b122b4ec847befa3091fa736a5c32c50d7b4 +azure-functions==1.21.3 \ + --hash=sha256:6c45f5e61fe59328c81928a428d43c838e9ead52f1cde1628fcabb372fa10cc8 \ + --hash=sha256:c359b9dbd2998c84d8595e31a28ffad4e8ca8dcfb4a3798327f776a67f964351 +azure-identity==1.19.0 \ + --hash=sha256:500144dc18197d7019b81501165d4fa92225f03778f17d7ca8a2a180129a9c83 \ + --hash=sha256:e3f6558c181692d7509f09de10cca527c7dce426776454fb97df512a46527e81 +azure-search==1.0.0b2 \ + --hash=sha256:49cbb1937b2e256f6631d467f62f8a1c94a14c5fed84f6625d24bc7b210a25d4 \ + --hash=sha256:ba3974224be1329d26e58e63df9c8561b416e7536b79a1c5576055dfb6c472ae +azure-search-documents==11.6.0b8 \ + --hash=sha256:5fa84bacbf72b9778ab7a2a43ab5df335fc5516eeb169c36d78ced39a29cfe69 \ + --hash=sha256:edd7af876dc9353d1ede46429547df0a3891beed182308636f0f86a97cce94b5 +azure-storage-blob==12.24.0 \ + --hash=sha256:4f0bb4592ea79a2d986063696514c781c9e62be240f09f6397986e01755bc071 \ + --hash=sha256:eaaaa1507c8c363d6e1d1342bd549938fdf1adec9b1ada8658c8f5bf3aea844e +babel==2.16.0 \ + --hash=sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b \ + --hash=sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316 +beautifulsoup4==4.12.3 \ + --hash=sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051 \ + --hash=sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed +black==24.10.0 \ + --hash=sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f \ + --hash=sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981 \ + --hash=sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b \ + --hash=sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8 \ + --hash=sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d \ + --hash=sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b \ + --hash=sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875 \ + --hash=sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3 \ + --hash=sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65 \ + --hash=sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2 +bleach==6.2.0 \ + --hash=sha256:117d9c6097a7c3d22fd578fcd8d35ff1e125df6736f554da4e432fdd63f31e5e \ + --hash=sha256:123e894118b8a599fd80d3ec1a6d4cc7ce4e5882b1317a7e1ba69b56e95f991f +blis==0.7.11 \ + --hash=sha256:5a305dbfc96d202a20d0edd6edf74a406b7e1404f4fa4397d24c68454e60b1b4 \ + --hash=sha256:5bcdaf370f03adaf4171d6405a89fa66cb3c09399d75fc02e1230a78cd2759e4 \ + --hash=sha256:7de19264b1d49a178bf8035406d0ae77831f3bfaa3ce02942964a81a202abb03 \ + --hash=sha256:8ea55c6a4a60fcbf6a0fdce40df6e254451ce636988323a34b9c94b583fc11e5 \ + --hash=sha256:cec6d48f75f7ac328ae1b6fbb372dde8c8a57c89559172277f66e01ff08d4d42 \ + --hash=sha256:dadf8713ea51d91444d14ad4104a5493fa7ecc401bbb5f4a203ff6448fadb113 +bs4==0.0.2 \ + --hash=sha256:a48685c58f50fe127722417bae83fe6badf500d54b55f7e39ffe43b798653925 \ + --hash=sha256:abf8742c0805ef7f662dce4b51cca104cffe52b835238afc169142ab9b3fbccc +catalogue==2.0.10 \ + --hash=sha256:4f56daa940913d3f09d589c191c74e5a6d51762b3a9e37dd53b7437afd6cda15 \ + --hash=sha256:58c2de0020aa90f4a2da7dfad161bf7b3b054c86a5f09fcedc0b2b740c109a9f +certifi==2024.12.14 \ + --hash=sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56 \ + --hash=sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db +cffi==1.17.1 \ + --hash=sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2 \ + --hash=sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36 \ + --hash=sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824 \ + --hash=sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3 \ + --hash=sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed \ + --hash=sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8 \ + --hash=sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903 \ + --hash=sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683 \ + --hash=sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9 \ + --hash=sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c \ + --hash=sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4 \ + --hash=sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65 \ + --hash=sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93 \ + --hash=sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4 \ + --hash=sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3 \ + --hash=sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff \ + --hash=sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5 \ + --hash=sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd \ + --hash=sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5 \ + --hash=sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d \ + --hash=sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e \ + --hash=sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a \ + --hash=sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99 +cfgv==3.4.0 \ + --hash=sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9 \ + --hash=sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560 +charset-normalizer==3.4.1 \ + --hash=sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd \ + --hash=sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601 \ + --hash=sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d \ + --hash=sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313 \ + --hash=sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa \ + --hash=sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2 \ + --hash=sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b \ + --hash=sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3 \ + --hash=sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f \ + --hash=sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9 \ + --hash=sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f \ + --hash=sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545 \ + --hash=sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b \ + --hash=sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9 \ + --hash=sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11 \ + --hash=sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35 \ + --hash=sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda \ + --hash=sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971 \ + --hash=sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d \ + --hash=sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757 \ + --hash=sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a \ + --hash=sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886 \ + --hash=sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85 \ + --hash=sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7 \ + --hash=sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1 \ + --hash=sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407 \ + --hash=sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd \ + --hash=sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616 +click==8.1.8 \ + --hash=sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2 \ + --hash=sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a +cloudpathlib==0.20.0 \ + --hash=sha256:7af3bcefbf73392ae7f31c08b3660ec31607f8c01b7f6262d4d73469a845f641 \ + --hash=sha256:f6ef7ca409a510f7ba4639ba50ab3fc5b6dee82d6dff0d7f5715fd0c9ab35891 +colorama==0.4.6 ; sys_platform == 'win32' \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 +comm==0.2.2 \ + --hash=sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e \ + --hash=sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3 +confection==0.1.5 \ + --hash=sha256:8e72dd3ca6bd4f48913cd220f10b8275978e740411654b6e8ca6d7008c590f0e \ + --hash=sha256:e29d3c3f8eac06b3f77eb9dfb4bf2fc6bcc9622a98ca00a698e3d019c6430b14 +cryptography==44.0.0 \ + --hash=sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7 \ + --hash=sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b \ + --hash=sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc \ + --hash=sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543 \ + --hash=sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591 \ + --hash=sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede \ + --hash=sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb \ + --hash=sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f \ + --hash=sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123 \ + --hash=sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c \ + --hash=sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285 \ + --hash=sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd \ + --hash=sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092 \ + --hash=sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289 \ + --hash=sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02 \ + --hash=sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64 \ + --hash=sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053 \ + --hash=sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417 \ + --hash=sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e \ + --hash=sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e \ + --hash=sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7 +cymem==2.0.10 \ + --hash=sha256:33d7f5014ad36af22995847fccd82ca0bd4b0394fb1d9dd9fef1e8cefdab2444 \ + --hash=sha256:5698a515900dc697874444fa05d8d852bbad43543de2e7834ec3895156cc2aad \ + --hash=sha256:5e57928d9e93c61265281ea01a1d24499d397625b2766a0c5735b99bceb3ba75 \ + --hash=sha256:6580d657d0f208d675d62cc052fb908529d52d24282342e24a9843de85352b88 \ + --hash=sha256:6ae7f22af4bc4311f06c925df61c62219c11939dffc9c91d67caf89a7e1557a5 \ + --hash=sha256:82f19a39052747309ced6b948b34aff62aa00c795c9d9d3d31a071e8c791efee \ + --hash=sha256:c6ed8b1ed448cd65e12405a02aa71b22a4094d8a623205625057c4c73ba4b133 \ + --hash=sha256:dc4932060a5d55648fa4a3960f1cad9905572ed5c6f02af42f849e869d2803d4 \ + --hash=sha256:ea72cf0e369f3cf1f10038d572143d88ce7c959222cf7d742acbeb45e00ac5c0 \ + --hash=sha256:f4bc6c823b400d32cddcfeefb3f352d52a0cc911cb0b5c1ef64e3f9741fd56b9 \ + --hash=sha256:f51700acfa1209b4a221dc892cca8030f4bc10d4c153dec098042f484c7f07a4 +debugpy==1.8.11 \ + --hash=sha256:0e22f846f4211383e6a416d04b4c13ed174d24cc5d43f5fd52e7821d0ebc8920 \ + --hash=sha256:28e45b3f827d3bf2592f3cf7ae63282e859f3259db44ed2b129093ca0ac7940b \ + --hash=sha256:44b1b8e6253bceada11f714acf4309ffb98bfa9ac55e4fce14f9e5d4484287a1 \ + --hash=sha256:6ad2688b69235c43b020e04fecccdf6a96c8943ca9c2fb340b8adc103c655e57 \ + --hash=sha256:6c1f6a173d1140e557347419767d2b14ac1c9cd847e0b4c5444c7f3144697e4e \ + --hash=sha256:84e511a7545d11683d32cdb8f809ef63fc17ea2a00455cc62d0a4dbb4ed1c308 \ + --hash=sha256:8988f7163e4381b0da7696f37eec7aca19deb02e500245df68a7159739bbd0d3 \ + --hash=sha256:bb3b15e25891f38da3ca0740271e63ab9db61f41d4d8541745cfc1824252cb28 \ + --hash=sha256:ce291a5aca4985d82875d6779f61375e959208cdf09fcec40001e65fb0a54768 \ + --hash=sha256:d8768edcbeb34da9e11bcb8b5c2e0958d25218df7a6e56adf415ef262cd7b6d1 +decorator==5.1.1 \ + --hash=sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330 \ + --hash=sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186 +defusedxml==0.7.1 \ + --hash=sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69 \ + --hash=sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61 +distlib==0.3.9 \ + --hash=sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87 \ + --hash=sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403 +distro==1.9.0 \ + --hash=sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed \ + --hash=sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2 +en-core-web-md @ https://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.7.1/en_core_web_md-3.7.1.tar.gz \ + --hash=sha256:3273a1335fcb688be09949c5cdb73e85eb584ec3dfc50d4338c17daf6ccd4628 +et-xmlfile==2.0.0 \ + --hash=sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa \ + --hash=sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54 +executing==2.1.0 \ + --hash=sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf \ + --hash=sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab +fastjsonschema==2.21.1 \ + --hash=sha256:794d4f0a58f848961ba16af7b9c85a3e88cd360df008c59aac6fc5ae9323b5d4 \ + --hash=sha256:c9e5b7e908310918cf494a434eeb31384dd84a98b57a30bcb1f535015b554667 +filelock==3.16.1 \ + --hash=sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0 \ + --hash=sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435 +fqdn==1.5.1 \ + --hash=sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f \ + --hash=sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014 +frozenlist==1.5.0 \ + --hash=sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e \ + --hash=sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28 \ + --hash=sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b \ + --hash=sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9 \ + --hash=sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2 \ + --hash=sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8 \ + --hash=sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6 \ + --hash=sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21 \ + --hash=sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c \ + --hash=sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608 \ + --hash=sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de \ + --hash=sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f \ + --hash=sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641 \ + --hash=sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9 \ + --hash=sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f \ + --hash=sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a \ + --hash=sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784 \ + --hash=sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d \ + --hash=sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03 \ + --hash=sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e \ + --hash=sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953 \ + --hash=sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee \ + --hash=sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817 \ + --hash=sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039 \ + --hash=sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f \ + --hash=sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439 \ + --hash=sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631 \ + --hash=sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840 \ + --hash=sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3 \ + --hash=sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0 \ + --hash=sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e \ + --hash=sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a +fsspec==2024.12.0 \ + --hash=sha256:670700c977ed2fb51e0d9f9253177ed20cbde4a3e5c0283cc5385b5870c8533f \ + --hash=sha256:b520aed47ad9804237ff878b504267a3b0b441e97508bd6d2d8774e3db85cee2 +h11==0.14.0 \ + --hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \ + --hash=sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761 +httpcore==1.0.7 \ + --hash=sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c \ + --hash=sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd +httpx==0.28.1 \ + --hash=sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc \ + --hash=sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad +huggingface-hub==0.27.1 \ + --hash=sha256:1c5155ca7d60b60c2e2fc38cbb3ffb7f7c3adf48f824015b219af9061771daec \ + --hash=sha256:c004463ca870283909d715d20f066ebd6968c2207dae9393fdffb3c1d4d8f98b +identify==2.6.5 \ + --hash=sha256:14181a47091eb75b337af4c23078c9d09225cd4c48929f521f3bf16b09d02566 \ + --hash=sha256:c10b33f250e5bba374fae86fb57f3adcebf1161bce7cdf92031915fd480c13bc +idna==3.10 \ + --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \ + --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3 +ipykernel==6.29.5 \ + --hash=sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5 \ + --hash=sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215 +ipython==8.31.0 \ + --hash=sha256:46ec58f8d3d076a61d128fe517a51eb730e3aaf0c184ea8c17d16e366660c6a6 \ + --hash=sha256:b6a2274606bec6166405ff05e54932ed6e5cfecaca1fc05f2cacde7bb074d70b +ipywidgets==8.1.5 \ + --hash=sha256:3290f526f87ae6e77655555baba4f36681c555b8bdbbff430b70e52c34c86245 \ + --hash=sha256:870e43b1a35656a80c18c9503bbf2d16802db1cb487eec6fab27d683381dde17 +isodate==0.7.2 \ + --hash=sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15 \ + --hash=sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6 +isoduration==20.11.0 \ + --hash=sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9 \ + --hash=sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042 +jedi==0.19.2 \ + --hash=sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0 \ + --hash=sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9 +jinja2==3.1.5 \ + --hash=sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb \ + --hash=sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb +jiter==0.8.2 \ + --hash=sha256:025337859077b41548bdcbabe38698bcd93cfe10b06ff66617a48ff92c9aec60 \ + --hash=sha256:14601dcac4889e0a1c75ccf6a0e4baf70dbc75041e51bcf8d0e9274519df6887 \ + --hash=sha256:180a8aea058f7535d1c84183c0362c710f4750bef66630c05f40c93c2b152a0f \ + --hash=sha256:37b2998606d6dadbb5ccda959a33d6a5e853252d921fec1792fc902351bb4e2c \ + --hash=sha256:3ac9f578c46f22405ff7f8b1f5848fb753cc4b8377fbec8470a7dc3997ca7566 \ + --hash=sha256:4ab9a87f3784eb0e098f84a32670cfe4a79cb6512fd8f42ae3d0709f06405d18 \ + --hash=sha256:5672a86d55416ccd214c778efccf3266b84f87b89063b582167d803246354be4 \ + --hash=sha256:58dc9bc9767a1101f4e5e22db1b652161a225874d66f0e5cb8e2c7d1c438b587 \ + --hash=sha256:653cf462db4e8c41995e33d865965e79641ef45369d8a11f54cd30888b7e6ff1 \ + --hash=sha256:711e408732d4e9a0208008e5892c2966b485c783cd2d9a681f3eb147cf36c7ef \ + --hash=sha256:76e324da7b5da060287c54f2fabd3db5f76468006c811831f051942bf68c9d44 \ + --hash=sha256:789361ed945d8d42850f919342a8665d2dc79e7e44ca1c97cc786966a21f627a \ + --hash=sha256:79aec8172b9e3c6d05fd4b219d5de1ac616bd8da934107325a6c0d0e866a21b6 \ + --hash=sha256:7efe4853ecd3d6110301665a5178b9856be7e2a9485f49d91aa4d737ad2ae49e \ + --hash=sha256:83c0efd80b29695058d0fd2fa8a556490dbce9804eac3e281f373bbc99045f6c \ + --hash=sha256:92249669925bc1c54fcd2ec73f70f2c1d6a817928480ee1c65af5f6b81cdf12d \ + --hash=sha256:9c63eaef32b7bebac8ebebf4dabebdbc6769a09c127294db6babee38e9f405b9 \ + --hash=sha256:ab7f43235d71e03b941c1630f4b6e3055d46b6cb8728a17663eaac9d8e83a865 \ + --hash=sha256:b2dd880785088ff2ad21ffee205e58a8c1ddabc63612444ae41e5e4b321b39c0 \ + --hash=sha256:b426f72cd77da3fec300ed3bc990895e2dd6b49e3bfe6c438592a3ba660e41ca \ + --hash=sha256:bf55846c7b7a680eebaf9c3c48d630e1bf51bdf76c68a5f654b8524335b0ad29 \ + --hash=sha256:ca1f08b8e43dc3bd0594c992fb1fd2f7ce87f7bf0d44358198d6da8034afdf84 \ + --hash=sha256:cd73d3e740666d0e639f678adb176fad25c1bcbdae88d8d7b857e1783bb4212d \ + --hash=sha256:e6ec2be506e7d6f9527dae9ff4b7f54e68ea44a0ef6b098256ddf895218a2f8f \ + --hash=sha256:e725edd0929fa79f8349ab4ec7f81c714df51dc4e991539a578e5018fa4a7152 \ + --hash=sha256:eb21aaa9a200d0a80dacc7a81038d2e476ffe473ffdd9c91eb745d623561de05 \ + --hash=sha256:ecff0dc14f409599bbcafa7e470c00b80f17abc14d1405d38ab02e4b42e55b57 \ + --hash=sha256:ffd9fee7d0775ebaba131f7ca2e2d83839a62ad65e8e02fe2bd8fc975cedeb9e +joblib==1.4.2 \ + --hash=sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6 \ + --hash=sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e +json5==0.10.0 \ + --hash=sha256:19b23410220a7271e8377f81ba8aacba2fdd56947fbb137ee5977cbe1f5e8dfa \ + --hash=sha256:e66941c8f0a02026943c52c2eb34ebeb2a6f819a0be05920a6f5243cd30fd559 +jsonpointer==3.0.0 \ + --hash=sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942 \ + --hash=sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef +jsonschema==4.23.0 \ + --hash=sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4 \ + --hash=sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566 +jsonschema-specifications==2024.10.1 \ + --hash=sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272 \ + --hash=sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf +jupyter==1.1.1 \ + --hash=sha256:7a59533c22af65439b24bbe60373a4e95af8f16ac65a6c00820ad378e3f7cc83 \ + --hash=sha256:d55467bceabdea49d7e3624af7e33d59c37fff53ed3a350e1ac957bed731de7a +jupyter-client==8.6.3 \ + --hash=sha256:35b3a0947c4a6e9d589eb97d7d4cd5e90f910ee73101611f01283732bd6d9419 \ + --hash=sha256:e8a19cc986cc45905ac3362915f410f3af85424b4c0905e94fa5f2cb08e8f23f +jupyter-console==6.6.3 \ + --hash=sha256:309d33409fcc92ffdad25f0bcdf9a4a9daa61b6f341177570fdac03de5352485 \ + --hash=sha256:566a4bf31c87adbfadf22cdf846e3069b59a71ed5da71d6ba4d8aaad14a53539 +jupyter-core==5.7.2 \ + --hash=sha256:4f7315d2f6b4bcf2e3e7cb6e46772eba760ae459cd1f59d29eb57b0a01bd7409 \ + --hash=sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9 +jupyter-events==0.11.0 \ + --hash=sha256:36399b41ce1ca45fe8b8271067d6a140ffa54cec4028e95491c93b78a855cacf \ + --hash=sha256:c0bc56a37aac29c1fbc3bcfbddb8c8c49533f9cf11f1c4e6adadba936574ab90 +jupyter-lsp==2.2.5 \ + --hash=sha256:45fbddbd505f3fbfb0b6cb2f1bc5e15e83ab7c79cd6e89416b248cb3c00c11da \ + --hash=sha256:793147a05ad446f809fd53ef1cd19a9f5256fd0a2d6b7ce943a982cb4f545001 +jupyter-server==2.15.0 \ + --hash=sha256:872d989becf83517012ee669f09604aa4a28097c0bd90b2f424310156c2cdae3 \ + --hash=sha256:9d446b8697b4f7337a1b7cdcac40778babdd93ba614b6d68ab1c0c918f1c4084 +jupyter-server-terminals==0.5.3 \ + --hash=sha256:41ee0d7dc0ebf2809c668e0fc726dfaf258fcd3e769568996ca731b6194ae9aa \ + --hash=sha256:5ae0295167220e9ace0edcfdb212afd2b01ee8d179fe6f23c899590e9b8a5269 +jupyterlab==4.3.4 \ + --hash=sha256:b754c2601c5be6adf87cb5a1d8495d653ffb945f021939f77776acaa94dae952 \ + --hash=sha256:f0bb9b09a04766e3423cccc2fc23169aa2ffedcdf8713e9e0fb33cac0b6859d0 +jupyterlab-pygments==0.3.0 \ + --hash=sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d \ + --hash=sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780 +jupyterlab-server==2.27.3 \ + --hash=sha256:e697488f66c3db49df675158a77b3b017520d772c6e1548c7d9bcc5df7944ee4 \ + --hash=sha256:eb36caca59e74471988f0ae25c77945610b887f777255aa21f8065def9e51ed4 +jupyterlab-widgets==3.0.13 \ + --hash=sha256:a2966d385328c1942b683a8cd96b89b8dd82c8b8f81dda902bb2bc06d46f5bed \ + --hash=sha256:e3cda2c233ce144192f1e29914ad522b2f4c40e77214b0cc97377ca3d323db54 +langcodes==3.5.0 \ + --hash=sha256:1eef8168d07e51e131a2497ffecad4b663f6208e7c3ae3b8dc15c51734a6f801 \ + --hash=sha256:853c69d1a35e0e13da2f427bb68fb2fa4a8f4fb899e0c62ad8df8d073dcfed33 +language-data==1.3.0 \ + --hash=sha256:7600ef8aa39555145d06c89f0c324bf7dab834ea0b0a439d8243762e3ebad7ec \ + --hash=sha256:e2ee943551b5ae5f89cd0e801d1fc3835bb0ef5b7e9c3a4e8e17b2b214548fbf +marisa-trie==1.2.1 \ + --hash=sha256:20948e40ab2038e62b7000ca6b4a913bc16c91a2c2e6da501bd1f917eeb28d51 \ + --hash=sha256:2428b495003c189695fb91ceeb499f9fcced3a2dce853e17fa475519433c67ff \ + --hash=sha256:36aa4401a1180615f74d575571a6550081d84fc6461e9aefc0bb7b2427af098e \ + --hash=sha256:3a27c408e2aefc03e0f1d25b2ff2afb85aac3568f6fa2ae2a53b57a2e87ce29d \ + --hash=sha256:3ad356442c2fea4c2a6f514738ddf213d23930f942299a2b2c05df464a00848a \ + --hash=sha256:46e528ee71808c961baf8c3ce1c46a8337ec7a96cc55389d11baafe5b632f8e9 \ + --hash=sha256:5e649f3dc8ab5476732094f2828cc90cac3be7c79bc0c8318b6fda0c1d248db4 \ + --hash=sha256:638506eacf20ca503fff72221a7e66a6eadbf28d6a4a6f949fcf5b1701bb05ec \ + --hash=sha256:6532615111eec2c79e711965ece0bc95adac1ff547a7fff5ffca525463116deb \ + --hash=sha256:66b23e5b35dd547f85bf98db7c749bc0ffc57916ade2534a6bbc32db9a4abc44 \ + --hash=sha256:6704adf0247d2dda42e876b793be40775dff46624309ad99bc7537098bee106d \ + --hash=sha256:735c363d9aaac82eaf516a28f7c6b95084c2e176d8231c87328dc80e112a9afa \ + --hash=sha256:98042040d1d6085792e8d0f74004fc0f5f9ca6091c298f593dd81a22a4643854 \ + --hash=sha256:9f627f4e41be710b6cb6ed54b0128b229ac9d50e2054d9cde3af0fef277c23cf \ + --hash=sha256:aa7cd17e1c690ce96c538b2f4aae003d9a498e65067dd433c52dd069009951d4 \ + --hash=sha256:b2a7d00f53f4945320b551bccb826b3fb26948bde1a10d50bb9802fabb611b10 \ + --hash=sha256:b5ea16e69bfda0ac028c921b58de1a4aaf83d43934892977368579cd3c0a2554 \ + --hash=sha256:ce59bcd2cda9bb52b0e90cc7f36413cd86c3d0ce7224143447424aafb9f4aa48 \ + --hash=sha256:de1665eaafefa48a308e4753786519888021740501a15461c77bdfd57638e6b4 \ + --hash=sha256:eba6ca45500ca1a042466a0684aacc9838e7f20fe2605521ee19f2853062798f \ + --hash=sha256:f2806f75817392cedcacb24ac5d80b0350dde8d3861d67d045c1d9b109764114 \ + --hash=sha256:f4cd800704a5fc57e53c39c3a6b0c9b1519ebdbcb644ede3ee67a06eb542697d \ + --hash=sha256:f713af9b8aa66a34cd3a78c7d150a560a75734713abe818a69021fd269e927fa +markdown-it-py==3.0.0 \ + --hash=sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1 \ + --hash=sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb +markupsafe==3.0.2 \ + --hash=sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30 \ + --hash=sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9 \ + --hash=sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396 \ + --hash=sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028 \ + --hash=sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557 \ + --hash=sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a \ + --hash=sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c \ + --hash=sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c \ + --hash=sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22 \ + --hash=sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094 \ + --hash=sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5 \ + --hash=sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225 \ + --hash=sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c \ + --hash=sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87 \ + --hash=sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf \ + --hash=sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb \ + --hash=sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48 \ + --hash=sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c \ + --hash=sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6 \ + --hash=sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd \ + --hash=sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1 \ + --hash=sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d \ + --hash=sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca \ + --hash=sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a \ + --hash=sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe \ + --hash=sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8 \ + --hash=sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f \ + --hash=sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f \ + --hash=sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0 \ + --hash=sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79 \ + --hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430 +matplotlib-inline==0.1.7 \ + --hash=sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90 \ + --hash=sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca +mdurl==0.1.2 \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ + --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba +mistune==3.1.0 \ + --hash=sha256:b05198cf6d671b3deba6c87ec6cf0d4eb7b72c524636eddb6dbf13823b52cee1 \ + --hash=sha256:dbcac2f78292b9dc066cd03b7a3a26b62d85f8159f2ea5fd28e55df79908d667 +model2vec==0.3.5 \ + --hash=sha256:437b13febcffac6d12ea50baa96f4e166f01e1dc487508d75a4a61e2774aa02e \ + --hash=sha256:f6596dc0660c4bffa492cbd8445b1925b6bda04c12b7c4cc825d195325322748 +msal==1.31.1 \ + --hash=sha256:11b5e6a3f802ffd3a72107203e20c4eac6ef53401961b880af2835b723d80578 \ + --hash=sha256:29d9882de247e96db01386496d59f29035e5e841bcac892e6d7bf4390bf6bd17 +msal-extensions==1.2.0 \ + --hash=sha256:6f41b320bfd2933d631a215c91ca0dd3e67d84bd1a2f50ce917d5874ec646bef \ + --hash=sha256:cf5ba83a2113fa6dc011a254a72f1c223c88d7dfad74cc30617c4679a417704d +msrest==0.7.1 \ + --hash=sha256:21120a810e1233e5e6cc7fe40b474eeb4ec6f757a15d7cf86702c369f9567c32 \ + --hash=sha256:6e7661f46f3afd88b75667b7187a92829924446c7ea1d169be8c4bb7eeb788b9 +multidict==6.1.0 \ + --hash=sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f \ + --hash=sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761 \ + --hash=sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3 \ + --hash=sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6 \ + --hash=sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966 \ + --hash=sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1 \ + --hash=sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305 \ + --hash=sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a \ + --hash=sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c \ + --hash=sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4 \ + --hash=sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81 \ + --hash=sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3 \ + --hash=sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506 \ + --hash=sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925 \ + --hash=sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6 \ + --hash=sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e \ + --hash=sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95 \ + --hash=sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2 \ + --hash=sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133 \ + --hash=sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa \ + --hash=sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3 \ + --hash=sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436 \ + --hash=sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2 \ + --hash=sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2 \ + --hash=sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa \ + --hash=sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b \ + --hash=sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa \ + --hash=sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef \ + --hash=sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44 \ + --hash=sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008 \ + --hash=sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774 \ + --hash=sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28 +murmurhash==1.0.11 \ + --hash=sha256:036aea55d160d65698888a903fd2a19c4258be711f7bf2ab1b6cebdf41e09e09 \ + --hash=sha256:0b507dd8ea10f3e5204b397ea9917a3a5f11756859d91406a8f485f18a411bdf \ + --hash=sha256:185b2cd20b81fa876eaa2249faafd0b7b3d0c54ef04714e38135d9f482cf6ce9 \ + --hash=sha256:24aba80a793bf371de70fffffc1f16c06810e4d8b90125b5bb762aabda3174d1 \ + --hash=sha256:49a3cf4d26f7213d0f4a6c2c49496cbe9f78b30d56b1c3b17fbc74676372ea3f \ + --hash=sha256:61f4b991b5bd88f5d57550a6328f8adb2f16656781e9eade9c16e55b41f6fab7 \ + --hash=sha256:87ff68a255e54e7648d0729ff4130f43f7f38f03288a376e567934e16db93767 \ + --hash=sha256:a1bdb3c3fe32d93f7c461f11e6b2f7bbe64b3d70f56e48052490435853ed5c91 \ + --hash=sha256:b26cf1be87c13fb242b9c252f11a25da71056c8fb5f22623e455129cce99592a \ + --hash=sha256:b5527ec305236a2ef404a38e0e57b1dc886a431e2032acf4c7ce3b17382c49ef \ + --hash=sha256:fd3083c6d977c2bc1e2f35ff999c39de43de09fd588f780243ec78debb316406 +mypy-extensions==1.0.0 \ + --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \ + --hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782 +nbclient==0.10.2 \ + --hash=sha256:4ffee11e788b4a27fabeb7955547e4318a5298f34342a4bfd01f2e1faaeadc3d \ + --hash=sha256:90b7fc6b810630db87a6d0c2250b1f0ab4cf4d3c27a299b0cde78a4ed3fd9193 +nbconvert==7.16.5 \ + --hash=sha256:c83467bb5777fdfaac5ebbb8e864f300b277f68692ecc04d6dab72f2d8442344 \ + --hash=sha256:e12eac052d6fd03040af4166c563d76e7aeead2e9aadf5356db552a1784bd547 +nbformat==5.10.4 \ + --hash=sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a \ + --hash=sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b +nest-asyncio==1.6.0 \ + --hash=sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe \ + --hash=sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c +nodeenv==1.9.1 \ + --hash=sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f \ + --hash=sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9 +notebook==7.3.2 \ + --hash=sha256:705e83a1785f45b383bf3ee13cb76680b92d24f56fb0c7d2136fe1d850cd3ca8 \ + --hash=sha256:e5f85fc59b69d3618d73cf27544418193ff8e8058d5bf61d315ce4f473556288 +notebook-shim==0.2.4 \ + --hash=sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef \ + --hash=sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb +numpy==1.26.4 \ + --hash=sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b \ + --hash=sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818 \ + --hash=sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0 \ + --hash=sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010 \ + --hash=sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110 \ + --hash=sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed \ + --hash=sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b \ + --hash=sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a \ + --hash=sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218 +oauthlib==3.2.2 \ + --hash=sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca \ + --hash=sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918 +openai==1.59.7 \ + --hash=sha256:043603def78c00befb857df9f0a16ee76a3af5984ba40cb7ee5e2f40db4646bf \ + --hash=sha256:cfa806556226fa96df7380ab2e29814181d56fea44738c2b0e581b462c268692 +openpyxl==3.1.5 \ + --hash=sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2 \ + --hash=sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050 +overrides==7.7.0 \ + --hash=sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a \ + --hash=sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49 +packaging==24.2 \ + --hash=sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759 \ + --hash=sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f +pandas==2.2.3 \ + --hash=sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a \ + --hash=sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d \ + --hash=sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4 \ + --hash=sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0 \ + --hash=sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28 \ + --hash=sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18 \ + --hash=sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468 \ + --hash=sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667 \ + --hash=sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13 \ + --hash=sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3 \ + --hash=sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d \ + --hash=sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb \ + --hash=sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8 \ + --hash=sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659 \ + --hash=sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4 \ + --hash=sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a \ + --hash=sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9 \ + --hash=sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2 \ + --hash=sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015 \ + --hash=sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24 \ + --hash=sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319 +pandocfilters==1.5.1 \ + --hash=sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e \ + --hash=sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc +parso==0.8.4 \ + --hash=sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18 \ + --hash=sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d +pathspec==0.12.1 \ + --hash=sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08 \ + --hash=sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712 +pexpect==4.9.0 ; sys_platform != 'emscripten' and sys_platform != 'win32' \ + --hash=sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523 \ + --hash=sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f +pillow==11.1.0 \ + --hash=sha256:11633d58b6ee5733bde153a8dafd25e505ea3d32e261accd388827ee987baf65 \ + --hash=sha256:2062ffb1d36544d42fcaa277b069c88b01bb7298f4efa06731a7fd6cc290b81a \ + --hash=sha256:31eba6bbdd27dde97b0174ddf0297d7a9c3a507a8a1480e1e60ef914fe23d352 \ + --hash=sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20 \ + --hash=sha256:36ba10b9cb413e7c7dfa3e189aba252deee0602c86c309799da5a74009ac7a1c \ + --hash=sha256:3764d53e09cdedd91bee65c2527815d315c6b90d7b8b79759cc48d7bf5d4f114 \ + --hash=sha256:3cdcdb0b896e981678eee140d882b70092dac83ac1cdf6b3a60e2216a73f2b91 \ + --hash=sha256:4dd43a78897793f60766563969442020e90eb7847463eca901e41ba186a7d4a5 \ + --hash=sha256:593c5fd6be85da83656b93ffcccc2312d2d149d251e98588b14fbc288fd8909c \ + --hash=sha256:67cd427c68926108778a9005f2a04adbd5e67c442ed21d95389fe1d595458756 \ + --hash=sha256:70ca5ef3b3b1c4a0812b5c63c57c23b63e53bc38e758b37a951e5bc466449861 \ + --hash=sha256:758e9d4ef15d3560214cddbc97b8ef3ef86ce04d62ddac17ad39ba87e89bd3b1 \ + --hash=sha256:7fdadc077553621911f27ce206ffcbec7d3f8d7b50e0da39f10997e8e2bb7f6a \ + --hash=sha256:8000376f139d4d38d6851eb149b321a52bb8893a88dae8ee7d95840431977081 \ + --hash=sha256:9044b5e4f7083f209c4e35aa5dd54b1dd5b112b108648f5c902ad586d4f945c5 \ + --hash=sha256:93a18841d09bcdd774dcdc308e4537e1f867b3dec059c131fde0327899734aa1 \ + --hash=sha256:9409c080586d1f683df3f184f20e36fb647f2e0bc3988094d4fd8c9f4eb1b3b3 \ + --hash=sha256:9aa9aeddeed452b2f616ff5507459e7bab436916ccb10961c4a382cd3e03f47f \ + --hash=sha256:9ee85f0696a17dd28fbcfceb59f9510aa71934b483d1f5601d1030c3c8304f3c \ + --hash=sha256:a697cd8ba0383bba3d2d3ada02b34ed268cb548b369943cd349007730c92bddf \ + --hash=sha256:a85b653980faad27e88b141348707ceeef8a1186f75ecc600c395dcac19f385b \ + --hash=sha256:ad5db5781c774ab9a9b2c4302bbf0c1014960a0a7be63278d13ae6fdf88126fe \ + --hash=sha256:ae98e14432d458fc3de11a77ccb3ae65ddce70f730e7c76140653048c71bfcbc \ + --hash=sha256:b523466b1a31d0dcef7c5be1f20b942919b62fd6e9a9be199d035509cbefc0ec \ + --hash=sha256:b5d658fbd9f0d6eea113aea286b21d3cd4d3fd978157cbf2447a6035916506d3 \ + --hash=sha256:cc1331b6d5a6e144aeb5e626f4375f5b7ae9934ba620c0ac6b3e43d5e683a0f0 \ + --hash=sha256:cfd5cd998c2e36a862d0e27b2df63237e67273f2fc78f47445b14e73a810e7e6 \ + --hash=sha256:dd0e081319328928531df7a0e63621caf67652c8464303fd102141b785ef9547 \ + --hash=sha256:dda60aa465b861324e65a78c9f5cf0f4bc713e4309f83bc387be158b077963d9 \ + --hash=sha256:e63e4e5081de46517099dc30abe418122f54531a6ae2ebc8680bcd7096860eab \ + --hash=sha256:f86d3a7a9af5d826744fabf4afd15b9dfef44fe69a98541f666f66fbb8d3fef9 +platformdirs==4.3.6 \ + --hash=sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907 \ + --hash=sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb +portalocker==2.10.1 \ + --hash=sha256:53a5984ebc86a025552264b459b46a2086e269b21823cb572f8f28ee759e45bf \ + --hash=sha256:ef1bf844e878ab08aee7e40184156e1151f228f103aa5c6bd0724cc330960f8f +pre-commit==4.0.1 \ + --hash=sha256:80905ac375958c0444c65e9cebebd948b3cdb518f335a091a670a89d652139d2 \ + --hash=sha256:efde913840816312445dc98787724647c65473daefe420785f885e8ed9a06878 +preshed==3.0.9 \ + --hash=sha256:24229c77364628743bc29c5620c5d6607ed104f0e02ae31f8a030f99a78a5ceb \ + --hash=sha256:4a55091d0e395f1fdb62ab43401bb9f8b46c7d7794d5b071813c29dc1ab22fd0 \ + --hash=sha256:721863c5244ffcd2651ad0928951a2c7c77b102f4e11a251ad85d37ee7621660 \ + --hash=sha256:7de8f5138bcac7870424e09684dc3dd33c8e30e81b269f6c9ede3d8c7bb8e257 \ + --hash=sha256:b4fe6720012c62e6d550d6a5c1c7ad88cacef8388d186dad4bafea4140d9d198 \ + --hash=sha256:e04f05758875be9751e483bd3c519c22b00d3b07f5a64441ec328bb9e3c03700 +prometheus-client==0.21.1 \ + --hash=sha256:252505a722ac04b0456be05c05f75f45d760c2911ffc45f2a06bcaed9f3ae3fb \ + --hash=sha256:594b45c410d6f4f8888940fe80b5cc2521b305a1fafe1c58609ef715a001f301 +prompt-toolkit==3.0.48 \ + --hash=sha256:d6623ab0477a80df74e646bdbc93621143f5caf104206aa29294d53de1a03d90 \ + --hash=sha256:f49a827f90062e411f1ce1f854f2aedb3c23353244f8108b89283587397ac10e +propcache==0.2.1 \ + --hash=sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4 \ + --hash=sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a \ + --hash=sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f \ + --hash=sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9 \ + --hash=sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d \ + --hash=sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6 \ + --hash=sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d \ + --hash=sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30 \ + --hash=sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95 \ + --hash=sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348 \ + --hash=sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64 \ + --hash=sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce \ + --hash=sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629 \ + --hash=sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54 \ + --hash=sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1 \ + --hash=sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf \ + --hash=sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b \ + --hash=sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24 \ + --hash=sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5 \ + --hash=sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc \ + --hash=sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce \ + --hash=sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518 \ + --hash=sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536 \ + --hash=sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052 \ + --hash=sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff \ + --hash=sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1 \ + --hash=sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246 \ + --hash=sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0 \ + --hash=sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f \ + --hash=sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439 \ + --hash=sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6 \ + --hash=sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec \ + --hash=sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d \ + --hash=sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6 +psutil==6.1.1 \ + --hash=sha256:0bdd4eab935276290ad3cb718e9809412895ca6b5b334f5a9111ee6d9aff9377 \ + --hash=sha256:33431e84fee02bc84ea36d9e2c4a6d395d479c9dd9bba2376c1f6ee8f3a4e0b3 \ + --hash=sha256:97f7cb9921fbec4904f522d972f0c0e1f4fabbdd4e0287813b21215074a0f160 \ + --hash=sha256:b6e06c20c05fe95a3d7302d74e7097756d4ba1247975ad6905441ae1b5b66003 \ + --hash=sha256:cf8496728c18f2d0b45198f06895be52f36611711746b7f30c464b422b50e2f5 \ + --hash=sha256:eaa912e0b11848c4d9279a93d7e2783df352b082f40111e078388701fd479e53 \ + --hash=sha256:f35cfccb065fff93529d2afb4a2e89e363fe63ca1e4a5da22b603a85833c2649 \ + --hash=sha256:fc0ed7fe2231a444fc219b9c42d0376e0a9a1a72f16c5cfa0f68d19f1a0663e8 +ptyprocess==0.7.0 ; os_name != 'nt' or (sys_platform != 'emscripten' and sys_platform != 'win32') \ + --hash=sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35 \ + --hash=sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220 +pure-eval==0.2.3 \ + --hash=sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0 \ + --hash=sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42 +pycparser==2.22 \ + --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ + --hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc +pydantic==2.10.5 \ + --hash=sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff \ + --hash=sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53 +pydantic-core==2.27.2 \ + --hash=sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6 \ + --hash=sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7 \ + --hash=sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee \ + --hash=sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc \ + --hash=sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130 \ + --hash=sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4 \ + --hash=sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4 \ + --hash=sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b \ + --hash=sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934 \ + --hash=sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2 \ + --hash=sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9 \ + --hash=sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27 \ + --hash=sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b \ + --hash=sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154 \ + --hash=sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef \ + --hash=sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4 \ + --hash=sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee \ + --hash=sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c \ + --hash=sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0 \ + --hash=sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57 \ + --hash=sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b \ + --hash=sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1 \ + --hash=sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e \ + --hash=sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9 \ + --hash=sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1 \ + --hash=sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3 \ + --hash=sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39 \ + --hash=sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a \ + --hash=sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9 +pygments==2.19.1 \ + --hash=sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f \ + --hash=sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c +pyjwt==2.10.1 \ + --hash=sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953 \ + --hash=sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb +pymupdf==1.25.1 \ + --hash=sha256:15e6f4013ad0a029a2221920f9d2081f56dc43259dabfdf5cad7fbf1cee4b5a7 \ + --hash=sha256:6725bec0f37c2380d926f792c262693c926af7cc1aa5aa2b8207e771867f015a \ + --hash=sha256:793f9f6d51029e97851c711b3f6d9fe912313d95a306fbe8b1866f301d0e2bd3 \ + --hash=sha256:a39afbd80381f43e30d6eb2ec4613f465f507ac2b76070abdd2da8724f32ef36 \ + --hash=sha256:a687bd387589e30abd810a78a23341f57f43fa16a4d8d8c0b870bb6d89607343 \ + --hash=sha256:b63f8e9e65b0bda48f9217efd4d2a8c6d7a739dd28baf460c1ae78439b9af489 \ + --hash=sha256:e2b0b73c0aab0f863e5132c93cfa4607e8129feb1afa3d544b2cf7f172c50b5a \ + --hash=sha256:fc7dbc1aa9e298a4c81084e389c9623c26fcaa232c71efaa073af150069e2221 +python-dateutil==2.9.0.post0 \ + --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ + --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 +python-dotenv==1.0.1 \ + --hash=sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca \ + --hash=sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a +python-json-logger==3.2.1 \ + --hash=sha256:8eb0554ea17cb75b05d2848bc14fb02fbdbd9d6972120781b974380bfa162008 \ + --hash=sha256:cdc17047eb5374bd311e748b42f99d71223f3b0e186f4206cc5d52aefe85b090 +pytz==2024.2 \ + --hash=sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a \ + --hash=sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725 +pywin32==308 ; sys_platform == 'win32' \ + --hash=sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47 \ + --hash=sha256:1c44539a37a5b7b21d02ab34e6a4d314e0788f1690d65b48e9b0b89f31abbbed \ + --hash=sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897 \ + --hash=sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091 \ + --hash=sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd \ + --hash=sha256:fd380990e792eaf6827fcb7e187b2b4b1cede0585e3d0c9e84201ec27b9905e4 +pywinpty==2.0.14 ; os_name == 'nt' \ + --hash=sha256:074fb988a56ec79ca90ed03a896d40707131897cefb8f76f926e3834227f2819 \ + --hash=sha256:18bd9529e4a5daf2d9719aa17788ba6013e594ae94c5a0c27e83df3278b0660e \ + --hash=sha256:55dad362ef3e9408ade68fd173e4f9032b3ce08f68cfe7eacb2c263ea1179737 +pyyaml==6.0.2 \ + --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \ + --hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \ + --hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \ + --hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \ + --hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \ + --hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \ + --hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \ + --hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \ + --hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \ + --hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \ + --hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \ + --hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \ + --hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \ + --hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \ + --hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \ + --hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \ + --hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \ + --hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \ + --hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba +pyzmq==26.2.0 \ + --hash=sha256:007137c9ac9ad5ea21e6ad97d3489af654381324d5d3ba614c323f60dab8fae6 \ + --hash=sha256:034da5fc55d9f8da09015d368f519478a52675e558c989bfcb5cf6d4e16a7d2a \ + --hash=sha256:070672c258581c8e4f640b5159297580a9974b026043bd4ab0470be9ed324f1f \ + --hash=sha256:17bf5a931c7f6618023cdacc7081f3f266aecb68ca692adac015c383a134ca52 \ + --hash=sha256:23f4aad749d13698f3f7b64aad34f5fc02d6f20f05999eebc96b89b01262fb18 \ + --hash=sha256:25bf2374a2a8433633c65ccb9553350d5e17e60c8eb4de4d92cc6bd60f01d306 \ + --hash=sha256:28c812d9757fe8acecc910c9ac9dafd2ce968c00f9e619db09e9f8f54c3a68a3 \ + --hash=sha256:29c6a4635eef69d68a00321e12a7d2559fe2dfccfa8efae3ffb8e91cd0b36a8b \ + --hash=sha256:2a50625acdc7801bc6f74698c5c583a491c61d73c6b7ea4dee3901bb99adb27a \ + --hash=sha256:2ae90ff9dad33a1cfe947d2c40cb9cb5e600d759ac4f0fd22616ce6540f72797 \ + --hash=sha256:31507f7b47cc1ead1f6e86927f8ebb196a0bab043f6345ce070f412a59bf87b5 \ + --hash=sha256:43a47408ac52647dfabbc66a25b05b6a61700b5165807e3fbd40063fcaf46386 \ + --hash=sha256:4661c88db4a9e0f958c8abc2b97472e23061f0bc737f6f6179d7a27024e1faa5 \ + --hash=sha256:470d4a4f6d48fb34e92d768b4e8a5cc3780db0d69107abf1cd7ff734b9766eb0 \ + --hash=sha256:4d29ab8592b6ad12ebbf92ac2ed2bedcfd1cec192d8e559e2e099f648570e19b \ + --hash=sha256:4d80b1dd99c1942f74ed608ddb38b181b87476c6a966a88a950c7dee118fdf50 \ + --hash=sha256:55cf66647e49d4621a7e20c8d13511ef1fe1efbbccf670811864452487007e08 \ + --hash=sha256:6b274e0762c33c7471f1a7471d1a2085b1a35eba5cdc48d2ae319f28b6fc4de3 \ + --hash=sha256:70fc7fcf0410d16ebdda9b26cbd8bf8d803d220a7f3522e060a69a9c87bf7bad \ + --hash=sha256:794a4562dcb374f7dbbfb3f51d28fb40123b5a2abadee7b4091f93054909add5 \ + --hash=sha256:7ad1bc8d1b7a18497dda9600b12dc193c577beb391beae5cd2349184db40f187 \ + --hash=sha256:7f98f6dfa8b8ccaf39163ce872bddacca38f6a67289116c8937a02e30bbe9711 \ + --hash=sha256:8c997098cc65e3208eca09303630e84d42718620e83b733d0fd69543a9cab9cb \ + --hash=sha256:989d842dc06dc59feea09e58c74ca3e1678c812a4a8a2a419046d711031f69c7 \ + --hash=sha256:9dd8cd1aeb00775f527ec60022004d030ddc51d783d056e3e23e74e623e33726 \ + --hash=sha256:a4f96f0d88accc3dbe4a9025f785ba830f968e21e3e2c6321ccdfc9aef755115 \ + --hash=sha256:aee22939bb6075e7afededabad1a56a905da0b3c4e3e0c45e75810ebe3a52672 \ + --hash=sha256:bea2acdd8ea4275e1278350ced63da0b166421928276c7c8e3f9729d7402a57b \ + --hash=sha256:c3789bd5768ab5618ebf09cef6ec2b35fed88709b104351748a63045f0ff9797 \ + --hash=sha256:c92d73464b886931308ccc45b2744e5968cbaade0b1d6aeb40d8ab537765f5bc \ + --hash=sha256:ced65e5a985398827cc9276b93ef6dfabe0273c23de8c7931339d7e141c2818e \ + --hash=sha256:ded0fc7d90fe93ae0b18059930086c51e640cdd3baebdc783a695c77f123dcd9 \ + --hash=sha256:e3e0210287329272539eea617830a6a28161fbbd8a3271bf4150ae3e58c5d0e6 \ + --hash=sha256:ea7f69de383cb47522c9c208aec6dd17697db7875a4674c4af3f8cfdac0bdeae +referencing==0.35.1 \ + --hash=sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c \ + --hash=sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de +regex==2024.11.6 \ + --hash=sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0 \ + --hash=sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad \ + --hash=sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe \ + --hash=sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3 \ + --hash=sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4 \ + --hash=sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39 \ + --hash=sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7 \ + --hash=sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a \ + --hash=sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54 \ + --hash=sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c \ + --hash=sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d \ + --hash=sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4 \ + --hash=sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a \ + --hash=sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07 \ + --hash=sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff \ + --hash=sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e \ + --hash=sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519 \ + --hash=sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2 \ + --hash=sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e \ + --hash=sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84 \ + --hash=sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29 \ + --hash=sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b \ + --hash=sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3 \ + --hash=sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7 \ + --hash=sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4 \ + --hash=sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e \ + --hash=sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577 \ + --hash=sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0 \ + --hash=sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51 \ + --hash=sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6 \ + --hash=sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9 +requests==2.32.3 \ + --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \ + --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6 +requests-oauthlib==2.0.0 \ + --hash=sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36 \ + --hash=sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9 +rfc3339-validator==0.1.4 \ + --hash=sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b \ + --hash=sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa +rfc3986-validator==0.1.1 \ + --hash=sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9 \ + --hash=sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055 +rich==13.9.4 \ + --hash=sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098 \ + --hash=sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90 +rpds-py==0.22.3 \ + --hash=sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518 \ + --hash=sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059 \ + --hash=sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61 \ + --hash=sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5 \ + --hash=sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56 \ + --hash=sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd \ + --hash=sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b \ + --hash=sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4 \ + --hash=sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d \ + --hash=sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1 \ + --hash=sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e \ + --hash=sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc \ + --hash=sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38 \ + --hash=sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b \ + --hash=sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c \ + --hash=sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83 \ + --hash=sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1 \ + --hash=sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627 \ + --hash=sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16 \ + --hash=sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45 \ + --hash=sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730 \ + --hash=sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25 \ + --hash=sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7 \ + --hash=sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f \ + --hash=sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd \ + --hash=sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333 \ + --hash=sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9 \ + --hash=sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4 \ + --hash=sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d \ + --hash=sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15 \ + --hash=sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84 \ + --hash=sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e \ + --hash=sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf \ + --hash=sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b \ + --hash=sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2 \ + --hash=sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3 \ + --hash=sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130 \ + --hash=sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b \ + --hash=sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de \ + --hash=sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e +ruff==0.9.1 \ + --hash=sha256:186c2313de946f2c22bdf5954b8dd083e124bcfb685732cfb0beae0c47233d9b \ + --hash=sha256:1cd76c7f9c679e6e8f2af8f778367dca82b95009bc7b1a85a47f1521ae524fa7 \ + --hash=sha256:2f312c86fb40c5c02b44a29a750ee3b21002bd813b5233facdaf63a51d9a85e1 \ + --hash=sha256:342a824b46ddbcdddd3abfbb332fa7fcaac5488bf18073e841236aadf4ad5c19 \ + --hash=sha256:39d0174ccc45c439093971cc06ed3ac4dc545f5e8bdacf9f067adf879544d969 \ + --hash=sha256:3cae39ba5d137054b0e5b472aee3b78a7c884e61591b100aeb544bcd1fc38d4f \ + --hash=sha256:3f94942a3bb767675d9a051867c036655fe9f6c8a491539156a6f7e6b5f31831 \ + --hash=sha256:46ebf5cc106cf7e7378ca3c28ce4293b61b449cd121b98699be727d40b79ba72 \ + --hash=sha256:50c647ff96f4ba288db0ad87048257753733763b409b2faf2ea78b45c8bb7fcb \ + --hash=sha256:5dc40a378a0e21b4cfe2b8a0f1812a6572fc7b230ef12cd9fac9161aa91d807f \ + --hash=sha256:69572926c0f0c9912288915214ca9b2809525ea263603370b9e00bed2ba56dbd \ + --hash=sha256:728d791b769cc28c05f12c280f99e8896932e9833fef1dd8756a6af2261fd1ab \ + --hash=sha256:84330dda7abcc270e6055551aca93fdde1b0685fc4fd358f26410f9349cf1743 \ + --hash=sha256:937267afce0c9170d6d29f01fcd1f4378172dec6760a9f4dface48cdabf9610a \ + --hash=sha256:ae017c3a29bee341ba584f3823f805abbe5fe9cd97f87ed07ecbf533c4c88366 \ + --hash=sha256:beb3298604540c884d8b282fe7625651378e1986c25df51dec5b2f60cafc31ce \ + --hash=sha256:f0c8b149e9c7353cace7d698e1656ffcf1e36e50f8ea3b5d5f7f87ff9986a7ca \ + --hash=sha256:fd2b25ecaf907d6458fa842675382c8597b3c746a2dde6717fe3415425df0c17 +safetensors==0.5.2 \ + --hash=sha256:03c937100f38c9ff4c1507abea9928a6a9b02c9c1c9c3609ed4fb2bf413d4975 \ + --hash=sha256:1506e4c2eda1431099cebe9abf6c76853e95d0b7a95addceaa74c6019c65d8cf \ + --hash=sha256:3ab696dfdc060caffb61dbe4066b86419107a24c804a4e373ba59be699ebd8d5 \ + --hash=sha256:3dfa7c2f3fe55db34eba90c29df94bcdac4821043fc391cb5d082d9922013869 \ + --hash=sha256:45b6092997ceb8aa3801693781a71a99909ab9cc776fbc3fa9322d29b1d3bef2 \ + --hash=sha256:46ff2116150ae70a4e9c490d2ab6b6e1b1b93f25e520e540abe1b81b48560c3a \ + --hash=sha256:5c5b5d9da594f638a259fca766046f44c97244cc7ab8bef161b3e80d04becc76 \ + --hash=sha256:6d0d6a8ee2215a440e1296b843edf44fd377b055ba350eaba74655a2fe2c4bae \ + --hash=sha256:78abdddd03a406646107f973c7843276e7b64e5e32623529dc17f3d94a20f589 \ + --hash=sha256:86016d40bcaa3bcc9a56cd74d97e654b5f4f4abe42b038c71e4f00a089c4526c \ + --hash=sha256:990833f70a5f9c7d3fc82c94507f03179930ff7d00941c287f73b6fcbf67f19e \ + --hash=sha256:a00e737948791b94dad83cf0eafc09a02c4d8c2171a239e8c8572fe04e25960e \ + --hash=sha256:cb4a8d98ba12fa016f4241932b1fc5e702e5143f5374bba0bbcf7ddc1c4cf2b8 \ + --hash=sha256:d3a06fae62418ec8e5c635b61a8086032c9e281f16c63c3af46a6efbab33156f \ + --hash=sha256:fe55c039d97090d1f85277d402954dd6ad27f63034fa81985a9cc59655ac3ee2 +send2trash==1.8.3 \ + --hash=sha256:0c31227e0bd08961c7665474a3d1ef7193929fedda4233843689baa056be46c9 \ + --hash=sha256:b18e7a3966d99871aefeb00cfbcfdced55ce4871194810fc71f4aa484b953abf +setuptools==75.8.0 \ + --hash=sha256:c5afc8f407c626b8313a86e10311dd3f661c6cd9c09d4bf8c15c0e11f9f2b0e6 \ + --hash=sha256:e3982f444617239225d675215d51f6ba05f845d4eec313da4418fdbb56fb27e3 +shellingham==1.5.4 \ + --hash=sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686 \ + --hash=sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de +six==1.17.0 \ + --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ + --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81 +smart-open==7.1.0 \ + --hash=sha256:4b8489bb6058196258bafe901730c7db0dcf4f083f316e97269c66f45502055b \ + --hash=sha256:a4f09f84f0f6d3637c6543aca7b5487438877a21360e7368ccf1f704789752ba +sniffio==1.3.1 \ + --hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \ + --hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc +soupsieve==2.6 \ + --hash=sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb \ + --hash=sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9 +spacy==3.7.5 \ + --hash=sha256:07677e270a6d729453cc04b5e2247a96a86320b8845e6428d9f90f217eff0f56 \ + --hash=sha256:262f8ebb71f7ed5ffe8e4f384b2594b7a296be50241ce9fbd9277b5da2f46f38 \ + --hash=sha256:4145cea7f9814fa7d86b2028c2dd83e02f13f80d5ac604a400b2f7d7b26a0e8c \ + --hash=sha256:a648c6cbf2acc7a55a69ee9e7fa4f22bdf69aa828a587a1bc5cfff08cf3c2dd3 \ + --hash=sha256:bf54c3c2425428b328b53a65913d47eb4cb27a1429aa4e8ed979ffc97d4663e0 \ + --hash=sha256:faa1e2b6234ae33c0b1f8dfa5a8dcb66fb891f19231725dfcff4b2666125c250 +spacy-legacy==3.0.12 \ + --hash=sha256:476e3bd0d05f8c339ed60f40986c07387c0a71479245d6d0f4298dbd52cda55f \ + --hash=sha256:b37d6e0c9b6e1d7ca1cf5bc7152ab64a4c4671f59c85adaf7a3fcb870357a774 +spacy-loggers==1.0.5 \ + --hash=sha256:196284c9c446cc0cdb944005384270d775fdeaf4f494d8e269466cfa497ef645 \ + --hash=sha256:d60b0bdbf915a60e516cc2e653baeff946f0cfc461b452d11a4d5458c6fe5f24 +srsly==2.5.0 \ + --hash=sha256:1d7fb3fd694eec2328b42ab0767193aa5561bb20cc50bf34da6cb213edf30c25 \ + --hash=sha256:2776752cdb14275ca01e9a7b7a9c047ccf31db17f0076e73343cfcc9a8df6cbd \ + --hash=sha256:2a657d8c1486d47910868cfadd5a80cd77719c6228fed5b01b878329b95f0752 \ + --hash=sha256:35fa3aadfc0d983e80fc5e0319825e91f792d13b414c1aff20cbbb47569d5109 \ + --hash=sha256:3fac84c8fbda019e3f3652854ab3c8bd439af5b57825745fa3c67a603a13a05d \ + --hash=sha256:40932a850b10562eb739163ff7644a6b0804fde1fe5b1f9724198e81cb09c704 \ + --hash=sha256:5d2762e17ad61eea776428652d36da805b8d72c396d2651621ef59513bbcd504 \ + --hash=sha256:72e84cd4772f3d2a855e67cdfd293f9fd40d4939ff54e530dd32c4157b46b463 \ + --hash=sha256:767c902ccb16635af88fc98b10f998aa67180c343da41c34aa20679c6eb6618e \ + --hash=sha256:9f4430fab1bd62fea7b23ad2bd7822bf80cdd4a75c7d051a555c69aa10f4bfdc \ + --hash=sha256:e1f672e879b4ada0fb5b27401f36ad246ab3046183983961e49de1e8679cc3f5 +stack-data==0.6.3 \ + --hash=sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9 \ + --hash=sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695 +tenacity==9.0.0 \ + --hash=sha256:807f37ca97d62aa361264d497b0e31e92b8027044942bfa756160d908320d73b \ + --hash=sha256:93de0c98785b27fcf659856aa9f54bfbd399e29969b0621bc7f762bd441b4539 +terminado==0.18.1 \ + --hash=sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0 \ + --hash=sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e +thinc==8.2.5 \ + --hash=sha256:87e729f33c76ec6df9b375989743252ab880d79f3a2b4175169b21dece90f102 \ + --hash=sha256:8e299d4dc41107385d6d14d8604a060825798a031cabe2b894b22f9d75d9eaad \ + --hash=sha256:9fc26697e2358c71a5fe243d52e98ae67ee1a3b314eead5031845b6d1c0d121c \ + --hash=sha256:c2963791c934cc7fbd8f9b942d571cac79892ad11630bfca690a868c32752b75 \ + --hash=sha256:c5f750ea2dd32ca6d46947025dacfc0f6037340c4e5f7adb9af84c75f65aa7d8 \ + --hash=sha256:e8a8f2f249f2be9a5ce2a81a6efe7503b68be7b57e47ad54ab28204e1f0c723b +tiktoken==0.8.0 \ + --hash=sha256:02be1666096aff7da6cbd7cdaa8e7917bfed3467cd64b38b1f112e96d3b06a24 \ + --hash=sha256:18228d624807d66c87acd8f25fc135665617cab220671eb65b50f5d70fa51f69 \ + --hash=sha256:294440d21a2a51e12d4238e68a5972095534fe9878be57d905c476017bff99fc \ + --hash=sha256:4177faa809bd55f699e88c96d9bb4635d22e3f59d635ba6fd9ffedf7150b9953 \ + --hash=sha256:5376b6f8dc4753cd81ead935c5f518fa0fbe7e133d9e25f648d8c4dabdd4bad7 \ + --hash=sha256:6b231f5e8982c245ee3065cd84a4712d64692348bc609d84467c57b4b72dcbc5 \ + --hash=sha256:881839cfeae051b3628d9823b2e56b5cc93a9e2efb435f4cf15f17dc45f21586 \ + --hash=sha256:9a58deb7075d5b69237a3ff4bb51a726670419db6ea62bdcd8bd80c78497d7ab \ + --hash=sha256:9ccbb2740f24542534369c5635cfd9b2b3c2490754a78ac8831d99f89f94eeb2 \ + --hash=sha256:c94ff53c5c74b535b2cbf431d907fc13c678bbd009ee633a2aca269a04389f9a \ + --hash=sha256:d2908c0d043a7d03ebd80347266b0e58440bdef5564f84f4d29fb235b5df3b04 \ + --hash=sha256:d8f3192733ac4d77977432947d563d7e1b310b96497acd3c196c9bddb36ed9db \ + --hash=sha256:fe9399bdc3f29d428f16a2f86c3c8ec20be3eac5f53693ce4980371c3245729b +tinycss2==1.4.0 \ + --hash=sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7 \ + --hash=sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289 +tokenizers==0.21.0 \ + --hash=sha256:089d56db6782a73a27fd8abf3ba21779f5b85d4a9f35e3b493c7bbcbbf0d539b \ + --hash=sha256:3c4c93eae637e7d2aaae3d376f06085164e1660f89304c0ab2b1d08a406636b2 \ + --hash=sha256:400832c0904f77ce87c40f1a8a27493071282f785724ae62144324f171377273 \ + --hash=sha256:4145505a973116f91bc3ac45988a92e618a6f83eb458f49ea0790df94ee243ff \ + --hash=sha256:6b177fb54c4702ef611de0c069d9169f0004233890e0c4c5bd5508ae05abf193 \ + --hash=sha256:6b43779a269f4629bebb114e19c3fca0223296ae9fea8bb9a7a6c6fb0657ff8e \ + --hash=sha256:87841da5a25a3a5f70c102de371db120f41873b854ba65e52bccd57df5a3780c \ + --hash=sha256:9aeb255802be90acfd363626753fda0064a8df06031012fe7d52fd9a905eb00e \ + --hash=sha256:c87ca3dc48b9b1222d984b6b7490355a6fdb411a2d810f6f05977258400ddb74 \ + --hash=sha256:d8b09dbeb7a8d73ee204a70f94fc06ea0f17dcf0844f16102b9f414f0b7463ba \ + --hash=sha256:e84ca973b3a96894d1707e189c14a774b701596d579ffc7e69debfc036a61a04 \ + --hash=sha256:eb1702c2f27d25d9dd5b389cc1f2f51813e99f8ca30d9e25348db6585a97e24a \ + --hash=sha256:eb7202d231b273c34ec67767378cd04c767e967fda12d4a9e36208a34e2f137e \ + --hash=sha256:ee0894bf311b75b0c03079f33859ae4b2334d675d4e93f5a4132e1eae2834fe4 \ + --hash=sha256:f53ea537c925422a2e0e92a24cce96f6bc5046bbef24a1652a5edc8ba975f62e +tornado==6.4.2 \ + --hash=sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803 \ + --hash=sha256:1a017d239bd1bb0919f72af256a970624241f070496635784d9bf0db640d3fec \ + --hash=sha256:2876cef82e6c5978fde1e0d5b1f919d756968d5b4282418f3146b79b58556482 \ + --hash=sha256:304463bd0772442ff4d0f5149c6f1c2135a1fae045adf070821c6cdc76980634 \ + --hash=sha256:908b71bf3ff37d81073356a5fadcc660eb10c1476ee6e2725588626ce7e5ca38 \ + --hash=sha256:92bad5b4746e9879fd7bf1eb21dce4e3fc5128d71601f80005afa39237ad620b \ + --hash=sha256:932d195ca9015956fa502c6b56af9eb06106140d844a335590c1ec7f5277d10c \ + --hash=sha256:bca9eb02196e789c9cb5c3c7c0f04fb447dc2adffd95265b2c7223a8a615ccbf \ + --hash=sha256:c36e62ce8f63409301537222faffcef7dfc5284f27eec227389f2ad11b09d946 \ + --hash=sha256:c82c46813ba483a385ab2a99caeaedf92585a1f90defb5693351fa7e4ea0bf73 \ + --hash=sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1 +tqdm==4.67.1 \ + --hash=sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2 \ + --hash=sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2 +traitlets==5.14.3 \ + --hash=sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7 \ + --hash=sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f +typer==0.15.1 \ + --hash=sha256:7994fb7b8155b64d3402518560648446072864beefd44aa2dc36972a5972e847 \ + --hash=sha256:a0588c0a7fa68a1978a069818657778f86abe6ff5ea6abf472f940a08bfe4f0a +types-python-dateutil==2.9.0.20241206 \ + --hash=sha256:18f493414c26ffba692a72369fea7a154c502646301ebfe3d56a04b3767284cb \ + --hash=sha256:e248a4bc70a486d3e3ec84d0dc30eec3a5f979d6e7ee4123ae043eedbb987f53 +typing-extensions==4.12.2 \ + --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ + --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 +tzdata==2024.2 \ + --hash=sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc \ + --hash=sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd +uri-template==1.3.0 \ + --hash=sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7 \ + --hash=sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363 +urllib3==2.3.0 \ + --hash=sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df \ + --hash=sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d +virtualenv==20.28.1 \ + --hash=sha256:412773c85d4dab0409b83ec36f7a6499e72eaf08c80e81e9576bca61831c71cb \ + --hash=sha256:5d34ab240fdb5d21549b76f9e8ff3af28252f5499fb6d6f031adac4e5a8c5329 +wasabi==1.1.3 \ + --hash=sha256:4bb3008f003809db0c3e28b4daf20906ea871a2bb43f9914197d540f4f2e0878 \ + --hash=sha256:f76e16e8f7e79f8c4c8be49b4024ac725713ab10cd7f19350ad18a8e3f71728c +wcwidth==0.2.13 \ + --hash=sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859 \ + --hash=sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5 +weasel==0.4.1 \ + --hash=sha256:24140a090ea1ac512a2b2f479cc64192fd1d527a7f3627671268d08ed5ac418c \ + --hash=sha256:aabc210f072e13f6744e5c3a28037f93702433405cd35673f7c6279147085aa9 +webcolors==24.11.1 \ + --hash=sha256:515291393b4cdf0eb19c155749a096f779f7d909f7cceea072791cb9095b92e9 \ + --hash=sha256:ecb3d768f32202af770477b8b65f318fa4f566c22948673a977b00d589dd80f6 +webencodings==0.5.1 \ + --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ + --hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923 +websocket-client==1.8.0 \ + --hash=sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526 \ + --hash=sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da +widgetsnbextension==4.0.13 \ + --hash=sha256:74b2692e8500525cc38c2b877236ba51d34541e6385eeed5aec15a70f88a6c71 \ + --hash=sha256:ffcb67bc9febd10234a362795f643927f4e0c05d9342c727b65d2384f8feacb6 +wrapt==1.17.1 \ + --hash=sha256:0eb33799b7582bb73787b9903b70595f8eff67eecc9455f668ed01adf53f9eea \ + --hash=sha256:0fdc4e73a3fa0c25eed4d836d9732226f0326957cb075044a7f252b465299433 \ + --hash=sha256:162d5f15bdd3b8037e06540902227ef9e0f298496c0afaadd9e2875851446693 \ + --hash=sha256:169033329022739c6f0d8cd3031a113953b0ba500f3d5978904bdd40baec4568 \ + --hash=sha256:16b2fdfa09a74a3930175b6d9d7d008022aa72a4f02de2b3eecafcc1adfd3cfe \ + --hash=sha256:181a844005c9818792212a32e004cb4c6bd8e35cae8e97b1a39a1918d95cef58 \ + --hash=sha256:21ffcf16f5c243a626b0f8da637948e3d5984e3bc0c1bc500ad990e88e974e3b \ + --hash=sha256:2c160bb8815787646b27a0c8575a26a4d6bf6abd7c5eb250ad3f2d38b29cb2cb \ + --hash=sha256:2f1bc359f6c52e53565e7af24b423e7a1eea97d155f38ac9e90e95303514710b \ + --hash=sha256:52f0907287d9104112dbebda46af4db0793fcc4c64c8a867099212d116b6db64 \ + --hash=sha256:5660e470edfa15ae7ef407272c642d29e9962777a6b30bfa8fc0da2173dc9afd \ + --hash=sha256:57e932ad1908b53e9ad67a746432f02bc8473a9ee16e26a47645a2b224fba5fd \ + --hash=sha256:5c2e24ba455af4b0a237a890ea6ed9bafd01fac2c47095f87c53ea3344215d43 \ + --hash=sha256:6bb82447ddae4e3d9b51f40c494f66e6cbd8fb0e8e8b993678416535c67f9a0d \ + --hash=sha256:6ce4cff3922707048d754e365c4ebf41a3bcbf29b329349bf85d51873c7c7e9e \ + --hash=sha256:6d44b14f3a2f6343a07c90344850b7af5515538ce3a5d01f9c87d8bae9bd8724 \ + --hash=sha256:78da796b74f2c8e0af021ee99feb3bff7cb46f8e658fe25c20e66be1080db4a2 \ + --hash=sha256:7966f98fa36933333d8a1c3d8552aa3d0735001901a4aabcfbd5a502b4ef14fe \ + --hash=sha256:88623fd957ba500d8bb0f7427a76496d99313ca2f9e932481c0882e034cf1add \ + --hash=sha256:93018dbb956e0ad99ea2fa2c3c22f033549dcb1f56ad9f4555dfe25e49688c5d \ + --hash=sha256:99e544e6ce26f89ad5acc6f407bc4daf7c1d42321e836f5c768f834100bdf35c \ + --hash=sha256:9e04f3bd30e0b23c0ca7e1d4084e7d28b6d7d2feb8b7bc69b496fe881280579b \ + --hash=sha256:a992f9e019145e84616048556546edeaba68e05e1c1ffbe8391067a63cdadb0c \ + --hash=sha256:b1a4c8edd038fee0ce67bf119b16eaa45d22a52bbaf7d0a17d2312eb0003b1bb \ + --hash=sha256:b8bd35c15bc82c5cbe397e8196fa57a17ce5d3f30e925a6fd39e4c5bb02fdcff \ + --hash=sha256:bca1c0824f824bcd97b4b179dd55dcad1dab419252be2b2faebbcacefa3b27b2 \ + --hash=sha256:bdf7b0e3d3713331c0bb9daac47cd10e5aa60d060e53696f50de4e560bd5617f \ + --hash=sha256:cbead724daa13cae46e8ab3bb24938d8514d123f34345535b184f3eb1b7ad717 \ + --hash=sha256:d609f0ab0603bbcbf2de906b366b9f9bec75c32b4493550a940de658cc2ce512 \ + --hash=sha256:e5bd9186d52cf3d36bf1823be0e85297e4dbad909bc6dd495ce0d272806d84a7 \ + --hash=sha256:f17e8d926f63aed65ff949682c922f96d00f65c2e852c24272232313fa7823d5 \ + --hash=sha256:f3117feb1fc479eaf84b549d3f229d5d2abdb823f003bc2a1c6dd70072912fa0 +yarl==1.18.3 \ + --hash=sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba \ + --hash=sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186 \ + --hash=sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50 \ + --hash=sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640 \ + --hash=sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8 \ + --hash=sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58 \ + --hash=sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2 \ + --hash=sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393 \ + --hash=sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c \ + --hash=sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272 \ + --hash=sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d \ + --hash=sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576 \ + --hash=sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477 \ + --hash=sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2 \ + --hash=sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512 \ + --hash=sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a \ + --hash=sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0 \ + --hash=sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8 \ + --hash=sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb \ + --hash=sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa \ + --hash=sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1 \ + --hash=sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10 \ + --hash=sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b \ + --hash=sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e \ + --hash=sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb \ + --hash=sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6 \ + --hash=sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285 \ + --hash=sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb \ + --hash=sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482 \ + --hash=sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75 \ + --hash=sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782 \ + --hash=sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53 \ + --hash=sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2 \ + --hash=sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1 From d6386e9716886cd63a974c0106f05da7876f3f96 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Thu, 16 Jan 2025 19:42:14 +0000 Subject: [PATCH 20/64] Update return --- .../src/image_processing/mark_up_cleaner.py | 58 +++++++++++++------ 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/image_processing/src/image_processing/mark_up_cleaner.py b/image_processing/src/image_processing/mark_up_cleaner.py index 048ed7f0..4cb75596 100644 --- a/image_processing/src/image_processing/mark_up_cleaner.py +++ b/image_processing/src/image_processing/mark_up_cleaner.py @@ -3,10 +3,11 @@ import logging import json import regex as re +from layout_holders import FigureHolder -class MarkDownCleaner: - def get_sections(self, text: str) -> list: +class MarkUpCleaner: + def get_sections(self, text) -> list: """ Returns the section details from the content. @@ -21,14 +22,15 @@ def get_sections(self, text: str) -> list: doc_metadata = re.findall(combined_pattern, text, re.DOTALL) return self.clean_sections(doc_metadata) - def clean_sections(self, sections: list) -> list: - """ - Cleans the sections by removing special characters and extra white spaces. + def get_figure_ids(self, text: str) -> list: """ - cleaned_sections = [re.sub(r"[=#]", "", match).strip() for match in sections] - return cleaned_sections + Get the FigureIds from the text. - def get_figures(self, text: str) -> list: + Args: + text: The input text. + + Returns: + list: The list of FigureIds.""" # Regex pattern to extract FigureIds pattern = r"FigureId='([^']+)'" @@ -37,6 +39,13 @@ def get_figures(self, text: str) -> list: return figure_ids + def clean_sections(self, sections: list) -> list: + """ + Cleans the sections by removing special characters and extra white spaces. + """ + cleaned_sections = [re.sub(r"[=#]", "", match).strip() for match in sections] + return cleaned_sections + def remove_markdown_tags(self, text: str, tag_patterns: dict) -> str: """ Remove specified Markdown tags from the text, keeping the contents of the tags. @@ -64,12 +73,15 @@ def remove_markdown_tags(self, text: str, tag_patterns: dict) -> str: logging.error(f"An error occurred in remove_markdown_tags: {e}") return text - def clean_text_and_extract_metadata(self, src_text: str) -> tuple[str, str]: + def clean_text_and_extract_metadata( + self, text: str, figures: list[FigureHolder] + ) -> tuple[str, str]: """This function performs following cleanup activities on the text, remove all unicode characters remove line spacing,remove stop words, normalize characters Args: - src_text (str): The text to cleanup. + text (str): The input text to clean. + figures (list): The list of figures. Returns: str: The clean text.""" @@ -77,13 +89,21 @@ def clean_text_and_extract_metadata(self, src_text: str) -> tuple[str, str]: return_record = {} try: - logging.info(f"Input text: {src_text}") - if len(src_text) == 0: + logging.info(f"Input text: {text}") + if len(text) == 0: logging.error("Input text is empty") raise ValueError("Input text is empty") - return_record["marked_up_chunk"] = src_text - return_record["sections"] = self.get_sections(src_text) + return_record["marked_up_chunk"] = text + + figure_ids = self.get_figure_ids(text) + + return_record["sections"] = self.get_sections(text) + return_record["figures"] = [ + figure.model_dump(by_alias=True) + for figure in figures + if figure.figure_id in figure_ids + ] logging.info(f"Sections: {return_record['sections']}") @@ -95,7 +115,7 @@ def clean_text_and_extract_metadata(self, src_text: str) -> tuple[str, str]: "figcaption": r"
(.*?)
", "header": r"^\s*(#{1,6})\s*(.*?)\s*$", } - cleaned_text = self.remove_markdown_tags(src_text, tag_patterns) + cleaned_text = self.remove_markdown_tags(text, tag_patterns) logging.info(f"Removed markdown tags: {cleaned_text}") @@ -114,7 +134,7 @@ def clean_text_and_extract_metadata(self, src_text: str) -> tuple[str, str]: return "" return return_record - async def process_mark_up_cleaner(self, record: dict) -> dict: + async def clean(self, record: dict) -> dict: """Cleanup the data using standard python libraries. Args: @@ -135,15 +155,17 @@ async def process_mark_up_cleaner(self, record: dict) -> dict: "warnings": None, } + figures = [FigureHolder(**figure) for figure in record["data"]["figures"]] + cleaned_record["data"] = self.clean_text_and_extract_metadata( - record["data"]["chunk"] + record["data"]["chunk"], figures ) except Exception as e: logging.error("string cleanup Error: %s", e) return { "recordId": record["recordId"], - "data": {}, + "data": None, "errors": [ { "message": "Failed to cleanup data. Check function app logs for more details of exact failure." From 2521e764c0446c031f11371478b2ba492c915ed2 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Thu, 16 Jan 2025 19:46:59 +0000 Subject: [PATCH 21/64] Update documents --- .../src/deploy_ai_search/rag_documents.py | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/deploy_ai_search/src/deploy_ai_search/rag_documents.py b/deploy_ai_search/src/deploy_ai_search/rag_documents.py index bf5cdf70..3853f383 100644 --- a/deploy_ai_search/src/deploy_ai_search/rag_documents.py +++ b/deploy_ai_search/src/deploy_ai_search/rag_documents.py @@ -87,9 +87,6 @@ def get_index_fields(self) -> list[SearchableField]: vector_search_dimensions=self.environment.open_ai_embedding_dimensions, vector_search_profile_name=self.vector_search_profile_name, ), - SearchableField( - name="Keywords", type=SearchFieldDataType.String, collection=True - ), SearchableField( name="SourceUri", type=SearchFieldDataType.String, @@ -129,7 +126,7 @@ def get_index_fields(self) -> list[SearchableField]: SimpleField( name="Data", type=SearchFieldDataType.String, - filterable=True, + filterable=False, ), ], ), @@ -167,7 +164,6 @@ def get_semantic_search(self) -> SemanticSearch: title_field=SemanticField(field_name="Title"), content_fields=[SemanticField(field_name="Chunk")], keywords_fields=[ - SemanticField(field_name="Keywords"), SemanticField(field_name="Sections"), ], ), @@ -193,10 +189,6 @@ def get_skills(self) -> list: "/document/chunks/*", "/document/chunks/*/content" ) - key_phrase_extraction_skill = self.get_key_phrase_extraction_skill( - "/document/chunks/*", "/document/chunks/*/cleaned_chunk" - ) - embedding_skill = self.get_vector_skill( "/document/chunks/*", "/document/chunks/*/cleaned_chunk" ) @@ -205,7 +197,6 @@ def get_skills(self) -> list: skills = [ adi_skill, mark_up_cleaner_skill, - key_phrase_extraction_skill, embedding_skill, ] else: @@ -213,7 +204,6 @@ def get_skills(self) -> list: adi_skill, text_split_skill, mark_up_cleaner_skill, - key_phrase_extraction_skill, embedding_skill, ] @@ -229,9 +219,6 @@ def get_index_projections(self) -> SearchIndexerIndexProjection: ), InputFieldMappingEntry(name="Title", source="/document/Title"), InputFieldMappingEntry(name="SourceUri", source="/document/SourceUri"), - InputFieldMappingEntry( - name="Keywords", source="/document/chunks/*/keywords" - ), InputFieldMappingEntry( name="Sections", source="/document/chunks/*/sections" ), From be744e5131e7b3726b398b2ab51ed411b1df2188 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Thu, 16 Jan 2025 19:56:30 +0000 Subject: [PATCH 22/64] Update rag examples --- .../src/deploy_ai_search/.env.example | 27 +++++++++++++++++ .../src/deploy_ai_search/ai_search.py | 4 +-- .../src/deploy_ai_search/environment.py | 29 ++++++++++++------- .../src/deploy_ai_search/rag_documents.py | 16 +++++++--- 4 files changed, 60 insertions(+), 16 deletions(-) create mode 100644 deploy_ai_search/src/deploy_ai_search/.env.example diff --git a/deploy_ai_search/src/deploy_ai_search/.env.example b/deploy_ai_search/src/deploy_ai_search/.env.example new file mode 100644 index 00000000..0cad1743 --- /dev/null +++ b/deploy_ai_search/src/deploy_ai_search/.env.example @@ -0,0 +1,27 @@ + +FunctionApp__Endpoint= +FunctionApp__Key= +FunctionApp__LayoutAnalysis__FunctionName=layout_analysis +FunctionApp__FigureAnalysis__FunctionName=figure_analysis +FunctionApp__LayoutAndFigureMerger__FunctionName=layout_and_figure_merger +FunctionApp__MarkUpCleaner__FunctionName=mark_up_cleaner +FunctionApp__SemanticTextChunker__FunctionName=semantic_text_chunker +FunctionApp__AppRegistrationResourceId= +IdentityType=key # system_assigned or user_assigned or key +AIService__AzureSearchOptions__Endpoint= +AIService__AzureSearchOptions__Identity__ClientId= +AIService__AzureSearchOptions__Key= +AIService__AzureSearchOptions__UsePrivateEndpoint=false +AIService__AzureSearchOptions__Identity__FQName= +StorageAccount__FQEndpoint= +StorageAccount__ConnectionString= +OpenAI__ApiKey= +OpenAI__Endpoint= +OpenAI__EmbeddingModel="text-embedding-ada-002" +OpenAI__EmbeddingDeployment="text-embedding-ada-002" +OpenAI__EmbeddingDimensions=1536 +Text2Sql__DatabaseEngine= +StorageAccount__RagDocuments__Container= +StorageAccount__Text2SqlQueryCache__Container= +StorageAccount__Text2SqlSchemaStore__Container= +StorageAccount__Text2SqlColumnValueStore__Container= diff --git a/deploy_ai_search/src/deploy_ai_search/ai_search.py b/deploy_ai_search/src/deploy_ai_search/ai_search.py index e82575b3..bec31bb3 100644 --- a/deploy_ai_search/src/deploy_ai_search/ai_search.py +++ b/deploy_ai_search/src/deploy_ai_search/ai_search.py @@ -253,7 +253,7 @@ def get_mark_up_cleaner_skill(self, context, source) -> WebApiSkill: return mark_up_cleaner_skill - def get_text_split_skill( + def get_semantic_chunker_skill( self, context, source, @@ -292,7 +292,7 @@ def get_text_split_skill( ] semantic_text_chunker_skill = WebApiSkill( - name="Mark Up Cleaner Skill", + name="Semantic Chunker Skill", description="Skill to clean the data before sending to embedding", context=context, uri=self.environment.get_custom_skill_function_url("semantic_text_chunker"), diff --git a/deploy_ai_search/src/deploy_ai_search/environment.py b/deploy_ai_search/src/deploy_ai_search/environment.py index 5747cb6c..c91ca694 100644 --- a/deploy_ai_search/src/deploy_ai_search/environment.py +++ b/deploy_ai_search/src/deploy_ai_search/environment.py @@ -210,7 +210,7 @@ def function_app_mark_up_cleaner_route(self) -> str: """ This function returns function app data cleanup function name """ - return os.environ.get("FunctionApp__PreEmbeddingCleaner__FunctionName") + return os.environ.get("FunctionApp__MarkUpCleaner__FunctionName") @property def function_app_semantic_text_chunker_route(self) -> str: @@ -220,18 +220,25 @@ def function_app_semantic_text_chunker_route(self) -> str: return os.environ.get("FunctionApp__SemanticTextChunker__FunctionName") @property - def function_app_adi_route(self) -> str: + def function_app_layout_analysis_route(self) -> str: """ This function returns function app adi name """ - return os.environ.get("FunctionApp__ADI__FunctionName") + return os.environ.get("FunctionApp__LayoutAnalysis__FunctionName") @property - def function_app_key_phrase_extractor_route(self) -> str: + def function_app_figure_analysis_route(self) -> str: """ - This function returns function app keyphrase extractor name + This function returns function app figure analysis name """ - return os.environ.get("FunctionApp__KeyPhraseExtractor__FunctionName") + return os.environ.get("FunctionApp__FigureAnalysis__FunctionName") + + @property + def function_app_layout_and_figure_merger_route(self) -> str: + """ + This function returns function app layout and figure merger name + """ + return os.environ.get("FunctionApp__LayoutAndFigureMerger__FunctionName") @property def open_ai_embedding_dimensions(self) -> str: @@ -260,10 +267,12 @@ def get_custom_skill_function_url(self, skill_type: str): """ if skill_type == "mark_up_cleaner": route = self.function_app_mark_up_cleaner_route - elif skill_type == "adi": - route = self.function_app_adi_route - elif skill_type == "key_phrase_extraction": - route = self.function_app_key_phrase_extractor_route + elif skill_type == "layout_analysis": + route = self.function_app_layout_analysis_route + elif skill_type == "figure_analysis": + route = self.function_app_figure_analysis + elif skill_type == "layout_and_figure_merger": + route = self.function_app_layout_and_figure_merger elif skill_type == "semantic_text_chunker": route = self.function_app_semantic_text_chunker_route else: diff --git a/deploy_ai_search/src/deploy_ai_search/rag_documents.py b/deploy_ai_search/src/deploy_ai_search/rag_documents.py index 3853f383..0f6eb692 100644 --- a/deploy_ai_search/src/deploy_ai_search/rag_documents.py +++ b/deploy_ai_search/src/deploy_ai_search/rag_documents.py @@ -179,9 +179,13 @@ def get_skills(self) -> list: Returns: list: The skillsets used in the indexer""" - adi_skill = self.get_adi_skill(self.enable_page_by_chunking) + layout_skill = self.get_layout_analysis_skill(self.enable_page_by_chunking) - text_split_skill = self.get_text_split_skill( + figure_skill = self.get_figure_analysis_skill() + + merger_skill = self.get_layout_and_figure_merger_skill() + + text_split_skill = self.get_semantic_chunker_skill( "/document", "/document/extracted_content/content" ) @@ -195,13 +199,17 @@ def get_skills(self) -> list: if self.enable_page_by_chunking: skills = [ - adi_skill, + layout_skill, + figure_skill, + merger_skill, mark_up_cleaner_skill, embedding_skill, ] else: skills = [ - adi_skill, + layout_skill, + figure_skill, + merger_skill, text_split_skill, mark_up_cleaner_skill, embedding_skill, From 1ef26cd2e0482f9f7da65beafb411fcef3166fe6 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Thu, 16 Jan 2025 20:09:31 +0000 Subject: [PATCH 23/64] Update README --- image_processing/GETTING_STARTED.md | 6 +- image_processing/README.md | 170 ++++------------------------ 2 files changed, 24 insertions(+), 152 deletions(-) diff --git a/image_processing/GETTING_STARTED.md b/image_processing/GETTING_STARTED.md index f4e52223..1b818637 100644 --- a/image_processing/GETTING_STARTED.md +++ b/image_processing/GETTING_STARTED.md @@ -4,7 +4,7 @@ To get started, perform the following steps: 1. Setup Azure OpenAI in your subscription with **gpt-4o-mini** & an embedding model, an Python Function App, AI Search and a storage account. 2. Clone this repository and deploy the AI Search rag documents indexes from `deploy_ai_search`. -3. Run `uv sync` within the image_processing directory to install dependencies. -4. Configure the environment variables of the function app based on the provided sample -5. Package your Azure Function and upload to your Function App +3. Run `uv sync` within the image_processing directory to install dependencies (or used the synced `requirements.txt`) +4. Use the `.env.example` to add the required environmental variables to your function app. Not all values are required dependent on whether you are using System / User Assigned Identities or a Key based authentication. Use this template to update the environment variables in the function app. +5. [Package your Azure Function and upload to your Function App.](https://learn.microsoft.com/en-us/azure/azure-functions/functions-deployment-technologies?tabs=windows) and test with a HTTP request. 6. Upload a document for indexing or send a direct HTTP request to the Azure Function. diff --git a/image_processing/README.md b/image_processing/README.md index 8b8e36a1..c3e1f71a 100644 --- a/image_processing/README.md +++ b/image_processing/README.md @@ -1,6 +1,6 @@ # AI Search Indexing with Azure Document Intelligence -This portion of the repo contains code for linking Azure Document Intelligence with AI Search to process complex documents with charts and images, and uses multi-modal models (gpt-4o-mini) to interpret and understand these. +This portion of the repo contains code for linking Azure Document Intelligence with AI Search to process complex documents with charts and figures, and uses multi-modal models (gpt-4o-mini) to interpret and understand these. The implementation in Python, although it can easily be adapted for C# or another language. The code is designed to run in an Azure Function App inside the tenant. @@ -8,11 +8,11 @@ The implementation in Python, although it can easily be adapted for C# or anothe ## High Level Workflow -A common way to perform document indexing, is to either extract the text content or use [optical character recognition](https://learn.microsoft.com/en-us/azure/search/cognitive-search-skill-ocr) to gather the text content before indexing. Whilst this works well for simple files that contain mainly text based information, the response quality diminishes significantly when the documents contain mainly charts and images, such as a PowerPoint presentation. +A common way to perform document indexing, is to either extract the text content or use [optical character recognition](https://learn.microsoft.com/en-us/azure/search/cognitive-search-skill-ocr) to gather the text content before indexing. Whilst this works well for simple files that contain mainly text based information, the response quality diminishes significantly when the documents contain mainly charts and figures, such as a PowerPoint presentation. To solve this issue and to ensure that good quality information is extracted from the document, an indexer using [Azure Document Intelligence (ADI)](https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/overview?view=doc-intel-4.0.0) is developed with [Custom Skills](https://learn.microsoft.com/en-us/azure/search/cognitive-search-custom-skill-web-api): -![High level workflow for indexing with Azure Document Intelligence based skills](./images/Indexing%20vs%20Indexing%20with%20ADI.png "Indexing with Azure Document Intelligence Approach") +![High level workflow for indexing with Azure Document Intelligence based skills](./figures/Indexing%20vs%20Indexing%20with%20ADI.png "Indexing with Azure Document Intelligence Approach") Instead of using OCR to extract the contents of the document, ADIv4 is used to analyse the layout of the document and convert it to a Markdown format. The Markdown format brings benefits such as: @@ -22,7 +22,7 @@ Instead of using OCR to extract the contents of the document, ADIv4 is used to a Once the Markdown is obtained, several steps are carried out: -1. **Extraction of images / charts**. The figures identified are extracted from the original document and passed to a multi-modal model (gpt-4o-mini in this case) for analysis. We obtain a description and summary of the chart / image to infer the meaning of the figure. This allows us to index and perform RAG analysis the information that is visually obtainable from a chart, without it being explicitly mentioned in the text surrounding. The information is added back into the original chart. +1. **Extraction of figures / charts**. The figures identified are extracted from the original document and passed to a multi-modal model (gpt-4o-mini in this case) for analysis. We obtain a description and summary of the chart / image to infer the meaning of the figure. This allows us to index and perform RAG analysis the information that is visually obtainable from a chart, without it being explicitly mentioned in the text surrounding. The information is added back into the original chart. 2. **Chunking**. The obtained content is chunked accordingly depending on the chunking strategy. This function app supports two chunking methods, **page wise** and **semantic chunking**. The page wise chunking is performed natively by Azure Document Intelligence. For a Semantic Chunking, we include a customer chunker that splits the text with the following strategy: @@ -34,16 +34,10 @@ Once the Markdown is obtained, several steps are carried out: This chunking method aims to improve on page wise chunking, whilst still retaining similar sentences together. When tested, this method shows great performance improvements, over straight page wise chunking, without splitting up the context when relevant. -3. **Cleaning of Markdown**. The final markdown content is cleaned of any characters or unsupported Markdown elements that we do not want in the chunk e.g. non-relevant images. - -The properties returned from the ADI Custom Skill and Chunking are then used to perform the following skills: - -- Markup cleaning. This stage is important as we extract the section information in this step from the headers in the document. Additionally, we remove any Markdown tags or characters that would cause an embedding error. -- Keyphrase extraction -- Vectorisation +3. **Cleaning of Markdown**. The final markdown content is cleaned of any characters or unsupported Markdown elements that we do not want in the chunk e.g. non-relevant figures. > [!NOTE] -> See `GETTING_STARTED.md` for a step by step guide of how to use the accelerator. +> For scalability, the above steps are performed across 5 differnet function app endpoints that are orchestrated by AI search. ## Sample Output @@ -51,13 +45,16 @@ Using the [Phi-3 Technical Report: A Highly Capable Language Model Locally on Yo ```json { - "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Table 1: Comparison results on RepoQA benchmark.
ModelCtx SizePythonC++RustJavaTypeScriptAverage
gpt-4O-2024-05-13128k958085969790.6
gemini-1.5-flash-latest1000k937987949790
Phi-3.5-MoE128k897481889585
Phi-3.5-Mini128k866773778277
Llama-3.1-8B-Instruct128k806573766371
Mixtral-8x7B-Instruct-v0.132k666564717468
Mixtral-8x22B-Instruct-v0.164k606774835567.8
\n\n\nsuch as Arabic, Chinese, Russian, Ukrainian, and Vietnamese, with average MMLU-multilingual scores\nof 55.4 and 47.3, respectively. Due to its larger model capacity, phi-3.5-MoE achieves a significantly\nhigher average score of 69.9, outperforming phi-3.5-mini.\n\nMMLU(5-shot) MultiLingual\n\nPhi-3-mini\n\nPhi-3.5-mini\n\nPhi-3.5-MoE\n\n\n\n\n\n We evaluate the phi-3.5-mini and phi-3.5-MoE models on two long-context understanding tasks:\nRULER [HSK+24] and RepoQA [LTD+24]. As shown in Tables 1 and 2, both phi-3.5-MoE and phi-\n3.5-mini outperform other open-source models with larger sizes, such as Llama-3.1-8B, Mixtral-8x7B,\nand Mixtral-8x22B, on the RepoQA task, and achieve comparable performance to Llama-3.1-8B on\nthe RULER task. However, we observe a significant performance drop when testing the 128K context\nwindow on the RULER task. We suspect this is due to the lack of high-quality long-context data in\nmid-training, an issue we plan to address in the next version of the model release.\n\n In the table 3, we present a detailed evaluation of the phi-3.5-mini and phi-3.5-MoE models\ncompared with recent SoTA pretrained language models, such as GPT-4o-mini, Gemini-1.5 Flash, and\nopen-source models like Llama-3.1-8B and the Mistral models. The results show that phi-3.5-mini\nachieves performance comparable to much larger models like Mistral-Nemo-12B and Llama-3.1-8B, while\nphi-3.5-MoE significantly outperforms other open-source models, offers performance comparable to\nGemini-1.5 Flash, and achieves above 90% of the average performance of GPT-4o-mini across various\nlanguage benchmarks.\n\n\n\n\n", + "final_chunk_content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Table 1: Comparison results on RepoQA benchmark.
ModelCtx SizePythonC++RustJavaTypeScriptAverage
gpt-4O-2024-05-13128k958085969790.6
gemini-1.5-flash-latest1000k937987949790
Phi-3.5-MoE128k897481889585
Phi-3.5-Mini128k866773778277
Llama-3.1-8B-Instruct128k806573766371
Mixtral-8x7B-Instruct-v0.132k666564717468
Mixtral-8x22B-Instruct-v0.164k606774835567.8
\n\n\nsuch as Arabic, Chinese, Russian, Ukrainian, and Vietnamese, with average MMLU-multilingual scores\nof 55.4 and 47.3, respectively. Due to its larger model capacity, phi-3.5-MoE achieves a significantly\nhigher average score of 69.9, outperforming phi-3.5-mini.\n\nMMLU(5-shot) MultiLingual\n\nPhi-3-mini\n\nPhi-3.5-mini\n\nPhi-3.5-MoE\n\n\n\n\n\n We evaluate the phi-3.5-mini and phi-3.5-MoE models on two long-context understanding tasks:\nRULER [HSK+24] and RepoQA [LTD+24]. As shown in Tables 1 and 2, both phi-3.5-MoE and phi-\n3.5-mini outperform other open-source models with larger sizes, such as Llama-3.1-8B, Mixtral-8x7B,\nand Mixtral-8x22B, on the RepoQA task, and achieve comparable performance to Llama-3.1-8B on\nthe RULER task. However, we observe a significant performance drop when testing the 128K context\nwindow on the RULER task. We suspect this is due to the lack of high-quality long-context data in\nmid-training, an issue we plan to address in the next version of the model release.\n\n In the table 3, we present a detailed evaluation of the phi-3.5-mini and phi-3.5-MoE models\ncompared with recent SoTA pretrained language models, such as GPT-4o-mini, Gemini-1.5 Flash, and\nopen-source models like Llama-3.1-8B and the Mistral models. The results show that phi-3.5-mini\nachieves performance comparable to much larger models like Mistral-Nemo-12B and Llama-3.1-8B, while\nphi-3.5-MoE significantly outperforms other open-source models, offers performance comparable to\nGemini-1.5 Flash, and achieves above 90% of the average performance of GPT-4o-mini across various\nlanguage benchmarks.\n\n\n\n\n", "page_number": 7 } ``` The Figure 4 content has been interpreted and added into the extracted chunk to enhance the context for a RAG application. This is particularly powerful for applications where the documents are heavily imaged or chart based. +> [!NOTE] +> See `GETTING_STARTED.md` for a step by step guide of how to use the accelerator. + ## Provided Notebooks \& Utilities - `./function_app` provides a pre-built Python function app that communicates with Azure Document Intelligence, Azure OpenAI etc to perform the Markdown conversion, extraction of figures, figure understanding and corresponding cleaning of Markdown. @@ -71,154 +68,29 @@ To deploy the pre-built index and associated indexer / skillset setup, see instr Deploy the associated function app and the resources. To use with an index, either use the utility to configure a indexer in the provided form, or integrate the skill with your skillset pipeline. -### ADI Custom Skill - -You can then experiment with the custom skill by sending an HTTP request in the AI Search JSON format to the `/adi_2_ai_search` HTTP endpoint. The header controls the chunking technique *(page wise or not)*. - -### Semantic Chunker Skill - -You can then test the chunking by sending a AI Search JSON format to the `/semantic_text_chunker/ HTTP endpoint. The header controls the different chunking parameters *(num_surrounding_sentences, similarity_threshold, max_chunk_tokens, min_chunk_tokens)*. - -### Deployment Steps - -1. Update `.env` file with the associated values. Not all values are required dependent on whether you are using System / User Assigned Identities or a Key based authentication. Use this template to update the environment variables in the function app. -2. Make sure the infra and required identities are setup. This setup requires Azure Document Intelligence and gpt-4o-mini. -3. [Deploy your function app](https://learn.microsoft.com/en-us/azure/azure-functions/functions-deployment-technologies?tabs=windows) and test with a HTTP request. +### Layout Analysis Custom Skill -### Code Files +You can then experiment with the custom skill by sending an HTTP request in the AI Search JSON format to the `/layout_analysis` HTTP endpoint. The header controls the chunking technique *(page wise or not)* and whether to do *figure_extraction*. Figures are additionally saved to a blob storage account so they can be accessed later. -#### function_app.py +### Figure Analysis Custom Skill -`./indexer/function_app.py` contains the HTTP entrypoints for the ADI skill and the other provided utility skills. +This skill can be used to perform gpt-4o-mini analysis on the figures. Rather than analysing the image for consumption, we focus on generating relevant descriptions to aid with retrieval. At retrieval time, the full image can be passed to a visual model for further understanding. -#### semantic_text_chunker.py +### Layout and Figure Merger Custom Skill -`./semantic_text_chunker.py` contains the code to chunk the text semantically, whilst grouping similar sentences. +This skill merges the layout output with the figure outputs to create a unified text content that can be stored in the index for RAG use cases. -#### adi_2_ai_search.py +### Semantic Chunker Custom Skill -`./indexer/adi_2_ai_search.py` contains the methods for content extraction with ADI. The key methods are: - -##### analyse_document - -This method takes the passed file, uploads it to ADI and retrieves the Markdown format. - -##### process_figures_from_extracted_content - -This method takes the detected figures, and crops them out of the page to save them as images. It uses the `understand_image_with_vlm` to communicate with Azure OpenAI to understand the meaning of the extracted figure. - -`update_figure_description` is used to update the original Markdown content with the description and meaning of the figure. - -##### build_and_clean_markdown_for_response - -This method performs the final cleaning of the Markdown contents. In this method, the section headings and page numbers are extracted for the content to be returned to the indexer. - -### Input Format - -The ADI Skill conforms to the [Azure AI Search Custom Skill Input Format](https://learn.microsoft.com/en-gb/azure/search/cognitive-search-custom-skill-web-api?WT.mc_id=Portal-Microsoft_Azure_Search#sample-input-json-structure). AI Search will automatically build this format if you use the utility file provided in this repo to build your indexer and skillset. - -```json -{ - "values": [ - { - "recordId": "0", - "data": { - "source": "" - } - }, - { - "recordId": "1", - "data": { - "source": "" - } - } - ] -} -``` - -### Output Format - -The ADI Skill conforms to the [Azure AI Search Custom Skill Output Format](https://learn.microsoft.com/en-gb/azure/search/cognitive-search-custom-skill-web-api?WT.mc_id=Portal-Microsoft_Azure_Search#sample-output-json-structure). - -If `chunk_by_page` header is `True` (recommended): - -```json -{ - "values": [ - { - "recordId": "0", - "data": { - "extracted_content": [ - { - "page_number": 1, - "content": "" - }, - { - "page_number": 2, - "content": "" - } - ] - } - }, - { - "recordId": "1", - "data": { - "extracted_content": [ - { - "page_number": 1, - "content": "" - }, - { - "page_number": 2, - "content": "" - } - ] - } - } - ] -} -``` - -If `chunk_by_page` header is `False`: - -```json -{ - "values": [ - { - "recordId": "0", - "data": { - "extracted_content": { - "content": "" - } - } - }, - { - "recordId": "1", - "data": { - "extracted_content": { - "content": "" - } - } - } - ] -} -``` - -## Other Provided Custom Skills +You can then test the chunking by sending a AI Search JSON format to the `/semantic_text_chunker/ HTTP endpoint. The header controls the different chunking parameters *(num_surrounding_sentences, similarity_threshold, max_chunk_tokens, min_chunk_tokens)*. -Due to a AI Search product limitation that AI Search cannot connect to AI Services behind Private Endpoints, we provide a Custom Key Phrase Extraction Skill that will work within a Private Endpoint environment. +### MarkUp Cleaner Custom Skill -Additionally, a custom cleaning skill is provided to clean the chunks before vectorisation takes place. +This skill cleans the content and prepares it for vectorisation, and indexing. For any chunk, it will extract a list of Markdown headers that can be used as keywords, and of figures (and their properties) that were found in the chunk. ## Production Considerations Below are some of the considerations that should be made before using this custom skill in production: -- This approach makes use of Azure Document Intelligence v4.0 which is still in preview. Features may change before the GA release. ADI v4.0 preview is only available in select regions. - Azure Document Intelligence output quality varies significantly by file type. A PDF file type will producer richer outputs in terms of figure detection etc, compared to a PPTX file in our testing. - -## Possible Improvements - -Below are some possible improvements that could be made to the vectorisation approach: - -- Storing the extracted figures in blob storage for access later. This would allow the LLM to resurface the correct figure or provide a link to the give in the reference system to be displayed in the UI. +- Performing Document Intelligence Layout model and gpt-4o-mini analysis on every document can become expensive. Consider only using on a subset of documents if cost is a concern. From 6049d7bed309ca54e50589ab5d41ffc8b3208c8a Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Tue, 21 Jan 2025 21:02:43 +0000 Subject: [PATCH 24/64] Update readme and model --- image_processing/README.md | 10 +- .../image_processing/semantic_text_chunker.py | 24 +- text_2_sql/README.md | 9 +- uv.lock | 445 +++++++++--------- 4 files changed, 242 insertions(+), 246 deletions(-) diff --git a/image_processing/README.md b/image_processing/README.md index c3e1f71a..9ce082cd 100644 --- a/image_processing/README.md +++ b/image_processing/README.md @@ -1,10 +1,12 @@ -# AI Search Indexing with Azure Document Intelligence +# Image Processing for RAG - AI Search Indexing with Azure Document Intelligence This portion of the repo contains code for linking Azure Document Intelligence with AI Search to process complex documents with charts and figures, and uses multi-modal models (gpt-4o-mini) to interpret and understand these. The implementation in Python, although it can easily be adapted for C# or another language. The code is designed to run in an Azure Function App inside the tenant. -**This approach makes use of Azure Document Intelligence v4.0 which is still in preview.** +> [!NOTE] +> +> See `GETTING_STARTED.md` for a step by step guide of how to use the accelerator. ## High Level Workflow @@ -37,6 +39,7 @@ Once the Markdown is obtained, several steps are carried out: 3. **Cleaning of Markdown**. The final markdown content is cleaned of any characters or unsupported Markdown elements that we do not want in the chunk e.g. non-relevant figures. > [!NOTE] +> > For scalability, the above steps are performed across 5 differnet function app endpoints that are orchestrated by AI search. ## Sample Output @@ -52,9 +55,6 @@ Using the [Phi-3 Technical Report: A Highly Capable Language Model Locally on Yo The Figure 4 content has been interpreted and added into the extracted chunk to enhance the context for a RAG application. This is particularly powerful for applications where the documents are heavily imaged or chart based. -> [!NOTE] -> See `GETTING_STARTED.md` for a step by step guide of how to use the accelerator. - ## Provided Notebooks \& Utilities - `./function_app` provides a pre-built Python function app that communicates with Azure Document Intelligence, Azure OpenAI etc to perform the Markdown conversion, extraction of figures, figure understanding and corresponding cleaning of Markdown. diff --git a/image_processing/src/image_processing/semantic_text_chunker.py b/image_processing/src/image_processing/semantic_text_chunker.py index e990b7bd..3cfd1614 100644 --- a/image_processing/src/image_processing/semantic_text_chunker.py +++ b/image_processing/src/image_processing/semantic_text_chunker.py @@ -15,17 +15,16 @@ def __init__( num_surrounding_sentences: int = 1, similarity_threshold: float = 0.8, max_chunk_tokens: int = 200, - min_chunk_tokens: int = 50, - distill_model=True, + min_chunk_tokens: int = 50 ): self.num_surrounding_sentences = num_surrounding_sentences self.similarity_threshold = similarity_threshold self.max_chunk_tokens = max_chunk_tokens self.min_chunk_tokens = min_chunk_tokens - self.distill_model = distill_model model_name = "minishlab/M2V_base_output" self.distilled_model = StaticModel.from_pretrained(model_name) + try: self._nlp_model = spacy.load("en_core_web_md") except IOError as e: @@ -267,7 +266,7 @@ def look_ahead_and_behind_sentences( next_sentence_is_table_or_figure, ) in enumerate( is_table_or_figure_map[ - current_sentence_index : current_sentence_index + current_sentence_index: current_sentence_index + surround_sentences_gap_to_test ] ): @@ -301,7 +300,8 @@ def retrive_current_chunk_at_n(n): else: return current_chunk[n] - current_chunk_tokens = self.num_tokens_from_string(" ".join(current_chunk)) + current_chunk_tokens = self.num_tokens_from_string( + " ".join(current_chunk)) if len(current_chunk) >= 2 and current_chunk_tokens >= self.min_chunk_tokens: logging.info("Comparing chunks") @@ -403,13 +403,13 @@ def retrieve_current_chunk(): new_is_table_or_figure_map.append(False) if forwards_direction: current_chunk = sentences[ - current_sentence_index : current_sentence_index + current_sentence_index: current_sentence_index + min_of_distance_to_next_figure_or_num_surrounding_sentences ] else: current_chunk = sentences[ - current_sentence_index : current_sentence_index - - min_of_distance_to_next_figure_or_num_surrounding_sentences : -1 + current_sentence_index: current_sentence_index + - min_of_distance_to_next_figure_or_num_surrounding_sentences: -1 ] index += min_of_distance_to_next_figure_or_num_surrounding_sentences continue @@ -446,12 +446,8 @@ def retrieve_current_chunk(): return chunks, new_is_table_or_figure_map def sentence_similarity(self, text_1, text_2): - if self.distill_model: - vec1 = self.distilled_model.encode(text_1) - vec2 = self.distilled_model.encode(text_2) - else: - vec1 = self._nlp_model(text_1).vector - vec2 = self._nlp_model(text_2).vector + vec1 = self.distilled_model.encode(text_1) + vec2 = self.distilled_model.encode(text_2) dot_product = np.dot(vec1, vec2) magnitude = np.linalg.norm(vec1) * np.linalg.norm(vec2) diff --git a/text_2_sql/README.md b/text_2_sql/README.md index 7004d358..15d03057 100644 --- a/text_2_sql/README.md +++ b/text_2_sql/README.md @@ -6,7 +6,7 @@ The sample provided works with Azure SQL Server, although it has been easily ada > [!NOTE] > -> - Previous versions of this approach have now been moved to `previous_iterations/semantic_kernel`. These will not be updated. +> See `GETTING_STARTED.md` for a step by step guide of how to use the accelerator. ## Why Text2SQL instead of indexing the database contents? @@ -31,6 +31,10 @@ To solve these issues, a Multi-Shot approach is developed. Below is the iteratio ![Comparison between a common Text2SQL approach and a Multi-Shot Text2SQL approach.](./images/Text2SQL%20Approaches.png "Multi Shot SQL Approaches") +> [!NOTE] +> +> - Previous versions of this approach have now been moved to `previous_iterations/semantic_kernel`. These will not be updated or maintained. + Our approach has evolved as the system has matured into an multi-agent approach that brings improved reasoning, speed and instruction following capabilities. With separation into agents, different agents can focus on one task only, and provide a better overall flow and response quality. Using Auto-Function calling capabilities, the LLM is able to retrieve from the plugin the full schema information for the views / tables that it considers useful for answering the question. Once retrieved, the full SQL query can then be generated. The schemas for multiple views / tables can be retrieved to allow the LLM to perform joins and other complex queries. @@ -39,9 +43,6 @@ To improve the scalability and accuracy in SQL Query generation, the entity rela For the query cache enabled approach, AI Search is used as a vector based cache, but any other cache that supports vector queries could be used, such as Redis. -> [!NOTE] -> See `GETTING_STARTED.md` for a step by step guide of how to use the accelerator. - ### Full Logical Flow for Agentic Vector Based Approach The following diagram shows the logical flow within mutlti agent system. In an ideal scenario, the questions will follow the _Pre-Fetched Cache Results Path** which leads to the quickest answer generation. In cases where the question is not known, the group chat selector will fall back to the other agents accordingly and generate the SQL query using the LLMs. The cache is then updated with the newly generated query and schemas. diff --git a/uv.lock b/uv.lock index f050d273..c3c1c22f 100644 --- a/uv.lock +++ b/uv.lock @@ -11,15 +11,6 @@ members = [ "text-2-sql-core", ] -[[package]] -name = "aioconsole" -version = "0.8.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c7/c9/c57e979eea211b10a63783882a826f257713fa7c0d6c9a6eac851e674fb4/aioconsole-0.8.1.tar.gz", hash = "sha256:0535ce743ba468fb21a1ba43c9563032c779534d4ecd923a46dbd350ad91d234", size = 61085 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fa/ea/23e756ec1fea0c685149304dda954b3b3932d6d06afbf42a66a2e6dc2184/aioconsole-0.8.1-py3-none-any.whl", hash = "sha256:e1023685cde35dde909fbf00631ffb2ed1c67fe0b7058ebb0892afbde5f213e5", size = 43324 }, -] - [[package]] name = "aiofiles" version = "24.1.0" @@ -238,15 +229,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/9f/3c3503693386c4b0f245eaf5ca6198e3b28879ca0a40bde6b0e319793453/async_lru-2.0.4-py3-none-any.whl", hash = "sha256:ff02944ce3c288c5be660c42dbcca0742b32c3b279d6dceda655190240b99224", size = 6111 }, ] -[[package]] -name = "asyncio-atexit" -version = "1.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/22/d3/dd2974be3f67c7ec96e0d6ab454429d0372cb7c7bffa3d0ac67a483cb801/asyncio-atexit-1.0.1.tar.gz", hash = "sha256:1d0c71544b8ee2c484d322844ee72c0875dde6f250c0ed5b6993592ab9f7d436", size = 4373 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/65/10/d6abaefa57a52646651fd0383c056280b0853c0106229ece6bb38cd14463/asyncio_atexit-1.0.1-py3-none-any.whl", hash = "sha256:d93d5f7d5633a534abd521ce2896ed0fbe8de170bb1e65ec871d1c20eac9d376", size = 3752 }, -] - [[package]] name = "attrs" version = "24.3.0" @@ -258,48 +240,43 @@ wheels = [ [[package]] name = "autogen-agentchat" -version = "0.4.0.dev11" +version = "0.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "autogen-core" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/84/d6/b5141bb82f16774c582c990a6c53511ce580d1f8c809987ef546a78053c5/autogen_agentchat-0.4.0.dev11.tar.gz", hash = "sha256:d19091afb9f19f8a3ae7b91b88e5269cea39c696a9dde3b7b95b85f70343f0f3", size = 47859 } +sdist = { url = "https://files.pythonhosted.org/packages/c6/ac/15406c6167fd95e21a76e08d1347b4b8d87bfbda281ae70593f8b547fcea/autogen_agentchat-0.4.2.tar.gz", hash = "sha256:00634e7fbb6b8e922b44cea1b6632c7afdf6a285ed4a14dc84386b0669410c1c", size = 50815 } wheels = [ - { url = "https://files.pythonhosted.org/packages/96/21/93cfb1590c1bab01a1addaf1bdd0b1849c710fbe3cf408b469e59c751bd4/autogen_agentchat-0.4.0.dev11-py3-none-any.whl", hash = "sha256:f53d5226b8bd2fa069e48e6481a5e6fa9b1620daa5b60161f5f4423d4efa85d5", size = 57428 }, + { url = "https://files.pythonhosted.org/packages/98/c3/d8b9ddaaa8131a5eed6f2e70782bc255bfc9cb74ec675a65d626fbd7d05e/autogen_agentchat-0.4.2-py3-none-any.whl", hash = "sha256:7723b7ecedc1640e0c5053dcafe0e8045efb396916e8a2ac4d3e582b1016b7e1", size = 58514 }, ] [[package]] name = "autogen-core" -version = "0.4.0.dev11" +version = "0.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "aioconsole" }, - { name = "aiohttp" }, - { name = "asyncio-atexit" }, { name = "jsonref" }, - { name = "openai" }, { name = "opentelemetry-api" }, { name = "pillow" }, { name = "protobuf" }, { name = "pydantic" }, - { name = "tiktoken" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e1/dd/5382b907aa446349011defb2bd5073dc75f81a612caf664f77ad8f849726/autogen_core-0.4.0.dev11.tar.gz", hash = "sha256:d98d0cdb8bba0c01cd100b889a4616e0100e8bd8403e8087c6f1d7eb57608564", size = 2273945 } +sdist = { url = "https://files.pythonhosted.org/packages/90/e7/20b073cd0d78cc735a94d0bef8feafe158c0f0c5c4f1f3bad94e01d7602f/autogen_core-0.4.2.tar.gz", hash = "sha256:14b735a8eb76540014187c0051e0f22d72d4e683017b08285be76746defc7125", size = 2288241 } wheels = [ - { url = "https://files.pythonhosted.org/packages/af/89/573b0396f62a0df2ab16daf5018ed27fa3694b53d12aac1c26a0ece1f2fd/autogen_core-0.4.0.dev11-py3-none-any.whl", hash = "sha256:47692b7e15424051cecdcea3e57d09b9c44c82d2661591aa24c7e54bc2df0fef", size = 78442 }, + { url = "https://files.pythonhosted.org/packages/35/7a/d585292bdf6562576f66b0119a1cd73da780083702d05ce0405cdd2b8b3a/autogen_core-0.4.2-py3-none-any.whl", hash = "sha256:96a2a0e925d0ebb08556b556c5eb6c74177450e607309f9e318db33081adb1a0", size = 71782 }, ] [[package]] name = "autogen-ext" -version = "0.4.0.dev11" +version = "0.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "autogen-core" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b2/86/0bd0057e577beb3ed614939b4aaf521ae8d8196bb08bcd9440aae8ec8702/autogen_ext-0.4.0.dev11.tar.gz", hash = "sha256:518b7d011abaa491988eb6d170707efb19bed4c72b000833e13f279548e7ecd0", size = 91683 } +sdist = { url = "https://files.pythonhosted.org/packages/f4/b5/999b398bf0558f678c6a624288da0daa122f7c52537649f01c876d375b1d/autogen_ext-0.4.2.tar.gz", hash = "sha256:a35a529f332322a279f3bd60f83edca513772e97f5dbd65988d4886105c1e62d", size = 102990 } wheels = [ - { url = "https://files.pythonhosted.org/packages/f7/f5/f4ca335fef9956b50d5b132e427c2f7a883c101a9c33c52f50c5a422b48b/autogen_ext-0.4.0.dev11-py3-none-any.whl", hash = "sha256:b1d89e25356073c3adbb25aad5b05138176253288e682c0aac7b46883a2b8d30", size = 100352 }, + { url = "https://files.pythonhosted.org/packages/5b/2d/b0d5a80a2a241a233fdd4832d47214ad05a57552703ad35b1a6d04bb950c/autogen_ext-0.4.2-py3-none-any.whl", hash = "sha256:4f9a5eb6cf649cdba4a4bdf045946c5caf0f8976ff553f1d8cfcc71e391c0918", size = 111229 }, ] [package.optional-dependencies] @@ -310,6 +287,7 @@ azure = [ openai = [ { name = "aiofiles" }, { name = "openai" }, + { name = "tiktoken" }, ] [[package]] @@ -325,7 +303,7 @@ dependencies = [ { name = "nltk" }, { name = "pyyaml" }, { name = "sqlparse" }, - { name = "text-2-sql-core", extra = ["databricks", "snowflake"] }, + { name = "text-2-sql-core" }, ] [package.optional-dependencies] @@ -338,6 +316,9 @@ postgresql = [ snowflake = [ { name = "text-2-sql-core", extra = ["snowflake"] }, ] +sqlite = [ + { name = "text-2-sql-core", extra = ["sqlite"] }, +] [package.dev-dependencies] dev = [ @@ -354,17 +335,18 @@ dev = [ [package.metadata] requires-dist = [ { name = "aiostream", specifier = ">=0.6.4" }, - { name = "autogen-agentchat", specifier = "==0.4.0.dev11" }, - { name = "autogen-core", specifier = "==0.4.0.dev11" }, - { name = "autogen-ext", extras = ["azure", "openai"], specifier = "==0.4.0.dev11" }, + { name = "autogen-agentchat", specifier = "==0.4.2" }, + { name = "autogen-core", specifier = "==0.4.2" }, + { name = "autogen-ext", extras = ["azure", "openai"], specifier = "==0.4.2" }, { name = "grpcio", specifier = ">=1.68.1" }, { name = "nltk", specifier = ">=3.8.1" }, { name = "pyyaml", specifier = ">=6.0.2" }, { name = "sqlparse", specifier = ">=0.4.4" }, + { name = "text-2-sql-core", editable = "text_2_sql/text_2_sql_core" }, { name = "text-2-sql-core", extras = ["databricks"], marker = "extra == 'databricks'", editable = "text_2_sql/text_2_sql_core" }, { name = "text-2-sql-core", extras = ["postgresql"], marker = "extra == 'postgresql'", editable = "text_2_sql/text_2_sql_core" }, { name = "text-2-sql-core", extras = ["snowflake"], marker = "extra == 'snowflake'", editable = "text_2_sql/text_2_sql_core" }, - { name = "text-2-sql-core", extras = ["snowflake", "databricks"], editable = "text_2_sql/text_2_sql_core" }, + { name = "text-2-sql-core", extras = ["sqlite"], marker = "extra == 'sqlite'", editable = "text_2_sql/text_2_sql_core" }, ] [package.metadata.requires-dev] @@ -739,7 +721,7 @@ name = "click" version = "8.1.8" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } wheels = [ @@ -822,20 +804,24 @@ wheels = [ [[package]] name = "cymem" -version = "2.0.10" +version = "2.0.11" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b6/62/eac45989f3d3296133f292f3097cb4c1f9d3ad3e5a85e79bbd2c7f96278f/cymem-2.0.10.tar.gz", hash = "sha256:f51700acfa1209b4a221dc892cca8030f4bc10d4c153dec098042f484c7f07a4", size = 10239 } +sdist = { url = "https://files.pythonhosted.org/packages/f2/4a/1acd761fb6ac4c560e823ce40536a62f886f2d59b2763b5c3fc7e9d92101/cymem-2.0.11.tar.gz", hash = "sha256:efe49a349d4a518be6b6c6b255d4a80f740a341544bde1a807707c058b88d0bd", size = 10346 } wheels = [ - { url = "https://files.pythonhosted.org/packages/17/27/a4383a1f534676f1fccb90e35154b3cd1d333954c756b1b01839b5554169/cymem-2.0.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c6ed8b1ed448cd65e12405a02aa71b22a4094d8a623205625057c4c73ba4b133", size = 42577 }, - { url = "https://files.pythonhosted.org/packages/55/de/068d791d77c5f46844ee00c56414a6c7d9a3e80a82228ecb17c6530886bc/cymem-2.0.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5e57928d9e93c61265281ea01a1d24499d397625b2766a0c5735b99bceb3ba75", size = 42206 }, - { url = "https://files.pythonhosted.org/packages/35/af/f93d0fdd5f6174038c6745b708bb97e71f4568e7a9b25501ea481e269e3c/cymem-2.0.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc4932060a5d55648fa4a3960f1cad9905572ed5c6f02af42f849e869d2803d4", size = 227944 }, - { url = "https://files.pythonhosted.org/packages/8e/11/6bc72829cef14d1598a4c9f9381ac3d8b4e09d98f8496c9042cd994b7f13/cymem-2.0.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f4bc6c823b400d32cddcfeefb3f352d52a0cc911cb0b5c1ef64e3f9741fd56b9", size = 216400 }, - { url = "https://files.pythonhosted.org/packages/16/40/1b6bdfaab3f80eeb302cd6212c2dcaa735d055db509487cf8da51764b74d/cymem-2.0.10-cp312-cp312-win_amd64.whl", hash = "sha256:6ae7f22af4bc4311f06c925df61c62219c11939dffc9c91d67caf89a7e1557a5", size = 39243 }, - { url = "https://files.pythonhosted.org/packages/fa/88/e5c8f44e80a64fdca827f2dd2e323afdef339ae83f1a32763940f40232de/cymem-2.0.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5698a515900dc697874444fa05d8d852bbad43543de2e7834ec3895156cc2aad", size = 42340 }, - { url = "https://files.pythonhosted.org/packages/e4/27/5f76934645f53704fb116802480b21af5c3cbb71ba4661f5af1a1e5ba210/cymem-2.0.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6580d657d0f208d675d62cc052fb908529d52d24282342e24a9843de85352b88", size = 41903 }, - { url = "https://files.pythonhosted.org/packages/76/33/5d62b0e0461aed0a93d3a14a17e0e869d8eab9b2c0e9407f69ff763818ed/cymem-2.0.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea72cf0e369f3cf1f10038d572143d88ce7c959222cf7d742acbeb45e00ac5c0", size = 222927 }, - { url = "https://files.pythonhosted.org/packages/b7/ee/47f412bdf64ab5ad9d14ce6ed9378a989dac3651f61ae190a5ff9fb866f6/cymem-2.0.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:33d7f5014ad36af22995847fccd82ca0bd4b0394fb1d9dd9fef1e8cefdab2444", size = 219143 }, - { url = "https://files.pythonhosted.org/packages/38/f8/a8c04468929043acf8048cce72e438412c7c949f6983b6dc14209e4371ec/cymem-2.0.10-cp313-cp313-win_amd64.whl", hash = "sha256:82f19a39052747309ced6b948b34aff62aa00c795c9d9d3d31a071e8c791efee", size = 39046 }, + { url = "https://files.pythonhosted.org/packages/71/67/0d74f7e9d79f934368a78fb1d1466b94bebdbff14f8ae94dd3e4ea8738bb/cymem-2.0.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a0fbe19ce653cd688842d81e5819dc63f911a26e192ef30b0b89f0ab2b192ff2", size = 42621 }, + { url = "https://files.pythonhosted.org/packages/4a/d6/f7a19c63b48efc3f00a3ee8d69070ac90202e1e378f6cf81b8671f0cf762/cymem-2.0.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de72101dc0e6326f6a2f73e05a438d1f3c6110d41044236d0fbe62925091267d", size = 42249 }, + { url = "https://files.pythonhosted.org/packages/d7/60/cdc434239813eef547fb99b6d0bafe31178501702df9b77c4108c9a216f6/cymem-2.0.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee4395917f6588b8ac1699499128842768b391fe8896e8626950b4da5f9a406", size = 224758 }, + { url = "https://files.pythonhosted.org/packages/1d/68/8fa6efae17cd3b2ba9a2f83b824867c5b65b06f7aec3f8a0d0cabdeffb9b/cymem-2.0.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b02f2b17d760dc3fe5812737b1ce4f684641cdd751d67761d333a3b5ea97b83", size = 227995 }, + { url = "https://files.pythonhosted.org/packages/e4/f3/ceda70bf6447880140602285b7c6fa171cb7c78b623d35345cc32505cd06/cymem-2.0.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:04ee6b4041ddec24512d6e969ed6445e57917f01e73b9dabbe17b7e6b27fef05", size = 215325 }, + { url = "https://files.pythonhosted.org/packages/d3/47/6915eaa521e1ce7a0ba480eecb6870cb4f681bcd64ced88c2f0ed7a744b4/cymem-2.0.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e1048dae7e627ee25f22c87bb670b13e06bc0aecc114b89b959a798d487d1bf4", size = 216447 }, + { url = "https://files.pythonhosted.org/packages/7b/be/8e02bdd31e557f642741a06c8e886782ef78f0b00daffd681922dc9bbc88/cymem-2.0.11-cp312-cp312-win_amd64.whl", hash = "sha256:0c269c7a867d74adeb9db65fa1d226342aacf44d64b7931282f0b0eb22eb6275", size = 39283 }, + { url = "https://files.pythonhosted.org/packages/bd/90/b064e2677e27a35cf3605146abc3285d4f599cc1b6c18fc445ae876dd1e3/cymem-2.0.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4a311c82f743275c84f708df89ac5bf60ddefe4713d532000c887931e22941f", size = 42389 }, + { url = "https://files.pythonhosted.org/packages/fd/60/7aa0561a6c1f0d42643b02c4fdeb2a16181b0ff4e85d73d2d80c6689e92a/cymem-2.0.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:02ed92bead896cca36abad00502b14fa651bdf5d8319461126a2d5ac8c9674c5", size = 41948 }, + { url = "https://files.pythonhosted.org/packages/5f/4e/88a29cc5575374982e527b4ebcab3781bdc826ce693c6418a0f836544246/cymem-2.0.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44ddd3588379f8f376116384af99e3fb5f90091d90f520c341942618bf22f05e", size = 219382 }, + { url = "https://files.pythonhosted.org/packages/9b/3a/8f96e167e93b7f7ec105ed7b25c77bbf215d15bcbf4a24082cdc12234cd6/cymem-2.0.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87ec985623624bbd298762d8163fc194a096cb13282731a017e09ff8a60bb8b1", size = 222974 }, + { url = "https://files.pythonhosted.org/packages/6a/fc/ce016bb0c66a4776345fac7508fddec3b739b9dd4363094ac89cce048832/cymem-2.0.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3385a47285435848e0ed66cfd29b35f3ed8703218e2b17bd7a0c053822f26bf", size = 213426 }, + { url = "https://files.pythonhosted.org/packages/5c/c8/accf7cc768f751447a5050b14a195af46798bc22767ac25f49b02861b1eb/cymem-2.0.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5461e65340d6572eb64deadce79242a446a1d39cb7bf70fe7b7e007eb0d799b0", size = 219195 }, + { url = "https://files.pythonhosted.org/packages/74/65/c162fbac63e867a055240b6600b92ef96c0eb7a1895312ac53c4be93d056/cymem-2.0.11-cp313-cp313-win_amd64.whl", hash = "sha256:25da111adf425c29af0cfd9fecfec1c71c8d82e2244a85166830a0817a66ada7", size = 39090 }, ] [[package]] @@ -860,19 +846,19 @@ wheels = [ [[package]] name = "debugpy" -version = "1.8.11" +version = "1.8.12" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bc/e7/666f4c9b0e24796af50aadc28d36d21c2e01e831a934535f956e09b3650c/debugpy-1.8.11.tar.gz", hash = "sha256:6ad2688b69235c43b020e04fecccdf6a96c8943ca9c2fb340b8adc103c655e57", size = 1640124 } +sdist = { url = "https://files.pythonhosted.org/packages/68/25/c74e337134edf55c4dfc9af579eccb45af2393c40960e2795a94351e8140/debugpy-1.8.12.tar.gz", hash = "sha256:646530b04f45c830ceae8e491ca1c9320a2d2f0efea3141487c82130aba70dce", size = 1641122 } wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/ae/2cf26f3111e9d94384d9c01e9d6170188b0aeda15b60a4ac6457f7c8a26f/debugpy-1.8.11-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:84e511a7545d11683d32cdb8f809ef63fc17ea2a00455cc62d0a4dbb4ed1c308", size = 2498756 }, - { url = "https://files.pythonhosted.org/packages/b0/16/ec551789d547541a46831a19aa15c147741133da188e7e6acf77510545a7/debugpy-1.8.11-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce291a5aca4985d82875d6779f61375e959208cdf09fcec40001e65fb0a54768", size = 4219136 }, - { url = "https://files.pythonhosted.org/packages/72/6f/b2b3ce673c55f882d27a6eb04a5f0c68bcad6b742ac08a86d8392ae58030/debugpy-1.8.11-cp312-cp312-win32.whl", hash = "sha256:28e45b3f827d3bf2592f3cf7ae63282e859f3259db44ed2b129093ca0ac7940b", size = 5224440 }, - { url = "https://files.pythonhosted.org/packages/77/09/b1f05be802c1caef5b3efc042fc6a7cadd13d8118b072afd04a9b9e91e06/debugpy-1.8.11-cp312-cp312-win_amd64.whl", hash = "sha256:44b1b8e6253bceada11f714acf4309ffb98bfa9ac55e4fce14f9e5d4484287a1", size = 5264578 }, - { url = "https://files.pythonhosted.org/packages/2e/66/931dc2479aa8fbf362dc6dcee707d895a84b0b2d7b64020135f20b8db1ed/debugpy-1.8.11-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:8988f7163e4381b0da7696f37eec7aca19deb02e500245df68a7159739bbd0d3", size = 2483651 }, - { url = "https://files.pythonhosted.org/packages/10/07/6c171d0fe6b8d237e35598b742f20ba062511b3a4631938cc78eefbbf847/debugpy-1.8.11-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c1f6a173d1140e557347419767d2b14ac1c9cd847e0b4c5444c7f3144697e4e", size = 4213770 }, - { url = "https://files.pythonhosted.org/packages/89/f1/0711da6ac250d4fe3bf7b3e9b14b4a86e82a98b7825075c07e19bab8da3d/debugpy-1.8.11-cp313-cp313-win32.whl", hash = "sha256:bb3b15e25891f38da3ca0740271e63ab9db61f41d4d8541745cfc1824252cb28", size = 5223911 }, - { url = "https://files.pythonhosted.org/packages/56/98/5e27fa39050749ed460025bcd0034a0a5e78a580a14079b164cc3abdeb98/debugpy-1.8.11-cp313-cp313-win_amd64.whl", hash = "sha256:d8768edcbeb34da9e11bcb8b5c2e0958d25218df7a6e56adf415ef262cd7b6d1", size = 5264166 }, - { url = "https://files.pythonhosted.org/packages/77/0a/d29a5aacf47b4383ed569b8478c02d59ee3a01ad91224d2cff8562410e43/debugpy-1.8.11-py2.py3-none-any.whl", hash = "sha256:0e22f846f4211383e6a416d04b4c13ed174d24cc5d43f5fd52e7821d0ebc8920", size = 5226874 }, + { url = "https://files.pythonhosted.org/packages/ba/e6/0f876ecfe5831ebe4762b19214364753c8bc2b357d28c5d739a1e88325c7/debugpy-1.8.12-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:7e94b643b19e8feb5215fa508aee531387494bf668b2eca27fa769ea11d9f498", size = 2500846 }, + { url = "https://files.pythonhosted.org/packages/19/64/33f41653a701f3cd2cbff8b41ebaad59885b3428b5afd0d93d16012ecf17/debugpy-1.8.12-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:086b32e233e89a2740c1615c2f775c34ae951508b28b308681dbbb87bba97d06", size = 4222181 }, + { url = "https://files.pythonhosted.org/packages/32/a6/02646cfe50bfacc9b71321c47dc19a46e35f4e0aceea227b6d205e900e34/debugpy-1.8.12-cp312-cp312-win32.whl", hash = "sha256:2ae5df899732a6051b49ea2632a9ea67f929604fd2b036613a9f12bc3163b92d", size = 5227017 }, + { url = "https://files.pythonhosted.org/packages/da/a6/10056431b5c47103474312cf4a2ec1001f73e0b63b1216706d5fef2531eb/debugpy-1.8.12-cp312-cp312-win_amd64.whl", hash = "sha256:39dfbb6fa09f12fae32639e3286112fc35ae976114f1f3d37375f3130a820969", size = 5267555 }, + { url = "https://files.pythonhosted.org/packages/cf/4d/7c3896619a8791effd5d8c31f0834471fc8f8fb3047ec4f5fc69dd1393dd/debugpy-1.8.12-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:696d8ae4dff4cbd06bf6b10d671e088b66669f110c7c4e18a44c43cf75ce966f", size = 2485246 }, + { url = "https://files.pythonhosted.org/packages/99/46/bc6dcfd7eb8cc969a5716d858e32485eb40c72c6a8dc88d1e3a4d5e95813/debugpy-1.8.12-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:898fba72b81a654e74412a67c7e0a81e89723cfe2a3ea6fcd3feaa3395138ca9", size = 4218616 }, + { url = "https://files.pythonhosted.org/packages/03/dd/d7fcdf0381a9b8094da1f6a1c9f19fed493a4f8576a2682349b3a8b20ec7/debugpy-1.8.12-cp313-cp313-win32.whl", hash = "sha256:22a11c493c70413a01ed03f01c3c3a2fc4478fc6ee186e340487b2edcd6f4180", size = 5226540 }, + { url = "https://files.pythonhosted.org/packages/25/bd/ecb98f5b5fc7ea0bfbb3c355bc1dd57c198a28780beadd1e19915bf7b4d9/debugpy-1.8.12-cp313-cp313-win_amd64.whl", hash = "sha256:fdb3c6d342825ea10b90e43d7f20f01535a72b3a1997850c0c3cefa5c27a4a2c", size = 5267134 }, + { url = "https://files.pythonhosted.org/packages/38/c4/5120ad36405c3008f451f94b8f92ef1805b1e516f6ff870f331ccb3c4cc0/debugpy-1.8.12-py2.py3-none-any.whl", hash = "sha256:274b6a2040349b5c9864e475284bce5bb062e63dce368a394b8cc865ae3b00c6", size = 5229490 }, ] [[package]] @@ -1022,7 +1008,7 @@ source = { url = "https://github.com/explosion/spacy-models/releases/download/en dependencies = [ { name = "spacy" }, ] -sdist = { url = "https://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.7.1/en_core_web_md-3.7.1.tar.gz", hash = "sha256:3273a1335fcb688be09949c5cdb73e85eb584ec3dfc50d4338c17daf6ccd4628" } +sdist = { hash = "sha256:3273a1335fcb688be09949c5cdb73e85eb584ec3dfc50d4338c17daf6ccd4628" } [package.metadata] requires-dist = [{ name = "spacy", specifier = ">=3.7.2,<3.8.0" }] @@ -1056,11 +1042,11 @@ wheels = [ [[package]] name = "filelock" -version = "3.16.1" +version = "3.17.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9d/db/3ef5bb276dae18d6ec2124224403d1d67bccdbefc17af4cc8f553e341ab1/filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435", size = 18037 } +sdist = { url = "https://files.pythonhosted.org/packages/dc/9c/0b15fb47b464e1b663b1acd1253a062aa5feecb07d4e597daea542ebd2b5/filelock-3.17.0.tar.gz", hash = "sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e", size = 18027 } wheels = [ - { url = "https://files.pythonhosted.org/packages/b9/f8/feced7779d755758a52d1f6635d990b8d98dc0a29fa568bbe0625f18fdf3/filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0", size = 16163 }, + { url = "https://files.pythonhosted.org/packages/89/ec/00d68c4ddfedfe64159999e5f8a98fb8442729a63e2077eb9dcd89623d27/filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338", size = 16164 }, ] [[package]] @@ -1203,11 +1189,11 @@ wheels = [ [[package]] name = "identify" -version = "2.6.5" +version = "2.6.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cf/92/69934b9ef3c31ca2470980423fda3d00f0460ddefdf30a67adf7f17e2e00/identify-2.6.5.tar.gz", hash = "sha256:c10b33f250e5bba374fae86fb57f3adcebf1161bce7cdf92031915fd480c13bc", size = 99213 } +sdist = { url = "https://files.pythonhosted.org/packages/82/bf/c68c46601bacd4c6fb4dd751a42b6e7087240eaabc6487f2ef7a48e0e8fc/identify-2.6.6.tar.gz", hash = "sha256:7bec12768ed44ea4761efb47806f0a41f86e7c0a5fdf5950d4648c90eca7e251", size = 99217 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/fa/dce098f4cdf7621aa8f7b4f919ce545891f489482f0bfa5102f3eca8608b/identify-2.6.5-py2.py3-none-any.whl", hash = "sha256:14181a47091eb75b337af4c23078c9d09225cd4c48929f521f3bf16b09d02566", size = 99078 }, + { url = "https://files.pythonhosted.org/packages/74/a1/68a395c17eeefb04917034bd0a1bfa765e7654fa150cca473d669aa3afb5/identify-2.6.6-py2.py3-none-any.whl", hash = "sha256:cbd1810bce79f8b671ecb20f53ee0ae8e86ae84b557de31d89709dc2a48ba881", size = 99083 }, ] [[package]] @@ -1302,14 +1288,14 @@ dev = [ [[package]] name = "importlib-metadata" -version = "8.4.0" +version = "8.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "zipp" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c0/bd/fa8ce65b0a7d4b6d143ec23b0f5fd3f7ab80121078c465bc02baeaab22dc/importlib_metadata-8.4.0.tar.gz", hash = "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5", size = 54320 } +sdist = { url = "https://files.pythonhosted.org/packages/cd/12/33e59336dca5be0c398a7482335911a33aa0e20776128f038019f1a95f1b/importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7", size = 55304 } wheels = [ - { url = "https://files.pythonhosted.org/packages/c0/14/362d31bf1076b21e1bcdcb0dc61944822ff263937b804a79231df2774d28/importlib_metadata-8.4.0-py3-none-any.whl", hash = "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1", size = 26269 }, + { url = "https://files.pythonhosted.org/packages/a0/d9/a1e041c5e7caa9a05c925f4bdbdfb7f006d1f74996af53467bc394c97be7/importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b", size = 26514 }, ] [[package]] @@ -1317,7 +1303,7 @@ name = "ipykernel" version = "6.29.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "appnope", marker = "platform_system == 'Darwin'" }, + { name = "appnope", marker = "sys_platform == 'darwin'" }, { name = "comm" }, { name = "debugpy" }, { name = "ipython" }, @@ -1911,7 +1897,7 @@ wheels = [ [[package]] name = "model2vec" -version = "0.3.5" +version = "0.3.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jinja2" }, @@ -1923,18 +1909,18 @@ dependencies = [ { name = "tokenizers" }, { name = "tqdm" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5b/0a/8b7874ca692e7d1eabb7b723d87309914b5f2a251945d21fcfa3f242dbd4/model2vec-0.3.5.tar.gz", hash = "sha256:437b13febcffac6d12ea50baa96f4e166f01e1dc487508d75a4a61e2774aa02e", size = 2305705 } +sdist = { url = "https://files.pythonhosted.org/packages/b5/b8/aabe8d02e9d3a3da03a0fe011a6769b7867d5861c22333c0ca1afd35eefe/model2vec-0.3.7.tar.gz", hash = "sha256:1f13532fcbad57da524fd3ae1580597cdd2bc5d76077dd4f87dfd2b5a411540e", size = 2305871 } wheels = [ - { url = "https://files.pythonhosted.org/packages/02/4d/b04cb7c65910ec5b224d56323376753220cc1a81015f084b913df6af2c50/model2vec-0.3.5-py3-none-any.whl", hash = "sha256:f6596dc0660c4bffa492cbd8445b1925b6bda04c12b7c4cc825d195325322748", size = 27515 }, + { url = "https://files.pythonhosted.org/packages/4b/07/f35b07c2d721e634a9ccf7af4a8edabfda2a6accc777b4e8547f8a41d22e/model2vec-0.3.7-py3-none-any.whl", hash = "sha256:5000a19d86e76f20afa4b403946f512a4c17496e35295b8855e728f4ba04ec89", size = 27695 }, ] [[package]] name = "more-itertools" -version = "10.5.0" +version = "10.6.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/51/78/65922308c4248e0eb08ebcbe67c95d48615cc6f27854b6f2e57143e9178f/more-itertools-10.5.0.tar.gz", hash = "sha256:5482bfef7849c25dc3c6dd53a6173ae4795da2a41a80faea6700d9f5846c5da6", size = 121020 } +sdist = { url = "https://files.pythonhosted.org/packages/88/3b/7fa1fe835e2e93fd6d7b52b2f95ae810cf5ba133e1845f726f5a992d62c2/more-itertools-10.6.0.tar.gz", hash = "sha256:2cd7fad1009c31cc9fb6a035108509e6547547a7a738374f10bd49a09eb3ee3b", size = 125009 } wheels = [ - { url = "https://files.pythonhosted.org/packages/48/7e/3a64597054a70f7c86eb0a7d4fc315b8c1ab932f64883a297bdffeb5f967/more_itertools-10.5.0-py3-none-any.whl", hash = "sha256:037b0d3203ce90cca8ab1defbbdac29d5f993fc20131f3664dc8d6acfa872aef", size = 60952 }, + { url = "https://files.pythonhosted.org/packages/23/62/0fe302c6d1be1c777cab0616e6302478251dfbf9055ad426f5d0def75c89/more_itertools-10.6.0-py3-none-any.whl", hash = "sha256:6eb054cb4b6db1473f6e15fcc676a08e4732548acd47c708f0e179c2c7c01e89", size = 63038 }, ] [[package]] @@ -2021,20 +2007,24 @@ wheels = [ [[package]] name = "murmurhash" -version = "1.0.11" +version = "1.0.12" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5b/71/01fc0866ce9015cc57c584922a0ecc842ec4ac704b442eff23779e6b9443/murmurhash-1.0.11.tar.gz", hash = "sha256:87ff68a255e54e7648d0729ff4130f43f7f38f03288a376e567934e16db93767", size = 13112 } +sdist = { url = "https://files.pythonhosted.org/packages/64/d9/e7c6a7d4e9b5320c17e54af6f9edd2f521c6f86bbbb72aba571f641a9793/murmurhash-1.0.12.tar.gz", hash = "sha256:467b7ee31c1f79f46d00436a1957fc52a0e5801369dd2f30eb7655f380735b5f", size = 13233 } wheels = [ - { url = "https://files.pythonhosted.org/packages/be/0d/5170cd2cf39cdcb804ca7ddd5bf7864112a217f7e6a318ac64fc23447820/murmurhash-1.0.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:185b2cd20b81fa876eaa2249faafd0b7b3d0c54ef04714e38135d9f482cf6ce9", size = 27062 }, - { url = "https://files.pythonhosted.org/packages/9a/18/7c37d4a97be0602fd9589a613128f5820742513d1cec1d4e491a7ba9d81a/murmurhash-1.0.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fd3083c6d977c2bc1e2f35ff999c39de43de09fd588f780243ec78debb316406", size = 27017 }, - { url = "https://files.pythonhosted.org/packages/26/33/59d6a0830fe2aa963c9b90b6c581ed7f9f073c0ac8929b4c6053fcdf19a1/murmurhash-1.0.11-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49a3cf4d26f7213d0f4a6c2c49496cbe9f78b30d56b1c3b17fbc74676372ea3f", size = 138536 }, - { url = "https://files.pythonhosted.org/packages/91/ae/4baacba15e8973d2db61558d56b731fe093e92a004735c2a683dcb988589/murmurhash-1.0.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a1bdb3c3fe32d93f7c461f11e6b2f7bbe64b3d70f56e48052490435853ed5c91", size = 128894 }, - { url = "https://files.pythonhosted.org/packages/6f/87/f2bc915ea04ba7ba11c550d80d0c3a31331e00ef4266bcf241110978b9b1/murmurhash-1.0.11-cp312-cp312-win_amd64.whl", hash = "sha256:0b507dd8ea10f3e5204b397ea9917a3a5f11756859d91406a8f485f18a411bdf", size = 25499 }, - { url = "https://files.pythonhosted.org/packages/e4/15/4b56961be5ff1072b31a14d9ca23e8b334c2adce466fa2ec77fe8644af63/murmurhash-1.0.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:036aea55d160d65698888a903fd2a19c4258be711f7bf2ab1b6cebdf41e09e09", size = 26416 }, - { url = "https://files.pythonhosted.org/packages/b9/60/8d80e3cd6a21e531ea5bbd4792fad8bb048e85bdaeb08e2503c49c000964/murmurhash-1.0.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:61f4b991b5bd88f5d57550a6328f8adb2f16656781e9eade9c16e55b41f6fab7", size = 26360 }, - { url = "https://files.pythonhosted.org/packages/41/3e/8480b420c0c03725863b6d13a9358f6814e27da7aa09176cdf8d82cbd3e4/murmurhash-1.0.11-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b5527ec305236a2ef404a38e0e57b1dc886a431e2032acf4c7ce3b17382c49ef", size = 133011 }, - { url = "https://files.pythonhosted.org/packages/8e/7c/92b67df028504d19c9c571eb87af52ce99c79629e2636dfcde245575d87f/murmurhash-1.0.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b26cf1be87c13fb242b9c252f11a25da71056c8fb5f22623e455129cce99592a", size = 124637 }, - { url = "https://files.pythonhosted.org/packages/2b/f5/5ce095d7edceea9e1a5c2c7000b33aa29e2bbc983c61eaa6e022a733c025/murmurhash-1.0.11-cp313-cp313-win_amd64.whl", hash = "sha256:24aba80a793bf371de70fffffc1f16c06810e4d8b90125b5bb762aabda3174d1", size = 24648 }, + { url = "https://files.pythonhosted.org/packages/38/c7/0dc2914c24adb9466b69606dfdee7bbfed13476f4dda3753e0185cfbbe1f/murmurhash-1.0.12-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1a4c97c8ffbedb62b760c3c2f77b5b8cb0e0ac0ec83a74d2f289e113e3e92ed5", size = 27120 }, + { url = "https://files.pythonhosted.org/packages/ae/d7/aea56101f225eb021cfd47245d55680605665b556aba95eecee937b4d4d6/murmurhash-1.0.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9574f0b634f059158bb89734a811e435ac9ad2335c02a7abb59f1875dcce244c", size = 27081 }, + { url = "https://files.pythonhosted.org/packages/f4/68/4b723e0f318e92b0b4779f41ff5d9446e1dc0e68aca2f0043e1fab3fc1be/murmurhash-1.0.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:701cc0ce91809b4d7c2e0518be759635205e1e181325792044f5a8118019f716", size = 138552 }, + { url = "https://files.pythonhosted.org/packages/13/40/eed53da76a428f404ec9db6d0983691c61d2744fea7070c6b31caca31ac4/murmurhash-1.0.12-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e1c9de2167a9d408d121ebc918bcb20b2718ec956f3aae0ded53d9bb224bb8e", size = 138589 }, + { url = "https://files.pythonhosted.org/packages/12/e8/1b9164e62f75bf23d6af5262421985f45bce9bd5c4970a62b83ea7cb62df/murmurhash-1.0.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:94a52972835bdae8af18147c67c398ff3ea1d875f5b8dca1e1aa0fadb892f546", size = 129244 }, + { url = "https://files.pythonhosted.org/packages/a7/20/c91f06d3692705bc7ec16c219143cc56062afd8080756d55e0678a7b704c/murmurhash-1.0.12-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cc88004c8615dcabe31d21142689f719fdf549ba782850bef389cf227a1df575", size = 128944 }, + { url = "https://files.pythonhosted.org/packages/b2/66/7d74a9f547dd719e86245e2a3d126140335861b8e362bdd22c7f9842a2b8/murmurhash-1.0.12-cp312-cp312-win_amd64.whl", hash = "sha256:8c5b8804c07a76f779e67f83aad37bc2189a0e65ebdd3f2b305242d489d31e03", size = 25554 }, + { url = "https://files.pythonhosted.org/packages/12/77/bec7e3f00b0e23bfa027704d4023fea808d8cc0e593dd4247f4579de6776/murmurhash-1.0.12-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:63f10c6d6ef9ee85073dd896d2c4e0ab161bc6b8e7e9201c69f8061f9f1b6468", size = 26474 }, + { url = "https://files.pythonhosted.org/packages/57/46/8dd3631cfb58435004678179a70352d3258b159c3f110e4f11fb23b1f776/murmurhash-1.0.12-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:66356f6308fd2a44a8ab056f020acd5bc22302f23ef5cce3705f2493e0fe9c3c", size = 26418 }, + { url = "https://files.pythonhosted.org/packages/50/8f/ae8ee91c1b9ecdc4d849382af64b10e5d3c79ee7fcf8af13400d32092ae7/murmurhash-1.0.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdb2104aa3471324724abf5a3a76fc94bcbeaf023bb6a6dd94da567b8633d8a6", size = 133342 }, + { url = "https://files.pythonhosted.org/packages/cd/19/3ce034b0c068e8f88ea0ac28e196359aacf3c52718fbce1f7dbcf088261f/murmurhash-1.0.12-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a7ef5fb37e72536458ac4a6f486fb374c60ac4c4862d9195d3d4b58239a91de", size = 133062 }, + { url = "https://files.pythonhosted.org/packages/a0/0c/f9a868eb39751b9dceb9e35d91e8cf321dad8ce9e3e965d067b0fff0547a/murmurhash-1.0.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8bd5524de195991ce3551b14286ec0b730cc9dd2e10565dad2ae470eec082028", size = 124858 }, + { url = "https://files.pythonhosted.org/packages/b6/fc/52bcb3afc95733f30ec76e07cae4b5d0081fa049ade418303faeee619766/murmurhash-1.0.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:19de30edaaa2217cd0c41b6cf6bbfa418be5d7fdf267ca92e5e3710d4daac593", size = 124686 }, + { url = "https://files.pythonhosted.org/packages/cf/99/9cdea62dec8ea26a35a8231ee09c83b16f9dedf16280a7a15f41d2061706/murmurhash-1.0.12-cp313-cp313-win_amd64.whl", hash = "sha256:7dc4ebdfed7ef8ed70519962ac9b704e91978ee14e049f1ff37bca2f579ce84d", size = 24702 }, ] [[package]] @@ -2198,7 +2188,7 @@ wheels = [ [[package]] name = "openai" -version = "1.59.7" +version = "1.59.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -2210,9 +2200,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f9/d5/25cf04789c7929b476c4d9ef711f8979091db63d30bfc093828fe4bf5c72/openai-1.59.7.tar.gz", hash = "sha256:043603def78c00befb857df9f0a16ee76a3af5984ba40cb7ee5e2f40db4646bf", size = 345007 } +sdist = { url = "https://files.pythonhosted.org/packages/ec/2d/04faa92bac0341649223398503db4415d2f658a757d9d32bb68f3378ddd0/openai-1.59.9.tar.gz", hash = "sha256:ec1a20b0351b4c3e65c6292db71d8233515437c6065efd4fd50edeb55df5f5d2", size = 347134 } wheels = [ - { url = "https://files.pythonhosted.org/packages/6d/47/7b92f1731c227f4139ef0025b5996062e44f9a749c54315c8bdb34bad5ec/openai-1.59.7-py3-none-any.whl", hash = "sha256:cfa806556226fa96df7380ab2e29814181d56fea44738c2b0e581b462c268692", size = 454844 }, + { url = "https://files.pythonhosted.org/packages/07/b4/57f1954a4560092ad8c45f07ad183eab9c8e093e0a1db829f9b506b2d5d1/openai-1.59.9-py3-none-any.whl", hash = "sha256:61a0608a1313c08ddf92fe793b6dbd1630675a1fe3866b2f96447ce30050c448", size = 455527 }, ] [[package]] @@ -2277,42 +2267,42 @@ wheels = [ [[package]] name = "opentelemetry-api" -version = "1.27.0" +version = "1.29.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "deprecated" }, { name = "importlib-metadata" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c9/83/93114b6de85a98963aec218a51509a52ed3f8de918fe91eb0f7299805c3f/opentelemetry_api-1.27.0.tar.gz", hash = "sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342", size = 62693 } +sdist = { url = "https://files.pythonhosted.org/packages/bc/8e/b886a5e9861afa188d1fe671fb96ff9a1d90a23d57799331e137cc95d573/opentelemetry_api-1.29.0.tar.gz", hash = "sha256:d04a6cf78aad09614f52964ecb38021e248f5714dc32c2e0d8fd99517b4d69cf", size = 62900 } wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/1f/737dcdbc9fea2fa96c1b392ae47275165a7c641663fbb08a8d252968eed2/opentelemetry_api-1.27.0-py3-none-any.whl", hash = "sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7", size = 63970 }, + { url = "https://files.pythonhosted.org/packages/43/53/5249ea860d417a26a3a6f1bdedfc0748c4f081a3adaec3d398bc0f7c6a71/opentelemetry_api-1.29.0-py3-none-any.whl", hash = "sha256:5fcd94c4141cc49c736271f3e1efb777bebe9cc535759c54c936cca4f1b312b8", size = 64304 }, ] [[package]] name = "opentelemetry-sdk" -version = "1.27.0" +version = "1.29.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-semantic-conventions" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0d/9a/82a6ac0f06590f3d72241a587cb8b0b751bd98728e896cc4cbd4847248e6/opentelemetry_sdk-1.27.0.tar.gz", hash = "sha256:d525017dea0ccce9ba4e0245100ec46ecdc043f2d7b8315d56b19aff0904fa6f", size = 145019 } +sdist = { url = "https://files.pythonhosted.org/packages/0c/5a/1ed4c3cf6c09f80565fc085f7e8efa0c222712fd2a9412d07424705dcf72/opentelemetry_sdk-1.29.0.tar.gz", hash = "sha256:b0787ce6aade6ab84315302e72bd7a7f2f014b0fb1b7c3295b88afe014ed0643", size = 157229 } wheels = [ - { url = "https://files.pythonhosted.org/packages/c1/bd/a6602e71e315055d63b2ff07172bd2d012b4cba2d4e00735d74ba42fc4d6/opentelemetry_sdk-1.27.0-py3-none-any.whl", hash = "sha256:365f5e32f920faf0fd9e14fdfd92c086e317eaa5f860edba9cdc17a380d9197d", size = 110505 }, + { url = "https://files.pythonhosted.org/packages/d1/1d/512b86af21795fb463726665e2f61db77d384e8779fdcf4cb0ceec47866d/opentelemetry_sdk-1.29.0-py3-none-any.whl", hash = "sha256:173be3b5d3f8f7d671f20ea37056710217959e774e2749d984355d1f9391a30a", size = 118078 }, ] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.48b0" +version = "0.50b0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "deprecated" }, { name = "opentelemetry-api" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0a/89/1724ad69f7411772446067cdfa73b598694c8c91f7f8c922e344d96d81f9/opentelemetry_semantic_conventions-0.48b0.tar.gz", hash = "sha256:12d74983783b6878162208be57c9effcb89dc88691c64992d70bb89dc00daa1a", size = 89445 } +sdist = { url = "https://files.pythonhosted.org/packages/e7/4e/d7c7c91ff47cd96fe4095dd7231701aec7347426fd66872ff320d6cd1fcc/opentelemetry_semantic_conventions-0.50b0.tar.gz", hash = "sha256:02dc6dbcb62f082de9b877ff19a3f1ffaa3c306300fa53bfac761c4567c83d38", size = 100459 } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/7a/4f0063dbb0b6c971568291a8bc19a4ca70d3c185db2d956230dd67429dfc/opentelemetry_semantic_conventions-0.48b0-py3-none-any.whl", hash = "sha256:a0de9f45c413a8669788a38569c7e0a11ce6ce97861a628cca785deecdc32a1f", size = 149685 }, + { url = "https://files.pythonhosted.org/packages/da/fb/dc15fad105450a015e913cfa4f5c27b6a5f1bea8fb649f8cae11e699c8af/opentelemetry_semantic_conventions-0.50b0-py3-none-any.whl", hash = "sha256:e87efba8fdb67fb38113efea6a349531e75ed7ffc01562f65b802fcecb5e115e", size = 166602 }, ] [[package]] @@ -2476,7 +2466,7 @@ name = "portalocker" version = "2.10.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pywin32", marker = "platform_system == 'Windows'" }, + { name = "pywin32", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ed/d3/c6c64067759e87af98cc668c1cc75171347d0f1577fab7ca3749134e3cd4/portalocker-2.10.1.tar.gz", hash = "sha256:ef1bf844e878ab08aee7e40184156e1151f228f103aa5c6bd0724cc330960f8f", size = 40891 } wheels = [ @@ -2501,7 +2491,7 @@ wheels = [ [[package]] name = "pre-commit" -version = "4.0.1" +version = "4.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cfgv" }, @@ -2510,9 +2500,9 @@ dependencies = [ { name = "pyyaml" }, { name = "virtualenv" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2e/c8/e22c292035f1bac8b9f5237a2622305bc0304e776080b246f3df57c4ff9f/pre_commit-4.0.1.tar.gz", hash = "sha256:80905ac375958c0444c65e9cebebd948b3cdb518f335a091a670a89d652139d2", size = 191678 } +sdist = { url = "https://files.pythonhosted.org/packages/2a/13/b62d075317d8686071eb843f0bb1f195eb332f48869d3c31a4c6f1e063ac/pre_commit-4.1.0.tar.gz", hash = "sha256:ae3f018575a588e30dfddfab9a05448bfbd6b73d78709617b5a2b853549716d4", size = 193330 } wheels = [ - { url = "https://files.pythonhosted.org/packages/16/8f/496e10d51edd6671ebe0432e33ff800aa86775d2d147ce7d43389324a525/pre_commit-4.0.1-py2.py3-none-any.whl", hash = "sha256:efde913840816312445dc98787724647c65473daefe420785f885e8ed9a06878", size = 218713 }, + { url = "https://files.pythonhosted.org/packages/43/b3/df14c580d82b9627d173ceea305ba898dca135feb360b6d84019d0803d3b/pre_commit-4.1.0-py2.py3-none-any.whl", hash = "sha256:d29e7cb346295bcc1cc75fc3e92e343495e3ea0196c9ec6ba53f49f10ab6ae7b", size = 220560 }, ] [[package]] @@ -2543,14 +2533,14 @@ wheels = [ [[package]] name = "prompt-toolkit" -version = "3.0.48" +version = "3.0.50" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "wcwidth" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2d/4f/feb5e137aff82f7c7f3248267b97451da3644f6cdc218edfe549fb354127/prompt_toolkit-3.0.48.tar.gz", hash = "sha256:d6623ab0477a80df74e646bdbc93621143f5caf104206aa29294d53de1a03d90", size = 424684 } +sdist = { url = "https://files.pythonhosted.org/packages/a1/e1/bd15cb8ffdcfeeb2bdc215de3c3cffca11408d829e4b8416dcfe71ba8854/prompt_toolkit-3.0.50.tar.gz", hash = "sha256:544748f3860a2623ca5cd6d2795e7a14f3d0e1c3c9728359013f79877fc89bab", size = 429087 } wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/6a/fd08d94654f7e67c52ca30523a178b3f8ccc4237fce4be90d39c938a831a/prompt_toolkit-3.0.48-py3-none-any.whl", hash = "sha256:f49a827f90062e411f1ce1f854f2aedb3c23353244f8108b89283587397ac10e", size = 386595 }, + { url = "https://files.pythonhosted.org/packages/e4/ea/d836f008d33151c7a1f62caf3d8dd782e4d15f6a43897f64480c2b8de2ad/prompt_toolkit-3.0.50-py3-none-any.whl", hash = "sha256:9b6427eb19e479d98acff65196a307c555eb567989e6d88ebbb1b509d9779198", size = 387816 }, ] [[package]] @@ -2625,15 +2615,15 @@ wheels = [ [[package]] name = "psycopg" -version = "3.2.3" +version = "3.2.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.13'" }, { name = "tzdata", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d1/ad/7ce016ae63e231575df0498d2395d15f005f05e32d3a2d439038e1bd0851/psycopg-3.2.3.tar.gz", hash = "sha256:a5764f67c27bec8bfac85764d23c534af2c27b893550377e37ce59c12aac47a2", size = 155550 } +sdist = { url = "https://files.pythonhosted.org/packages/e0/f2/954b1467b3e2ca5945b83b5e320268be1f4df486c3e8ffc90f4e4b707979/psycopg-3.2.4.tar.gz", hash = "sha256:f26f1346d6bf1ef5f5ef1714dd405c67fb365cfd1c6cea07de1792747b167b92", size = 156109 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/21/534b8f5bd9734b7a2fcd3a16b1ee82ef6cad81a4796e95ebf4e0c6a24119/psycopg-3.2.3-py3-none-any.whl", hash = "sha256:644d3973fe26908c73d4be746074f6e5224b03c1101d302d9a53bf565ad64907", size = 197934 }, + { url = "https://files.pythonhosted.org/packages/40/49/15114d5f7ee68983f4e1a24d47e75334568960352a07c6f0e796e912685d/psycopg-3.2.4-py3-none-any.whl", hash = "sha256:43665368ccd48180744cab26b74332f46b63b7e06e8ce0775547a3533883d381", size = 198716 }, ] [[package]] @@ -2787,17 +2777,17 @@ sdist = { url = "https://files.pythonhosted.org/packages/ce/af/409edba35fc597f1e [[package]] name = "pymupdf" -version = "1.25.1" +version = "1.25.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c3/88/76c076c152be6d29a792defc3b3bff73de7f690e55f978b66adf6dbb8a1a/pymupdf-1.25.1.tar.gz", hash = "sha256:6725bec0f37c2380d926f792c262693c926af7cc1aa5aa2b8207e771867f015a", size = 60979390 } +sdist = { url = "https://files.pythonhosted.org/packages/40/fc/dd8776dc5c2f8cf0e51cf81a5f1de3840996bed7ca03ec768b0733024fb9/pymupdf-1.25.2.tar.gz", hash = "sha256:9ea88ff1b3ccb359620f106a6fd5ba6877d959d21d78272052c3496ceede6eec", size = 63814915 } wheels = [ - { url = "https://files.pythonhosted.org/packages/92/7b/e7205ea48f547122c226a34f5452bc72915b6d06d7925970b8dd3493baf1/pymupdf-1.25.1-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:793f9f6d51029e97851c711b3f6d9fe912313d95a306fbe8b1866f301d0e2bd3", size = 19364135 }, - { url = "https://files.pythonhosted.org/packages/0e/b6/2ad245dcbbb1abae9eeb8de5049b27c12c9ee8590c6c769499e386164bd6/pymupdf-1.25.1-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:15e6f4013ad0a029a2221920f9d2081f56dc43259dabfdf5cad7fbf1cee4b5a7", size = 18598176 }, - { url = "https://files.pythonhosted.org/packages/32/bf/d7697604ea2b1fe299c7bdf4b57e3549693ce73f75c44e890cfd34837d23/pymupdf-1.25.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a39afbd80381f43e30d6eb2ec4613f465f507ac2b76070abdd2da8724f32ef36", size = 19458090 }, - { url = "https://files.pythonhosted.org/packages/77/15/7bf672afb99002ad813aeb4886cc601bb9a4629210d9a3906a8d5650a941/pymupdf-1.25.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b63f8e9e65b0bda48f9217efd4d2a8c6d7a739dd28baf460c1ae78439b9af489", size = 20021618 }, - { url = "https://files.pythonhosted.org/packages/8c/e3/1a7a8400f1688c3c782478635ca929f85facd266157e4b90d650766bc49d/pymupdf-1.25.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a687bd387589e30abd810a78a23341f57f43fa16a4d8d8c0b870bb6d89607343", size = 21144453 }, - { url = "https://files.pythonhosted.org/packages/a1/d1/440b267842a1374f8d55c508302882f2ef7dd0f859514f060e1618ef97aa/pymupdf-1.25.1-cp39-abi3-win32.whl", hash = "sha256:fc7dbc1aa9e298a4c81084e389c9623c26fcaa232c71efaa073af150069e2221", size = 15112052 }, - { url = "https://files.pythonhosted.org/packages/46/72/8c5bbf817aacebe21a454f3ade8ee4b5b17afe698bb73d65c4ca23a89a87/pymupdf-1.25.1-cp39-abi3-win_amd64.whl", hash = "sha256:e2b0b73c0aab0f863e5132c93cfa4607e8129feb1afa3d544b2cf7f172c50b5a", size = 16559080 }, + { url = "https://files.pythonhosted.org/packages/24/34/8c3d82719d118beb48fded78fcab7cbe9ac3bf1906dc87a9ca4fd950087d/pymupdf-1.25.2-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:59dea22b633cc4fc13670b4c5db50d71f8cd4f420814420f33ce47ddcb61e1f6", size = 19336722 }, + { url = "https://files.pythonhosted.org/packages/4f/ec/c7f742f56ee42be27b3afdbf3364da12f03e309f6638e666a7816d9eef23/pymupdf-1.25.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:e8b8a874497cd0deee89a6a4fb76a3a08173c8d39e88fc7cf715764ec5a243e9", size = 18570847 }, + { url = "https://files.pythonhosted.org/packages/9d/27/557ee235aded5185e4824459e1540142fbb9323e1b83f77cbefe2e2c4e1e/pymupdf-1.25.2-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f61e5cdb25b86eb28d34aa3557b49ecf9e361d5f5cd3b1660406f8f0bf813af7", size = 19430802 }, + { url = "https://files.pythonhosted.org/packages/0e/de/35fde3d49e0d187b95ab64cc61b4d275ebc7fd4f45e152b206b0e17e6b69/pymupdf-1.25.2-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ae8cfa7a97d78f813d286ecba32369059d88073edd1e5cf105f4cd0811f71925", size = 19994315 }, + { url = "https://files.pythonhosted.org/packages/9d/d3/a8a09b550c62306c76e1c2d892c0890287470164d7941aea35330cceee4d/pymupdf-1.25.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:295505fe1ecb7c7b57d4124d373e207ea311d8e40bc7ac3016d8ec2d60b091e9", size = 21117143 }, + { url = "https://files.pythonhosted.org/packages/ef/ac/fc4f37c7620a20d25443868ed665291e96f283eda068cda673e9edebf5f0/pymupdf-1.25.2-cp39-abi3-win32.whl", hash = "sha256:b9488c8b82bb9be36fb13ee0c8d43b0ddcc50af83b61da01e6040413d9e67da6", size = 15084555 }, + { url = "https://files.pythonhosted.org/packages/64/8e/1d0ff215b37343c7e0bec4d571f1413e4f76a416591276b97081f1814710/pymupdf-1.25.2-cp39-abi3-win_amd64.whl", hash = "sha256:1b4ca6f5780d319a08dff885a5a0e3585c5d7af04dcfa063c535b88371fd91c1", size = 16531823 }, ] [[package]] @@ -3164,27 +3154,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.9.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/67/3e/e89f736f01aa9517a97e2e7e0ce8d34a4d8207087b3cfdec95133fee13b5/ruff-0.9.1.tar.gz", hash = "sha256:fd2b25ecaf907d6458fa842675382c8597b3c746a2dde6717fe3415425df0c17", size = 3498844 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/05/c3a2e0feb3d5d394cdfd552de01df9d3ec8a3a3771bbff247fab7e668653/ruff-0.9.1-py3-none-linux_armv6l.whl", hash = "sha256:84330dda7abcc270e6055551aca93fdde1b0685fc4fd358f26410f9349cf1743", size = 10645241 }, - { url = "https://files.pythonhosted.org/packages/dd/da/59f0a40e5f88ee5c054ad175caaa2319fc96571e1d29ab4730728f2aad4f/ruff-0.9.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3cae39ba5d137054b0e5b472aee3b78a7c884e61591b100aeb544bcd1fc38d4f", size = 10391066 }, - { url = "https://files.pythonhosted.org/packages/b7/fe/85e1c1acf0ba04a3f2d54ae61073da030f7a5dc386194f96f3c6ca444a78/ruff-0.9.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:50c647ff96f4ba288db0ad87048257753733763b409b2faf2ea78b45c8bb7fcb", size = 10012308 }, - { url = "https://files.pythonhosted.org/packages/6f/9b/780aa5d4bdca8dcea4309264b8faa304bac30e1ce0bcc910422bfcadd203/ruff-0.9.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0c8b149e9c7353cace7d698e1656ffcf1e36e50f8ea3b5d5f7f87ff9986a7ca", size = 10881960 }, - { url = "https://files.pythonhosted.org/packages/12/f4/dac4361afbfe520afa7186439e8094e4884ae3b15c8fc75fb2e759c1f267/ruff-0.9.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:beb3298604540c884d8b282fe7625651378e1986c25df51dec5b2f60cafc31ce", size = 10414803 }, - { url = "https://files.pythonhosted.org/packages/f0/a2/057a3cb7999513cb78d6cb33a7d1cc6401c82d7332583786e4dad9e38e44/ruff-0.9.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:39d0174ccc45c439093971cc06ed3ac4dc545f5e8bdacf9f067adf879544d969", size = 11464929 }, - { url = "https://files.pythonhosted.org/packages/eb/c6/1ccfcc209bee465ced4874dcfeaadc88aafcc1ea9c9f31ef66f063c187f0/ruff-0.9.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:69572926c0f0c9912288915214ca9b2809525ea263603370b9e00bed2ba56dbd", size = 12170717 }, - { url = "https://files.pythonhosted.org/packages/84/97/4a524027518525c7cf6931e9fd3b2382be5e4b75b2b61bec02681a7685a5/ruff-0.9.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:937267afce0c9170d6d29f01fcd1f4378172dec6760a9f4dface48cdabf9610a", size = 11708921 }, - { url = "https://files.pythonhosted.org/packages/a6/a4/4e77cf6065c700d5593b25fca6cf725b1ab6d70674904f876254d0112ed0/ruff-0.9.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:186c2313de946f2c22bdf5954b8dd083e124bcfb685732cfb0beae0c47233d9b", size = 13058074 }, - { url = "https://files.pythonhosted.org/packages/f9/d6/fcb78e0531e863d0a952c4c5600cc5cd317437f0e5f031cd2288b117bb37/ruff-0.9.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f94942a3bb767675d9a051867c036655fe9f6c8a491539156a6f7e6b5f31831", size = 11281093 }, - { url = "https://files.pythonhosted.org/packages/e4/3b/7235bbeff00c95dc2d073cfdbf2b871b5bbf476754c5d277815d286b4328/ruff-0.9.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:728d791b769cc28c05f12c280f99e8896932e9833fef1dd8756a6af2261fd1ab", size = 10882610 }, - { url = "https://files.pythonhosted.org/packages/2a/66/5599d23257c61cf038137f82999ca8f9d0080d9d5134440a461bef85b461/ruff-0.9.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2f312c86fb40c5c02b44a29a750ee3b21002bd813b5233facdaf63a51d9a85e1", size = 10489273 }, - { url = "https://files.pythonhosted.org/packages/78/85/de4aa057e2532db0f9761e2c2c13834991e087787b93e4aeb5f1cb10d2df/ruff-0.9.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ae017c3a29bee341ba584f3823f805abbe5fe9cd97f87ed07ecbf533c4c88366", size = 11003314 }, - { url = "https://files.pythonhosted.org/packages/00/42/afedcaa089116d81447347f76041ff46025849fedb0ed2b187d24cf70fca/ruff-0.9.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5dc40a378a0e21b4cfe2b8a0f1812a6572fc7b230ef12cd9fac9161aa91d807f", size = 11342982 }, - { url = "https://files.pythonhosted.org/packages/39/c6/fe45f3eb27e3948b41a305d8b768e949bf6a39310e9df73f6c576d7f1d9f/ruff-0.9.1-py3-none-win32.whl", hash = "sha256:46ebf5cc106cf7e7378ca3c28ce4293b61b449cd121b98699be727d40b79ba72", size = 8819750 }, - { url = "https://files.pythonhosted.org/packages/38/8d/580db77c3b9d5c3d9479e55b0b832d279c30c8f00ab0190d4cd8fc67831c/ruff-0.9.1-py3-none-win_amd64.whl", hash = "sha256:342a824b46ddbcdddd3abfbb332fa7fcaac5488bf18073e841236aadf4ad5c19", size = 9701331 }, - { url = "https://files.pythonhosted.org/packages/b2/94/0498cdb7316ed67a1928300dd87d659c933479f44dec51b4f62bfd1f8028/ruff-0.9.1-py3-none-win_arm64.whl", hash = "sha256:1cd76c7f9c679e6e8f2af8f778367dca82b95009bc7b1a85a47f1521ae524fa7", size = 9145708 }, +version = "0.9.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/80/63/77ecca9d21177600f551d1c58ab0e5a0b260940ea7312195bd2a4798f8a8/ruff-0.9.2.tar.gz", hash = "sha256:b5eceb334d55fae5f316f783437392642ae18e16dcf4f1858d55d3c2a0f8f5d0", size = 3553799 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/b9/0e168e4e7fb3af851f739e8f07889b91d1a33a30fca8c29fa3149d6b03ec/ruff-0.9.2-py3-none-linux_armv6l.whl", hash = "sha256:80605a039ba1454d002b32139e4970becf84b5fee3a3c3bf1c2af6f61a784347", size = 11652408 }, + { url = "https://files.pythonhosted.org/packages/2c/22/08ede5db17cf701372a461d1cb8fdde037da1d4fa622b69ac21960e6237e/ruff-0.9.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b9aab82bb20afd5f596527045c01e6ae25a718ff1784cb92947bff1f83068b00", size = 11587553 }, + { url = "https://files.pythonhosted.org/packages/42/05/dedfc70f0bf010230229e33dec6e7b2235b2a1b8cbb2a991c710743e343f/ruff-0.9.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fbd337bac1cfa96be615f6efcd4bc4d077edbc127ef30e2b8ba2a27e18c054d4", size = 11020755 }, + { url = "https://files.pythonhosted.org/packages/df/9b/65d87ad9b2e3def67342830bd1af98803af731243da1255537ddb8f22209/ruff-0.9.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b35259b0cbf8daa22a498018e300b9bb0174c2bbb7bcba593935158a78054d", size = 11826502 }, + { url = "https://files.pythonhosted.org/packages/93/02/f2239f56786479e1a89c3da9bc9391120057fc6f4a8266a5b091314e72ce/ruff-0.9.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b6a9701d1e371bf41dca22015c3f89769da7576884d2add7317ec1ec8cb9c3c", size = 11390562 }, + { url = "https://files.pythonhosted.org/packages/c9/37/d3a854dba9931f8cb1b2a19509bfe59e00875f48ade632e95aefcb7a0aee/ruff-0.9.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9cc53e68b3c5ae41e8faf83a3b89f4a5d7b2cb666dff4b366bb86ed2a85b481f", size = 12548968 }, + { url = "https://files.pythonhosted.org/packages/fa/c3/c7b812bb256c7a1d5553433e95980934ffa85396d332401f6b391d3c4569/ruff-0.9.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8efd9da7a1ee314b910da155ca7e8953094a7c10d0c0a39bfde3fcfd2a015684", size = 13187155 }, + { url = "https://files.pythonhosted.org/packages/bd/5a/3c7f9696a7875522b66aa9bba9e326e4e5894b4366bd1dc32aa6791cb1ff/ruff-0.9.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3292c5a22ea9a5f9a185e2d131dc7f98f8534a32fb6d2ee7b9944569239c648d", size = 12704674 }, + { url = "https://files.pythonhosted.org/packages/be/d6/d908762257a96ce5912187ae9ae86792e677ca4f3dc973b71e7508ff6282/ruff-0.9.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a605fdcf6e8b2d39f9436d343d1f0ff70c365a1e681546de0104bef81ce88df", size = 14529328 }, + { url = "https://files.pythonhosted.org/packages/2d/c2/049f1e6755d12d9cd8823242fa105968f34ee4c669d04cac8cea51a50407/ruff-0.9.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c547f7f256aa366834829a08375c297fa63386cbe5f1459efaf174086b564247", size = 12385955 }, + { url = "https://files.pythonhosted.org/packages/91/5a/a9bdb50e39810bd9627074e42743b00e6dc4009d42ae9f9351bc3dbc28e7/ruff-0.9.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d18bba3d3353ed916e882521bc3e0af403949dbada344c20c16ea78f47af965e", size = 11810149 }, + { url = "https://files.pythonhosted.org/packages/e5/fd/57df1a0543182f79a1236e82a79c68ce210efb00e97c30657d5bdb12b478/ruff-0.9.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b338edc4610142355ccf6b87bd356729b62bf1bc152a2fad5b0c7dc04af77bfe", size = 11479141 }, + { url = "https://files.pythonhosted.org/packages/dc/16/bc3fd1d38974f6775fc152a0554f8c210ff80f2764b43777163c3c45d61b/ruff-0.9.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:492a5e44ad9b22a0ea98cf72e40305cbdaf27fac0d927f8bc9e1df316dcc96eb", size = 12014073 }, + { url = "https://files.pythonhosted.org/packages/47/6b/e4ca048a8f2047eb652e1e8c755f384d1b7944f69ed69066a37acd4118b0/ruff-0.9.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:af1e9e9fe7b1f767264d26b1075ac4ad831c7db976911fa362d09b2d0356426a", size = 12435758 }, + { url = "https://files.pythonhosted.org/packages/c2/40/4d3d6c979c67ba24cf183d29f706051a53c36d78358036a9cd21421582ab/ruff-0.9.2-py3-none-win32.whl", hash = "sha256:71cbe22e178c5da20e1514e1e01029c73dc09288a8028a5d3446e6bba87a5145", size = 9796916 }, + { url = "https://files.pythonhosted.org/packages/c3/ef/7f548752bdb6867e6939489c87fe4da489ab36191525fadc5cede2a6e8e2/ruff-0.9.2-py3-none-win_amd64.whl", hash = "sha256:c5e1d6abc798419cf46eed03f54f2e0c3adb1ad4b801119dedf23fcaf69b55b5", size = 10773080 }, + { url = "https://files.pythonhosted.org/packages/0e/4e/33df635528292bd2d18404e4daabcd74ca8a9853b2e1df85ed3d32d24362/ruff-0.9.2-py3-none-win_arm64.whl", hash = "sha256:a1b63fa24149918f8b37cef2ee6fff81f24f0d74b6f0bdc37bc3e1f2143e41c6", size = 10001738 }, ] [[package]] @@ -3432,11 +3422,11 @@ wheels = [ [[package]] name = "sqlglot" -version = "26.1.3" +version = "26.2.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1b/02/60d542ff60b98ed444176f655a43ecd8c06e9d1f1d38abac3266a41a7eec/sqlglot-26.1.3.tar.gz", hash = "sha256:01fe1a31786e6c7b1ce02470942dfd5fbfd403b7c2d78d9fc4e8aad9eddba2ef", size = 19858552 } +sdist = { url = "https://files.pythonhosted.org/packages/92/63/24b0c17c9bd567b10b9c7282259cbde9a9c1fc768b0ca77b996a590de77a/sqlglot-26.2.1.tar.gz", hash = "sha256:82dd5ba9f60c664ed073cd365cccbc48d04b28ddba9cddd3419f29dc6e76df08", size = 19933689 } wheels = [ - { url = "https://files.pythonhosted.org/packages/71/fe/4521660e276a69f23f7773f52107a1c5ca079cdfaac7c09fb602b60a73c0/sqlglot-26.1.3-py3-none-any.whl", hash = "sha256:e64d696eedb917a0770a10bc0f2a0ce4dffdf95c4fd36cd66e44da3bf2c298c1", size = 439637 }, + { url = "https://files.pythonhosted.org/packages/ed/50/4aca824214afea433d9827afc4f4f9640ab50b7d0ac45a5aee286193469a/sqlglot-26.2.1-py3-none-any.whl", hash = "sha256:f5177482cc00997f9b7af886af23fcae8de827795a075c27c20296bdfdb9a522", size = 443283 }, ] [package.optional-dependencies] @@ -3446,30 +3436,30 @@ rs = [ [[package]] name = "sqlglotrs" -version = "0.3.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/55/9f/65c61093912e171601729af04cf06163a0275bd60dec5a73c2be2343c38c/sqlglotrs-0.3.4.tar.gz", hash = "sha256:74aebb4b2a8f4795488ac23b3ae2083f0984a8923b5ea151f34495cbe42ff1b9", size = 15326 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ba/0f/e8e2e84fa71841d7cffae554a07ffacdfe28dbc8be16dbf05293a1dfd956/sqlglotrs-0.3.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:660b505575dbade7a42eb5595c7cc42efccfb478a1ea4bf1200be7da78afe07a", size = 296791 }, - { url = "https://files.pythonhosted.org/packages/2b/fe/6f830db0d200cb67620710e886a15d1a4536cf87f53fb761e7a0615992a8/sqlglotrs-0.3.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1378a817535d36334814b404f0611d949d3f971c6c308c2e301da5ef6a750ee6", size = 285105 }, - { url = "https://files.pythonhosted.org/packages/bb/bd/080acb80984e624f31f22cdd8b6205ae62d83ae5e5f5dccf78860fd5fdf9/sqlglotrs-0.3.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7928dace33305f02fa99d568955ec4e3802834e76998db2695293ea0358fd3d", size = 323586 }, - { url = "https://files.pythonhosted.org/packages/9e/54/db7bdf5f3facfc9223b6c2c041488e91556ce5b41fd2c5c8592eaae23d11/sqlglotrs-0.3.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dd9a6064bbfbb3634831eada051678dcffad7e6b939b5ad481a02f2a1ed7243d", size = 333368 }, - { url = "https://files.pythonhosted.org/packages/21/11/bb33f0844ac8dd3ce5b12124233f501664dded9ecc8ed955bb6466c4238b/sqlglotrs-0.3.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cc43e5385238fbcf5f2cffe01007856732d51f651ae92021535851ba1529352", size = 372484 }, - { url = "https://files.pythonhosted.org/packages/08/f8/005c8797e710c6a2b2590a0400a191e980282d29380fcd719bfd188418f5/sqlglotrs-0.3.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5306cee54099fbd65a87e589aa827b2741088f3e18ae4c3057aca3f78f484fd5", size = 379553 }, - { url = "https://files.pythonhosted.org/packages/0d/36/e138813825f6d698ce5687bce4456bd0e9c8bf80468bf4bec6b8db5b3884/sqlglotrs-0.3.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d6bc103b23cf33d396ad8d6abd649d36855ebdee93b684f0383c2a907486e11", size = 329609 }, - { url = "https://files.pythonhosted.org/packages/6f/f0/49cfaa4fe297a3824992a88d61ea952d17b92d10592feb6d4bf35a369bc9/sqlglotrs-0.3.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4986b2d09f9c844cfb79b9e4e6da027869ac9550727d58a03cf17a99a7a79d07", size = 350040 }, - { url = "https://files.pythonhosted.org/packages/fe/fc/7d75ec43959e4751942b83fe26fe215a9a7d3e820eb3c8ac6cf32359b2a7/sqlglotrs-0.3.4-cp312-cp312-win32.whl", hash = "sha256:99f4b835aa48c51455389254a14ded5d371ac79fbd77ce9b734e6bf31a390e4f", size = 178183 }, - { url = "https://files.pythonhosted.org/packages/ef/c3/9e079adf1c426cb95b374e2c197ef40ad496167db1d5af99e427aeae0269/sqlglotrs-0.3.4-cp312-cp312-win_amd64.whl", hash = "sha256:e0d3aa68b7bc008d6a183a45cdbc573ded8b66727d700de9050d2bf0703cbf6b", size = 190403 }, - { url = "https://files.pythonhosted.org/packages/ea/63/5e9141e7304e4554bcb0edb0d272650609ce6a770e08bc656d0ac2bd7c40/sqlglotrs-0.3.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7a3e6b86c1f12adb96ce4bbfe11b00ec53b3dee07a9da68eb5bcc7ef9b544c11", size = 296316 }, - { url = "https://files.pythonhosted.org/packages/1a/83/020df139cd29f737fcfc544337a63c8354325c2218dadd15891f73bc4f3e/sqlglotrs-0.3.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:779ee5e0e2d3dc9dfa09d8fe0cf1635524335ef00e03f0d6b173733a911f5623", size = 284551 }, - { url = "https://files.pythonhosted.org/packages/c6/94/5bfecd4198cde739f0234d23cc90c8086104d08714d0e9430fb658b3573f/sqlglotrs-0.3.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:038aa86bfa3b9ee20ec26a1d348f69b6443c6435289802c3828bb63e3cd11bd1", size = 323243 }, - { url = "https://files.pythonhosted.org/packages/fb/9e/34f23308de53ddc9a4a2a29eefe3d6a9cf181f3ecc0e7fc0d65234814b3c/sqlglotrs-0.3.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03f28a4cc3076b878a6fc8f7413d1ede9d226ee5ac3cc416b7323fbdd53e24f5", size = 332791 }, - { url = "https://files.pythonhosted.org/packages/8b/e4/1879c97f237f7f2684273ac132200d5f5f6c6722df0b1131423d9e57a95a/sqlglotrs-0.3.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d62749aad9a6c0d085adf5dc4d70449c2fd763c6c4bba75f623151a3cb47dc20", size = 371936 }, - { url = "https://files.pythonhosted.org/packages/aa/ba/7e9956e4ae9db6970ff78a6c9fa56ed93a42ac205e65258ab31c61274809/sqlglotrs-0.3.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:000c6d4b13c69b7caa84fae7e72064c27892985a0bc987f7df9bed08428af7dc", size = 379162 }, - { url = "https://files.pythonhosted.org/packages/d9/f6/6cd6b37c73683f9a1ca29ae49a1d75455124711bffe15cdeb2efa3af073d/sqlglotrs-0.3.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:010dd22a9d1b7b54ef91b64d94e5459cf7e3a7ac35114fa4f9e31db7df50c246", size = 329209 }, - { url = "https://files.pythonhosted.org/packages/f8/39/0b3bbea3c7fc1dc69a73d7615b65de9e87c9888e7bee3368938573e15600/sqlglotrs-0.3.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a16069aaeba079cb14350b3d67b472137f1e465808d901d78f305b76fa433da4", size = 349283 }, - { url = "https://files.pythonhosted.org/packages/80/38/eb0f6ffcff012a736ffe5fcd4a8d15f8e68c37d49af3ed032518169b88b9/sqlglotrs-0.3.4-cp313-cp313-win32.whl", hash = "sha256:cb5a57e0f0f7b7c504f992a64bb75f486e2006cb2ee283cef3bb9a2cee8009ab", size = 177853 }, - { url = "https://files.pythonhosted.org/packages/78/f6/69c316471fd4d6488b1848be785187714ff6ad4c05a11d1fcfeb07e3572e/sqlglotrs-0.3.4-cp313-cp313-win_amd64.whl", hash = "sha256:60720696872538b1210f5ae150bac69fe9b506a29d98f8f87002185190bbee51", size = 190036 }, +version = "0.3.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/76/bb4288728fa00410bee939e9c23a0762a247c69b13c2ef3ee011f0cb33de/sqlglotrs-0.3.5.tar.gz", hash = "sha256:a945f88f21e9d952a129ed16c9201fefd7b0199d076b7a8c9cb02021374e5a4f", size = 15318 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/26/803a0e5f41c29f1d35e693816fb70e63377fc9541c04b650d03863b7c88d/sqlglotrs-0.3.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:91226d385734aa186b0e1ac402d7d12dbec92073bf7e51b6d026db01b497bf99", size = 295736 }, + { url = "https://files.pythonhosted.org/packages/04/1c/f3def87b02edbf4b07ba4d4bb15fa7727bb9a46b775053eb0308d0d36cb1/sqlglotrs-0.3.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d21beeaa3508f9e69dd8d2836d767faff2cf5d44c6acf0714d6bac71259b704c", size = 283773 }, + { url = "https://files.pythonhosted.org/packages/90/1d/ba039b604e5a9f1f8f0afb7991745ab3f69fbb733be7f2b32c5933b80fbb/sqlglotrs-0.3.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5daea06ac755b17512eaaf234320f283f6b019def43bc27e9f980026f8e9482c", size = 326529 }, + { url = "https://files.pythonhosted.org/packages/b0/96/fce0e8a908b7094c97998e62f574e5d5d7645ca206bf9f51bd6d6db66e7f/sqlglotrs-0.3.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4c87d22abd6f446015555a9289ae709bbffe4aa898fbe25bb739212a57be1c36", size = 332874 }, + { url = "https://files.pythonhosted.org/packages/b2/b3/d2600a150039ff054bd8351324c17a5fa65f82253983d7dcb7a8f3f5779d/sqlglotrs-0.3.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:95e080eb9fd2c528440ee1525467130df46eb47896fdddae88cc4241a9e6fd0d", size = 395396 }, + { url = "https://files.pythonhosted.org/packages/5f/ab/ae4e08dde4be69dc27c42e6550193fc5f6fc4d87d00790372fa9a086ee71/sqlglotrs-0.3.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16e27b97c55e6a97c0ca28c9611274e9c04743963f14a74bc0a7ccc92e8e4462", size = 382362 }, + { url = "https://files.pythonhosted.org/packages/d3/e2/b65d1336d926628d1f9c7eee26dcaaf2f7975fac524742cc8c71ea080ab2/sqlglotrs-0.3.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:674303f8790e4ca21a010585f2ec86a0081c08fb9c4271cd79abdc6c48a2d45b", size = 332114 }, + { url = "https://files.pythonhosted.org/packages/79/9f/958a08ad5fe00a1a7bc2b6b989ef3feb1eff3352137dd92714f1f74ce548/sqlglotrs-0.3.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8c5879d84271a002650c838943b7f93ebd1b84265b0f4477bdfdf0ebd477356d", size = 348851 }, + { url = "https://files.pythonhosted.org/packages/cc/bc/594b708ade71b069d8f0093407a409b8b28277dc0b201709a9757d9e4719/sqlglotrs-0.3.5-cp312-cp312-win32.whl", hash = "sha256:bcaf0968513b3647fe8d85ecc942ca0804c63101db77ed6304a641b388857f63", size = 173445 }, + { url = "https://files.pythonhosted.org/packages/d8/77/5c56bdcd72f739df4f5ffb9d1206f5e4ac3c728fdd7d990ac6cf83697fd1/sqlglotrs-0.3.5-cp312-cp312-win_amd64.whl", hash = "sha256:7248a58e4a54cc8a12bd3e92848a0404b9f180ef79ac7e6af1fbef8a4749d15d", size = 189925 }, + { url = "https://files.pythonhosted.org/packages/18/31/1abfa4a0c1355902af78d756d44c3eb43941e7507f3678b0fc69c2fe7438/sqlglotrs-0.3.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:89ff79ab9fc1cce775ee5e7d8ee38ea6ed79ddaa21bc7984385b23adcf170027", size = 295270 }, + { url = "https://files.pythonhosted.org/packages/0b/8c/053bd0ef5b235c4da43f5dd7a035c969c6052a22730edb06d16d997385cc/sqlglotrs-0.3.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ae25c32114b2ee0edab3a3f8660b9b50370191ff29c1b3228329171883abbdb8", size = 283271 }, + { url = "https://files.pythonhosted.org/packages/29/96/cf4a32cc4ca2b6989506bafdab1b1199cb75e7332895b662e6df684a356f/sqlglotrs-0.3.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95c5d494fe6a0a3fa59e46164ae62a8c4839d3b4d3a5124ae4eaa986f1a607a5", size = 326048 }, + { url = "https://files.pythonhosted.org/packages/7d/e2/dafabc134a10a9e749f4e788e1e118a1407b5b86afb3f621aca3ec2a40f1/sqlglotrs-0.3.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0cfeb4f07b77bd534f2a689d7b343243720c0d16d229b1efe7791fbc2352de4c", size = 332748 }, + { url = "https://files.pythonhosted.org/packages/1d/0e/f7a5bdd379844bd9fffbac3331429b9b21342f1056354f8906ea6b0bca75/sqlglotrs-0.3.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76b16b62c9f65f5c0467d2700e42bdc20bf0eed47c972e97d7686ad009160af3", size = 394356 }, + { url = "https://files.pythonhosted.org/packages/25/b7/bef52bc63fc1699d2b9aecc0ab8db584331cee7bbfd8a53fbf4764c4b07f/sqlglotrs-0.3.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df8b926d45d3e6b6b6a5e36d2dee5dd72bddea34e2aed177df41cd21051905a1", size = 381145 }, + { url = "https://files.pythonhosted.org/packages/02/84/58b5b50d7123a6572b6ee451edd271a22265fb66686e090b7c6c8711af1a/sqlglotrs-0.3.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1b4bb041026ca6f5a976c014d0daa582fb227bac01f69b9fb6212fbeea3fbe4", size = 331254 }, + { url = "https://files.pythonhosted.org/packages/6f/90/4c5a4cba8477929f486a115c840e99bbd6ca4a444e548b1de7844940724c/sqlglotrs-0.3.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5bf510f61f909fb9526fc79f69de0ce68a69c10ce199a7f467cb338bafc61d8f", size = 348642 }, + { url = "https://files.pythonhosted.org/packages/fc/05/f81f08a0a751b1ae90d8af4c508725c60ad56fbbf4ee9a4dd32359fb7daa/sqlglotrs-0.3.5-cp313-cp313-win32.whl", hash = "sha256:ce4edfd0eedd1f94cb7d522702c1bf7b19fd30930904199b17847ca043d5f5c4", size = 173099 }, + { url = "https://files.pythonhosted.org/packages/51/ec/4d8a6ff3a5e50bb84c5f471b72863ca415931378ea31a4ae6e95c497f8ba/sqlglotrs-0.3.5-cp313-cp313-win_amd64.whl", hash = "sha256:1bf0ea4202380933502b6f00c0c593877fa86fa3c70328da4e93b396d9238428", size = 189611 }, ] [[package]] @@ -3483,23 +3473,27 @@ wheels = [ [[package]] name = "srsly" -version = "2.5.0" +version = "2.5.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "catalogue" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f5/54/52041112dfa5932ea6696ca54c5ce051a71b551641733ccdf6e2b005cab3/srsly-2.5.0.tar.gz", hash = "sha256:2776752cdb14275ca01e9a7b7a9c047ccf31db17f0076e73343cfcc9a8df6cbd", size = 466506 } +sdist = { url = "https://files.pythonhosted.org/packages/b7/e8/eb51b1349f50bac0222398af0942613fdc9d1453ae67cbe4bf9936a1a54b/srsly-2.5.1.tar.gz", hash = "sha256:ab1b4bf6cf3e29da23dae0493dd1517fb787075206512351421b89b4fc27c77e", size = 466464 } wheels = [ - { url = "https://files.pythonhosted.org/packages/74/16/8b5997dae87eb39462bc23bf059622cfc76ac8da4dde47c457101aeb488d/srsly-2.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:72e84cd4772f3d2a855e67cdfd293f9fd40d4939ff54e530dd32c4157b46b463", size = 636712 }, - { url = "https://files.pythonhosted.org/packages/c0/90/9266899a16b275d9fd58aecbceb183562b4ee709d244e544f086e3358471/srsly-2.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e1f672e879b4ada0fb5b27401f36ad246ab3046183983961e49de1e8679cc3f5", size = 634700 }, - { url = "https://files.pythonhosted.org/packages/61/e4/d7495538ae1957662a7404863aac118930dafbc87e42c4cb95f7aa3feb43/srsly-2.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d2762e17ad61eea776428652d36da805b8d72c396d2651621ef59513bbcd504", size = 1143540 }, - { url = "https://files.pythonhosted.org/packages/f6/80/47d815f23a793772a3847b3f49d01528ba5013beabb0e7a20b13a8ea0d97/srsly-2.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:767c902ccb16635af88fc98b10f998aa67180c343da41c34aa20679c6eb6618e", size = 1110674 }, - { url = "https://files.pythonhosted.org/packages/33/ff/f76fb452a4a504728f5d03102f67b92bb2076080ba69e9e32292b7c0566a/srsly-2.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:3fac84c8fbda019e3f3652854ab3c8bd439af5b57825745fa3c67a603a13a05d", size = 632605 }, - { url = "https://files.pythonhosted.org/packages/af/3f/1b418e9157d2dfbf5f40e6319d16b41a34f0f3791d1bc11a263174740222/srsly-2.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1d7fb3fd694eec2328b42ab0767193aa5561bb20cc50bf34da6cb213edf30c25", size = 634880 }, - { url = "https://files.pythonhosted.org/packages/95/5e/4c2cc489006954e1bfc24687443cbcfccbd69c52034f26d7c4f902d4a42d/srsly-2.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:40932a850b10562eb739163ff7644a6b0804fde1fe5b1f9724198e81cb09c704", size = 632841 }, - { url = "https://files.pythonhosted.org/packages/95/3d/2dd76d2fd99f0fb632c40273755d99466bdee2aaebd40866507249debd43/srsly-2.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a657d8c1486d47910868cfadd5a80cd77719c6228fed5b01b878329b95f0752", size = 1127978 }, - { url = "https://files.pythonhosted.org/packages/54/93/22d3f4d3c1d35d83f15f56a995777535288388f5e6161fbe36ac4bf466a5/srsly-2.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9f4430fab1bd62fea7b23ad2bd7822bf80cdd4a75c7d051a555c69aa10f4bfdc", size = 1100354 }, - { url = "https://files.pythonhosted.org/packages/23/51/b448c7ffb15bf9e1af0369bdf3e00e87e893a9ea7fca7ea3f020af5a105a/srsly-2.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:35fa3aadfc0d983e80fc5e0319825e91f792d13b414c1aff20cbbb47569d5109", size = 630642 }, + { url = "https://files.pythonhosted.org/packages/fb/f6/bebc20d75bd02121fc0f65ad8c92a5dd2570e870005e940faa55a263e61a/srsly-2.5.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:683b54ed63d7dfee03bc2abc4b4a5f2152f81ec217bbadbac01ef1aaf2a75790", size = 636717 }, + { url = "https://files.pythonhosted.org/packages/b6/e8/9372317a4742c70b87b413335adfcdfb2bee4f88f3faba89fabb9e6abf21/srsly-2.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:459d987130e57e83ce9e160899afbeb871d975f811e6958158763dd9a8a20f23", size = 634697 }, + { url = "https://files.pythonhosted.org/packages/d5/00/c6a7b99ab27b051a27bd26fe1a8c1885225bb8980282bf9cb99f70610368/srsly-2.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:184e3c98389aab68ff04aab9095bd5f1a8e5a72cc5edcba9d733bac928f5cf9f", size = 1134655 }, + { url = "https://files.pythonhosted.org/packages/c2/e6/861459e8241ec3b78c111081bd5efa414ef85867e17c45b6882954468d6e/srsly-2.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c2a3e4856e63b7efd47591d049aaee8e5a250e098917f50d93ea68853fab78", size = 1143544 }, + { url = "https://files.pythonhosted.org/packages/2d/85/8448fe874dd2042a4eceea5315cfff3af03ac77ff5073812071852c4e7e2/srsly-2.5.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:366b4708933cd8d6025c13c2cea3331f079c7bb5c25ec76fca392b6fc09818a0", size = 1098330 }, + { url = "https://files.pythonhosted.org/packages/ef/7e/04d0e1417da140b2ac4053a3d4fcfc86cd59bf4829f69d370bb899f74d5d/srsly-2.5.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c8a0b03c64eb6e150d772c5149befbadd981cc734ab13184b0561c17c8cef9b1", size = 1110670 }, + { url = "https://files.pythonhosted.org/packages/96/1a/a8cd627eaa81a91feb6ceab50155f4ceff3eef6107916cb87ef796958427/srsly-2.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:7952538f6bba91b9d8bf31a642ac9e8b9ccc0ccbb309feb88518bfb84bb0dc0d", size = 632598 }, + { url = "https://files.pythonhosted.org/packages/42/94/cab36845aad6e2c22ecee1178accaa365657296ff87305b805648fd41118/srsly-2.5.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84b372f7ef1604b4a5b3cee1571993931f845a5b58652ac01bcb32c52586d2a8", size = 634883 }, + { url = "https://files.pythonhosted.org/packages/67/8b/501f51f4eaee7e1fd7327764799cb0a42f5d0de042a97916d30dbff770fc/srsly-2.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6ac3944c112acb3347a39bfdc2ebfc9e2d4bace20fe1c0b764374ac5b83519f2", size = 632842 }, + { url = "https://files.pythonhosted.org/packages/07/be/5b8fce4829661e070a7d3e262d2e533f0e297b11b8993d57240da67d7330/srsly-2.5.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6118f9c4b221cde0a990d06a42c8a4845218d55b425d8550746fe790acf267e9", size = 1118516 }, + { url = "https://files.pythonhosted.org/packages/91/60/a34e97564eac352c0e916c98f44b6f566b7eb6a9fb60bcd60ffa98530762/srsly-2.5.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7481460110d9986781d9e4ac0f5f991f1d6839284a80ad268625f9a23f686950", size = 1127974 }, + { url = "https://files.pythonhosted.org/packages/70/a2/f642334db0cabd187fa86b8773257ee6993c6009338a6831d4804e2c5b3c/srsly-2.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e57b8138082f09e35db60f99757e16652489e9e3692471d8e0c39aa95180688", size = 1086098 }, + { url = "https://files.pythonhosted.org/packages/0d/9b/be48e185c5a010e71b5135e4cdf317ff56b8ac4bc08f394bbf882ac13b05/srsly-2.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bab90b85a63a1fe0bbc74d373c8bb9bb0499ddfa89075e0ebe8d670f12d04691", size = 1100354 }, + { url = "https://files.pythonhosted.org/packages/3a/e2/745aeba88a8513017fbac2fd2f9f07b8a36065e51695f818541eb795ec0c/srsly-2.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:e73712be1634b5e1de6f81c273a7d47fe091ad3c79dc779c03d3416a5c117cee", size = 630634 }, ] [[package]] @@ -3553,6 +3547,7 @@ name = "text-2-sql-core" version = "0.1.0" source = { editable = "text_2_sql/text_2_sql_core" } dependencies = [ + { name = "aiohttp" }, { name = "aioodbc" }, { name = "azure-identity" }, { name = "azure-search" }, @@ -3600,6 +3595,7 @@ dev = [ [package.metadata] requires-dist = [ + { name = "aiohttp", specifier = ">=3.11.11" }, { name = "aioodbc", specifier = ">=0.5.0" }, { name = "aiosqlite", marker = "extra == 'sqlite'", specifier = ">=0.19.0" }, { name = "azure-identity", specifier = ">=1.19.0" }, @@ -3764,7 +3760,7 @@ name = "tqdm" version = "4.67.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737 } wheels = [ @@ -3815,11 +3811,11 @@ wheels = [ [[package]] name = "tzdata" -version = "2024.2" +version = "2025.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e1/34/943888654477a574a86a98e9896bae89c7aa15078ec29f490fef2f1e5384/tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc", size = 193282 } +sdist = { url = "https://files.pythonhosted.org/packages/43/0f/fa4723f22942480be4ca9527bbde8d43f6c3f2fe8412f00e7f5f6746bc8b/tzdata-2025.1.tar.gz", hash = "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694", size = 194950 } wheels = [ - { url = "https://files.pythonhosted.org/packages/a6/ab/7e5f53c3b9d14972843a647d8d7a853969a58aecc7559cb3267302c94774/tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd", size = 346586 }, + { url = "https://files.pythonhosted.org/packages/0f/dd/84f10e23edd882c6f968c21c2434fe67bd4a528967067515feca9e611e5e/tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639", size = 346762 }, ] [[package]] @@ -3842,16 +3838,16 @@ wheels = [ [[package]] name = "virtualenv" -version = "20.28.1" +version = "20.29.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/50/39/689abee4adc85aad2af8174bb195a819d0be064bf55fcc73b49d2b28ae77/virtualenv-20.28.1.tar.gz", hash = "sha256:5d34ab240fdb5d21549b76f9e8ff3af28252f5499fb6d6f031adac4e5a8c5329", size = 7650532 } +sdist = { url = "https://files.pythonhosted.org/packages/a7/ca/f23dcb02e161a9bba141b1c08aa50e8da6ea25e6d780528f1d385a3efe25/virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35", size = 7658028 } wheels = [ - { url = "https://files.pythonhosted.org/packages/51/8f/dfb257ca6b4e27cb990f1631142361e4712badab8e3ca8dc134d96111515/virtualenv-20.28.1-py3-none-any.whl", hash = "sha256:412773c85d4dab0409b83ec36f7a6499e72eaf08c80e81e9576bca61831c71cb", size = 4276719 }, + { url = "https://files.pythonhosted.org/packages/89/9b/599bcfc7064fbe5740919e78c5df18e5dceb0887e676256a1061bb5ae232/virtualenv-20.29.1-py3-none-any.whl", hash = "sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779", size = 4282379 }, ] [[package]] @@ -3945,41 +3941,44 @@ wheels = [ [[package]] name = "wrapt" -version = "1.17.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c8/dd/35c573cc2b4b8d65ea96bba0247d05710f284857d30e2266d1874f1c727d/wrapt-1.17.1.tar.gz", hash = "sha256:16b2fdfa09a74a3930175b6d9d7d008022aa72a4f02de2b3eecafcc1adfd3cfe", size = 55552 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ea/40/7fb607aa889b107ab7417f633f1893f48be4fd8bd12ec89c6355d26560a8/wrapt-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b1a4c8edd038fee0ce67bf119b16eaa45d22a52bbaf7d0a17d2312eb0003b1bb", size = 38820 }, - { url = "https://files.pythonhosted.org/packages/ce/24/9e8b8b670c5ebab2c05e51ad7403c5317985c53071d0ce4bb85684b9dce1/wrapt-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:181a844005c9818792212a32e004cb4c6bd8e35cae8e97b1a39a1918d95cef58", size = 38921 }, - { url = "https://files.pythonhosted.org/packages/d7/00/c07c9893e6761ee60d59ec319b33b2d3c5b68da674cbbf8ebf6c54cba146/wrapt-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21ffcf16f5c243a626b0f8da637948e3d5984e3bc0c1bc500ad990e88e974e3b", size = 88720 }, - { url = "https://files.pythonhosted.org/packages/d6/09/d3962a902a6be1d5a66b04ec10189618796a5a9b3fb87d0873294661289d/wrapt-1.17.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0eb33799b7582bb73787b9903b70595f8eff67eecc9455f668ed01adf53f9eea", size = 80899 }, - { url = "https://files.pythonhosted.org/packages/e2/fc/92d37def794c3626fb3c3aa112aa629544ba21f6c565034dae0e587f03c0/wrapt-1.17.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57e932ad1908b53e9ad67a746432f02bc8473a9ee16e26a47645a2b224fba5fd", size = 89222 }, - { url = "https://files.pythonhosted.org/packages/cd/4f/e0921cb71ed320508cbcf0e450449642c4b892f64bc5b2696ca725427dea/wrapt-1.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b8bd35c15bc82c5cbe397e8196fa57a17ce5d3f30e925a6fd39e4c5bb02fdcff", size = 86707 }, - { url = "https://files.pythonhosted.org/packages/85/16/f61d6afe9c3c9932f8699a62e4e594bcac87fdffc7dbd8f603939c44cfa5/wrapt-1.17.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:93018dbb956e0ad99ea2fa2c3c22f033549dcb1f56ad9f4555dfe25e49688c5d", size = 79685 }, - { url = "https://files.pythonhosted.org/packages/95/1d/a1940ce270fa7793044e7131d48528b7d4a6ab2e038142a7c82d722aa5c1/wrapt-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e5bd9186d52cf3d36bf1823be0e85297e4dbad909bc6dd495ce0d272806d84a7", size = 87568 }, - { url = "https://files.pythonhosted.org/packages/f0/ca/d1292891bfdda05a77b0bdc2ecdca4a9484b02d64a65e2afddfcb5ac17e1/wrapt-1.17.1-cp312-cp312-win32.whl", hash = "sha256:d609f0ab0603bbcbf2de906b366b9f9bec75c32b4493550a940de658cc2ce512", size = 36672 }, - { url = "https://files.pythonhosted.org/packages/63/0f/0d52bff5074392586eb754609bc0877cea5340a2152f946166002b70ed07/wrapt-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:2c160bb8815787646b27a0c8575a26a4d6bf6abd7c5eb250ad3f2d38b29cb2cb", size = 38866 }, - { url = "https://files.pythonhosted.org/packages/0e/16/82d25dd10e97eabb561d491487ff111ac272a4024f40df098bd61c96840b/wrapt-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:99e544e6ce26f89ad5acc6f407bc4daf7c1d42321e836f5c768f834100bdf35c", size = 38821 }, - { url = "https://files.pythonhosted.org/packages/08/e2/c79dd3c9712988156ea86cd507a81f2b3f045eb84af2d0f7aedb42c709f9/wrapt-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:78da796b74f2c8e0af021ee99feb3bff7cb46f8e658fe25c20e66be1080db4a2", size = 38920 }, - { url = "https://files.pythonhosted.org/packages/4d/d8/bc2bb9797543b31ef7311074583c83addbfc21f1bead66ca7c9d637de6fd/wrapt-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f1bc359f6c52e53565e7af24b423e7a1eea97d155f38ac9e90e95303514710b", size = 88691 }, - { url = "https://files.pythonhosted.org/packages/e7/d3/8d64b5ced10eb0ef856ae864c806292de4891c4945db3444188d45a17b43/wrapt-1.17.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cbead724daa13cae46e8ab3bb24938d8514d123f34345535b184f3eb1b7ad717", size = 80862 }, - { url = "https://files.pythonhosted.org/packages/65/22/ee8e9a7014f7c011edac4a9babea4d0aa73a363dd618afc9b31669e478a8/wrapt-1.17.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdf7b0e3d3713331c0bb9daac47cd10e5aa60d060e53696f50de4e560bd5617f", size = 89174 }, - { url = "https://files.pythonhosted.org/packages/fd/10/3d1610d0c220a9f09317d7c9c216889b9dd67329e23d2fcf1017f2d67fc9/wrapt-1.17.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f17e8d926f63aed65ff949682c922f96d00f65c2e852c24272232313fa7823d5", size = 86721 }, - { url = "https://files.pythonhosted.org/packages/3c/c1/2f4b20057afcfbfad4886138a702ae2ffd79abbb43884b31e2388895e367/wrapt-1.17.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9e04f3bd30e0b23c0ca7e1d4084e7d28b6d7d2feb8b7bc69b496fe881280579b", size = 79761 }, - { url = "https://files.pythonhosted.org/packages/f2/c9/c6bde0a10a7108da0ffaa0a8337221e66636199b367e7d6f1d035e0b306a/wrapt-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5660e470edfa15ae7ef407272c642d29e9962777a6b30bfa8fc0da2173dc9afd", size = 87586 }, - { url = "https://files.pythonhosted.org/packages/2a/ad/956a2db1196bde82088f5576eb1d7a290c4ffc0dec00bfc9d29fca440fff/wrapt-1.17.1-cp313-cp313-win32.whl", hash = "sha256:a992f9e019145e84616048556546edeaba68e05e1c1ffbe8391067a63cdadb0c", size = 36678 }, - { url = "https://files.pythonhosted.org/packages/d7/3a/8bf805ab213f7830b5998027ada2a3fae8e93529df7b0c446946d7f8e9e9/wrapt-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:5c2e24ba455af4b0a237a890ea6ed9bafd01fac2c47095f87c53ea3344215d43", size = 38873 }, - { url = "https://files.pythonhosted.org/packages/d7/76/878e3891ea25875608c5075b81240a4060e48eec786ff354b2a5d3eb87f1/wrapt-1.17.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88623fd957ba500d8bb0f7427a76496d99313ca2f9e932481c0882e034cf1add", size = 40060 }, - { url = "https://files.pythonhosted.org/packages/76/4b/fdde9124f6f61a56e1982cd0f7f0bc8fe2ababb876a50da3308e9ea462a0/wrapt-1.17.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:162d5f15bdd3b8037e06540902227ef9e0f298496c0afaadd9e2875851446693", size = 40154 }, - { url = "https://files.pythonhosted.org/packages/17/f2/e3d909ded67bd7d15b7f02f9cb05e111d2fef9499c1dc0f43690391b8c53/wrapt-1.17.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bb82447ddae4e3d9b51f40c494f66e6cbd8fb0e8e8b993678416535c67f9a0d", size = 113469 }, - { url = "https://files.pythonhosted.org/packages/6f/96/2ba3bd9b2d81b139a5784bf997bffc54979b561c272a953af3a69c242e02/wrapt-1.17.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ce4cff3922707048d754e365c4ebf41a3bcbf29b329349bf85d51873c7c7e9e", size = 101207 }, - { url = "https://files.pythonhosted.org/packages/eb/9a/c8e0275eeef83f0b8bf685034244fb0bf21d2e759fd7a6d54005de6b887f/wrapt-1.17.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fdc4e73a3fa0c25eed4d836d9732226f0326957cb075044a7f252b465299433", size = 109341 }, - { url = "https://files.pythonhosted.org/packages/4b/e3/346259c335b04d342beddba6a97030932b53a8ae35d7ff8a319ab2204270/wrapt-1.17.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:bca1c0824f824bcd97b4b179dd55dcad1dab419252be2b2faebbcacefa3b27b2", size = 110232 }, - { url = "https://files.pythonhosted.org/packages/c3/aa/9611db2f50359b0b091e501405bc2497b7369185b342cae7bb2218a986e8/wrapt-1.17.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:6d44b14f3a2f6343a07c90344850b7af5515538ce3a5d01f9c87d8bae9bd8724", size = 100474 }, - { url = "https://files.pythonhosted.org/packages/33/c2/edbcad020deeb742bce83647a7d13e47c35fafcab4fba4a89ec006ad0385/wrapt-1.17.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:169033329022739c6f0d8cd3031a113953b0ba500f3d5978904bdd40baec4568", size = 106377 }, - { url = "https://files.pythonhosted.org/packages/4f/bf/e2aa032cea63737cbabd4069c86d6aa4ba075ee19c44a165e1362a5b403b/wrapt-1.17.1-cp313-cp313t-win32.whl", hash = "sha256:52f0907287d9104112dbebda46af4db0793fcc4c64c8a867099212d116b6db64", size = 37987 }, - { url = "https://files.pythonhosted.org/packages/77/fb/439f032c1b52a1750c304ff85253edfec3a50d4e39fa9a338ab0f837acb4/wrapt-1.17.1-cp313-cp313t-win_amd64.whl", hash = "sha256:7966f98fa36933333d8a1c3d8552aa3d0735001901a4aabcfbd5a502b4ef14fe", size = 40751 }, - { url = "https://files.pythonhosted.org/packages/94/47/299f204e352655c117b9dec03fc585866df7eea72660515208ec67c185c4/wrapt-1.17.1-py3-none-any.whl", hash = "sha256:f3117feb1fc479eaf84b549d3f229d5d2abdb823f003bc2a1c6dd70072912fa0", size = 23589 }, +version = "1.17.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/fc/e91cc220803d7bc4db93fb02facd8461c37364151b8494762cc88b0fbcef/wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3", size = 55531 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a1/bd/ab55f849fd1f9a58ed7ea47f5559ff09741b25f00c191231f9f059c83949/wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925", size = 53799 }, + { url = "https://files.pythonhosted.org/packages/53/18/75ddc64c3f63988f5a1d7e10fb204ffe5762bc663f8023f18ecaf31a332e/wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392", size = 38821 }, + { url = "https://files.pythonhosted.org/packages/48/2a/97928387d6ed1c1ebbfd4efc4133a0633546bec8481a2dd5ec961313a1c7/wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40", size = 38919 }, + { url = "https://files.pythonhosted.org/packages/73/54/3bfe5a1febbbccb7a2f77de47b989c0b85ed3a6a41614b104204a788c20e/wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d", size = 88721 }, + { url = "https://files.pythonhosted.org/packages/25/cb/7262bc1b0300b4b64af50c2720ef958c2c1917525238d661c3e9a2b71b7b/wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b", size = 80899 }, + { url = "https://files.pythonhosted.org/packages/2a/5a/04cde32b07a7431d4ed0553a76fdb7a61270e78c5fd5a603e190ac389f14/wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98", size = 89222 }, + { url = "https://files.pythonhosted.org/packages/09/28/2e45a4f4771fcfb109e244d5dbe54259e970362a311b67a965555ba65026/wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82", size = 86707 }, + { url = "https://files.pythonhosted.org/packages/c6/d2/dcb56bf5f32fcd4bd9aacc77b50a539abdd5b6536872413fd3f428b21bed/wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae", size = 79685 }, + { url = "https://files.pythonhosted.org/packages/80/4e/eb8b353e36711347893f502ce91c770b0b0929f8f0bed2670a6856e667a9/wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9", size = 87567 }, + { url = "https://files.pythonhosted.org/packages/17/27/4fe749a54e7fae6e7146f1c7d914d28ef599dacd4416566c055564080fe2/wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9", size = 36672 }, + { url = "https://files.pythonhosted.org/packages/15/06/1dbf478ea45c03e78a6a8c4be4fdc3c3bddea5c8de8a93bc971415e47f0f/wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991", size = 38865 }, + { url = "https://files.pythonhosted.org/packages/ce/b9/0ffd557a92f3b11d4c5d5e0c5e4ad057bd9eb8586615cdaf901409920b14/wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125", size = 53800 }, + { url = "https://files.pythonhosted.org/packages/c0/ef/8be90a0b7e73c32e550c73cfb2fa09db62234227ece47b0e80a05073b375/wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998", size = 38824 }, + { url = "https://files.pythonhosted.org/packages/36/89/0aae34c10fe524cce30fe5fc433210376bce94cf74d05b0d68344c8ba46e/wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5", size = 38920 }, + { url = "https://files.pythonhosted.org/packages/3b/24/11c4510de906d77e0cfb5197f1b1445d4fec42c9a39ea853d482698ac681/wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8", size = 88690 }, + { url = "https://files.pythonhosted.org/packages/71/d7/cfcf842291267bf455b3e266c0c29dcb675b5540ee8b50ba1699abf3af45/wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6", size = 80861 }, + { url = "https://files.pythonhosted.org/packages/d5/66/5d973e9f3e7370fd686fb47a9af3319418ed925c27d72ce16b791231576d/wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc", size = 89174 }, + { url = "https://files.pythonhosted.org/packages/a7/d3/8e17bb70f6ae25dabc1aaf990f86824e4fd98ee9cadf197054e068500d27/wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2", size = 86721 }, + { url = "https://files.pythonhosted.org/packages/6f/54/f170dfb278fe1c30d0ff864513cff526d624ab8de3254b20abb9cffedc24/wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b", size = 79763 }, + { url = "https://files.pythonhosted.org/packages/4a/98/de07243751f1c4a9b15c76019250210dd3486ce098c3d80d5f729cba029c/wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504", size = 87585 }, + { url = "https://files.pythonhosted.org/packages/f9/f0/13925f4bd6548013038cdeb11ee2cbd4e37c30f8bfd5db9e5a2a370d6e20/wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a", size = 36676 }, + { url = "https://files.pythonhosted.org/packages/bf/ae/743f16ef8c2e3628df3ddfd652b7d4c555d12c84b53f3d8218498f4ade9b/wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845", size = 38871 }, + { url = "https://files.pythonhosted.org/packages/3d/bc/30f903f891a82d402ffb5fda27ec1d621cc97cb74c16fea0b6141f1d4e87/wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192", size = 56312 }, + { url = "https://files.pythonhosted.org/packages/8a/04/c97273eb491b5f1c918857cd26f314b74fc9b29224521f5b83f872253725/wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b", size = 40062 }, + { url = "https://files.pythonhosted.org/packages/4e/ca/3b7afa1eae3a9e7fefe499db9b96813f41828b9fdb016ee836c4c379dadb/wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0", size = 40155 }, + { url = "https://files.pythonhosted.org/packages/89/be/7c1baed43290775cb9030c774bc53c860db140397047cc49aedaf0a15477/wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306", size = 113471 }, + { url = "https://files.pythonhosted.org/packages/32/98/4ed894cf012b6d6aae5f5cc974006bdeb92f0241775addad3f8cd6ab71c8/wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb", size = 101208 }, + { url = "https://files.pythonhosted.org/packages/ea/fd/0c30f2301ca94e655e5e057012e83284ce8c545df7661a78d8bfca2fac7a/wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681", size = 109339 }, + { url = "https://files.pythonhosted.org/packages/75/56/05d000de894c4cfcb84bcd6b1df6214297b8089a7bd324c21a4765e49b14/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6", size = 110232 }, + { url = "https://files.pythonhosted.org/packages/53/f8/c3f6b2cf9b9277fb0813418e1503e68414cd036b3b099c823379c9575e6d/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6", size = 100476 }, + { url = "https://files.pythonhosted.org/packages/a7/b1/0bb11e29aa5139d90b770ebbfa167267b1fc548d2302c30c8f7572851738/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f", size = 106377 }, + { url = "https://files.pythonhosted.org/packages/6a/e1/0122853035b40b3f333bbb25f1939fc1045e21dd518f7f0922b60c156f7c/wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555", size = 37986 }, + { url = "https://files.pythonhosted.org/packages/09/5e/1655cf481e079c1f22d0cabdd4e51733679932718dc23bf2db175f329b76/wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c", size = 40750 }, + { url = "https://files.pythonhosted.org/packages/2d/82/f56956041adef78f849db6b289b282e72b55ab8045a75abad81898c28d19/wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8", size = 23594 }, ] [[package]] From 27e5251dc808d0e3612d643fc5d5d49305c9abcc Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Tue, 21 Jan 2025 21:07:19 +0000 Subject: [PATCH 25/64] Update ai search deploy --- .../{src/deploy_ai_search => }/.env.example | 0 deploy_ai_search/README.md | 8 +- .../src/deploy_ai_search/deploy.py | 6 +- .../src/deploy_ai_search/environment.py | 2 +- .../{rag_documents.py => image_processing.py} | 10 +- image_processing/requirements.txt | 1253 +++++++++++++++++ 6 files changed, 1266 insertions(+), 13 deletions(-) rename deploy_ai_search/{src/deploy_ai_search => }/.env.example (100%) rename deploy_ai_search/src/deploy_ai_search/{rag_documents.py => image_processing.py} (97%) diff --git a/deploy_ai_search/src/deploy_ai_search/.env.example b/deploy_ai_search/.env.example similarity index 100% rename from deploy_ai_search/src/deploy_ai_search/.env.example rename to deploy_ai_search/.env.example diff --git a/deploy_ai_search/README.md b/deploy_ai_search/README.md index bd3ebb1c..11fac63c 100644 --- a/deploy_ai_search/README.md +++ b/deploy_ai_search/README.md @@ -2,14 +2,14 @@ The associated scripts in this portion of the repository contains pre-built scripts to deploy the skillsets needed for both Text2SQL and Image Processing. -## Steps for Rag Documents Index Deployment (For Image Processing) +## Steps for Image Processing Index Deployment (For Image Processing) 1. Update `.env` file with the associated values. Not all values are required dependent on whether you are using System / User Assigned Identities or a Key based authentication. -2. Adjust `rag_documents.py` with any changes to the index / indexer. The `get_skills()` method implements the skills pipeline. Make any adjustments here in the skills needed to enrich the data source. +2. Adjust `image_processing.py` with any changes to the index / indexer. The `get_skills()` method implements the skills pipeline. Make any adjustments here in the skills needed to enrich the data source. 3. Run `deploy.py` with the following args: - - `index_type rag`. This selects the `RagDocumentsAISearch` sub class. - - `enable_page_chunking True`. This determines whether page wise chunking is applied in ADI, or whether the inbuilt skill is used for TextSplit. **Page wise analysis in ADI is recommended to avoid splitting tables / figures across multiple chunks, when the chunking is performed.** + - `index_type image_processing`. This selects the `ImageProcessingAISearch` sub class. + - `enable_page_chunking True`. This determines whether page wise chunking is applied in ADI, or whether the inbuilt skill is used for TextSplit. This suits documents that are inheritely page-wise e.g. pptx files. - `rebuild`. Whether to delete and rebuild the index. - `suffix`. Optional parameter that will apply a suffix onto the deployed index and indexer. This is useful if you want deploy a test version, before overwriting the main version. diff --git a/deploy_ai_search/src/deploy_ai_search/deploy.py b/deploy_ai_search/src/deploy_ai_search/deploy.py index 2b678201..41689f6e 100644 --- a/deploy_ai_search/src/deploy_ai_search/deploy.py +++ b/deploy_ai_search/src/deploy_ai_search/deploy.py @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. import argparse -from rag_documents import RagDocumentsAISearch +from image_processing import ImageProcessingAISearch from text_2_sql_schema_store import Text2SqlSchemaStoreAISearch from text_2_sql_query_cache import Text2SqlQueryCacheAISearch from text_2_sql_column_value_store import Text2SqlColumnValueStoreAISearch @@ -17,8 +17,8 @@ def deploy_config(arguments: argparse.Namespace): arguments (argparse.Namespace): The arguments passed to the script""" suffix = None if args.suffix == "None" else args.suffix - if arguments.index_type == "rag": - index_config = RagDocumentsAISearch( + if arguments.index_type == "image_processing": + index_config = ImageProcessingAISearch( suffix=suffix, rebuild=arguments.rebuild, enable_page_by_chunking=arguments.enable_page_chunking, diff --git a/deploy_ai_search/src/deploy_ai_search/environment.py b/deploy_ai_search/src/deploy_ai_search/environment.py index c91ca694..a99f5907 100644 --- a/deploy_ai_search/src/deploy_ai_search/environment.py +++ b/deploy_ai_search/src/deploy_ai_search/environment.py @@ -11,7 +11,7 @@ class IndexerType(Enum): """The type of the indexer""" - RAG_DOCUMENTS = "rag-documents" + IMAGE_PROCESSING = "image-processing" TEXT_2_SQL_SCHEMA_STORE = "text-2-sql-schema-store" TEXT_2_SQL_QUERY_CACHE = "text-2-sql-query-cache" TEXT_2_SQL_COLUMN_VALUE_STORE = "text-2-sql-column-value-store" diff --git a/deploy_ai_search/src/deploy_ai_search/rag_documents.py b/deploy_ai_search/src/deploy_ai_search/image_processing.py similarity index 97% rename from deploy_ai_search/src/deploy_ai_search/rag_documents.py rename to deploy_ai_search/src/deploy_ai_search/image_processing.py index 0f6eb692..e2abed2c 100644 --- a/deploy_ai_search/src/deploy_ai_search/rag_documents.py +++ b/deploy_ai_search/src/deploy_ai_search/image_processing.py @@ -29,7 +29,7 @@ ) -class RagDocumentsAISearch(AISearch): +class ImageProcessingAISearch(AISearch): """This class is used to deploy the rag document index.""" def __init__( @@ -38,13 +38,13 @@ def __init__( rebuild: bool | None = False, enable_page_by_chunking=False, ): - """Initialize the RagDocumentsAISearch class. This class implements the deployment of the rag document index. + """Initialize the ImageProcessingAISearch class. This class implements the deployment of the rag document index. Args: suffix (str, optional): The suffix for the indexer. Defaults to None. If an suffix is provided, it is assumed to be a test indexer. rebuild (bool, optional): Whether to rebuild the index. Defaults to False. """ - self.indexer_type = IndexerType.RAG_DOCUMENTS + self.indexer_type = IndexerType.IMAGE_PROCESSING super().__init__(suffix, rebuild) if enable_page_by_chunking is not None: @@ -140,7 +140,7 @@ def get_index_fields(self) -> list[SearchableField]: if self.enable_page_by_chunking: fields.extend( [ - SearchableField( + SimpleField( name="PageNumber", type=SearchFieldDataType.Int64, sortable=True, @@ -286,7 +286,7 @@ def get_indexer(self) -> SearchIndexer: indexer_parameters = IndexingParameters( batch_size=batch_size, configuration=IndexingParametersConfiguration( - data_to_extract=BlobIndexerDataToExtract.STORAGE_METADATA, + data_to_extract=BlobIndexerDataToExtract.ALL_METADATA, query_timeout=None, execution_environment=execution_environment, fail_on_unprocessable_document=False, diff --git a/image_processing/requirements.txt b/image_processing/requirements.txt index e69de29b..f0c790ae 100644 --- a/image_processing/requirements.txt +++ b/image_processing/requirements.txt @@ -0,0 +1,1253 @@ +# This file was autogenerated by uv via the following command: +# uv export --all-extras +aiohappyeyeballs==2.4.4 \ + --hash=sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745 \ + --hash=sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8 +aiohttp==3.11.11 \ + --hash=sha256:0882c2820fd0132240edbb4a51eb8ceb6eef8181db9ad5291ab3332e0d71df5f \ + --hash=sha256:0b7fb429ab1aafa1f48578eb315ca45bd46e9c37de11fe45c7f5f4138091e2f1 \ + --hash=sha256:1e69966ea6ef0c14ee53ef7a3d68b564cc408121ea56c0caa2dc918c1b2f553d \ + --hash=sha256:3499c7ffbfd9c6a3d8d6a2b01c26639da7e43d47c7b4f788016226b1e711caa8 \ + --hash=sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2 \ + --hash=sha256:541d823548ab69d13d23730a06f97460f4238ad2e5ed966aaf850d7c369782d9 \ + --hash=sha256:620598717fce1b3bd14dd09947ea53e1ad510317c85dda2c9c65b622edc96b12 \ + --hash=sha256:6fba278063559acc730abf49845d0e9a9e1ba74f85f0ee6efd5803f08b285853 \ + --hash=sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c \ + --hash=sha256:8e2bf8029dbf0810c7bfbc3e594b51c4cc9101fbffb583a3923aea184724203c \ + --hash=sha256:929f3ed33743a49ab127c58c3e0a827de0664bfcda566108989a14068f820194 \ + --hash=sha256:92fc484e34b733704ad77210c7957679c5c3877bd1e6b6d74b185e9320cc716e \ + --hash=sha256:9d73ee3725b7a737ad86c2eac5c57a4a97793d9f442599bea5ec67ac9f4bdc3d \ + --hash=sha256:9f5b3c1ed63c8fa937a920b6c1bec78b74ee09593b3f5b979ab2ae5ef60d7600 \ + --hash=sha256:a344d5dc18074e3872777b62f5f7d584ae4344cd6006c17ba12103759d407af3 \ + --hash=sha256:a8f5f7515f3552d899c61202d99dcb17d6e3b0de777900405611cd747cecd1b8 \ + --hash=sha256:a9b7371665d4f00deb8f32208c7c5e652059b0fda41cf6dbcac6114a041f1cc2 \ + --hash=sha256:aa54f8ef31d23c506910c21163f22b124facb573bff73930735cf9fe38bf7dff \ + --hash=sha256:b6212a60e5c482ef90f2d788835387070a88d52cf6241d3916733c9176d39eab \ + --hash=sha256:b63de12e44935d5aca7ed7ed98a255a11e5cb47f83a9fded7a5e41c40277d104 \ + --hash=sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e \ + --hash=sha256:bd7227b87a355ce1f4bf83bfae4399b1f5bb42e0259cb9405824bd03d2f4336a \ + --hash=sha256:bf8d9bfee991d8acc72d060d53860f356e07a50f0e0d09a8dfedea1c554dd0d5 \ + --hash=sha256:c341c7d868750e31961d6d8e60ff040fb9d3d3a46d77fd85e1ab8e76c3e9a5c4 \ + --hash=sha256:c7a06301c2fb096bdb0bd25fe2011531c1453b9f2c163c8031600ec73af1cc99 \ + --hash=sha256:d119fafe7b634dbfa25a8c597718e69a930e4847f0b88e172744be24515140da \ + --hash=sha256:d40f9da8cabbf295d3a9dae1295c69975b86d941bc20f0a087f0477fa0a66231 \ + --hash=sha256:de8d38f1c2810fa2a4f1d995a2e9c70bb8737b18da04ac2afbf3971f65781d87 \ + --hash=sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886 \ + --hash=sha256:ed9ee95614a71e87f1a70bc81603f6c6760128b140bc4030abe6abaa988f1c3d \ + --hash=sha256:ffb3dc385f6bb1568aa974fe65da84723210e5d9707e360e9ecb51f59406cd2e +aiosignal==1.3.2 \ + --hash=sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5 \ + --hash=sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54 +annotated-types==0.7.0 \ + --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ + --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 +anyio==4.8.0 \ + --hash=sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a \ + --hash=sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a +appnope==0.1.4 ; sys_platform == 'darwin' \ + --hash=sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee \ + --hash=sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c +argon2-cffi==23.1.0 \ + --hash=sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08 \ + --hash=sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea +argon2-cffi-bindings==21.2.0 \ + --hash=sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c \ + --hash=sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082 \ + --hash=sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f \ + --hash=sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d \ + --hash=sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f \ + --hash=sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae \ + --hash=sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3 \ + --hash=sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86 \ + --hash=sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367 \ + --hash=sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93 \ + --hash=sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e +arrow==1.3.0 \ + --hash=sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80 \ + --hash=sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85 +asttokens==3.0.0 \ + --hash=sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7 \ + --hash=sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2 +async-lru==2.0.4 \ + --hash=sha256:b8a59a5df60805ff63220b2a0c5b5393da5521b113cd5465a44eb037d81a5627 \ + --hash=sha256:ff02944ce3c288c5be660c42dbcca0742b32c3b279d6dceda655190240b99224 +attrs==24.3.0 \ + --hash=sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff \ + --hash=sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308 +azure-ai-documentintelligence==1.0.0 \ + --hash=sha256:c8b6efc0fc7e65d7892c9585cfd256f7d8b3f2b46cecf92c75ab82e629eac253 \ + --hash=sha256:cdedb1a67c075f58f47a413ec5846bf8d532a83a71f0c51ec49ce9b5bfe2a519 +azure-ai-textanalytics==5.3.0 \ + --hash=sha256:4f7d067d5bb08422599ca6175510d39b0911c711301647e5f18e904a5027bf58 \ + --hash=sha256:69bb736d93de81060e9075d42b6f0b92c25be0fb106da5cb6a6d30e772168221 +azure-ai-vision-imageanalysis==1.0.0 \ + --hash=sha256:9a7e4aed611d8b4b5fbe528e4e56257d3543b26affe98914f5fd2c53381c264d \ + --hash=sha256:a79bbbb9c6992fef3be53395d339c9db850719583ef96ac64e054b00b545b3b6 +azure-common==1.1.28 \ + --hash=sha256:4ac0cd3214e36b6a1b6a442686722a5d8cc449603aa833f3f0f40bda836704a3 \ + --hash=sha256:5c12d3dcf4ec20599ca6b0d3e09e86e146353d443e7fcc050c9a19c1f9df20ad +azure-core==1.32.0 \ + --hash=sha256:22b3c35d6b2dae14990f6c1be2912bf23ffe50b220e708a28ab1bb92b1c730e5 \ + --hash=sha256:eac191a0efb23bfa83fddf321b27b122b4ec847befa3091fa736a5c32c50d7b4 +azure-functions==1.21.3 \ + --hash=sha256:6c45f5e61fe59328c81928a428d43c838e9ead52f1cde1628fcabb372fa10cc8 \ + --hash=sha256:c359b9dbd2998c84d8595e31a28ffad4e8ca8dcfb4a3798327f776a67f964351 +azure-identity==1.19.0 \ + --hash=sha256:500144dc18197d7019b81501165d4fa92225f03778f17d7ca8a2a180129a9c83 \ + --hash=sha256:e3f6558c181692d7509f09de10cca527c7dce426776454fb97df512a46527e81 +azure-search==1.0.0b2 \ + --hash=sha256:49cbb1937b2e256f6631d467f62f8a1c94a14c5fed84f6625d24bc7b210a25d4 \ + --hash=sha256:ba3974224be1329d26e58e63df9c8561b416e7536b79a1c5576055dfb6c472ae +azure-search-documents==11.6.0b8 \ + --hash=sha256:5fa84bacbf72b9778ab7a2a43ab5df335fc5516eeb169c36d78ced39a29cfe69 \ + --hash=sha256:edd7af876dc9353d1ede46429547df0a3891beed182308636f0f86a97cce94b5 +azure-storage-blob==12.24.0 \ + --hash=sha256:4f0bb4592ea79a2d986063696514c781c9e62be240f09f6397986e01755bc071 \ + --hash=sha256:eaaaa1507c8c363d6e1d1342bd549938fdf1adec9b1ada8658c8f5bf3aea844e +babel==2.16.0 \ + --hash=sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b \ + --hash=sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316 +beautifulsoup4==4.12.3 \ + --hash=sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051 \ + --hash=sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed +black==24.10.0 \ + --hash=sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f \ + --hash=sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981 \ + --hash=sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b \ + --hash=sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8 \ + --hash=sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d \ + --hash=sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b \ + --hash=sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875 \ + --hash=sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3 \ + --hash=sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65 \ + --hash=sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2 +bleach==6.2.0 \ + --hash=sha256:117d9c6097a7c3d22fd578fcd8d35ff1e125df6736f554da4e432fdd63f31e5e \ + --hash=sha256:123e894118b8a599fd80d3ec1a6d4cc7ce4e5882b1317a7e1ba69b56e95f991f +blis==0.7.11 \ + --hash=sha256:5a305dbfc96d202a20d0edd6edf74a406b7e1404f4fa4397d24c68454e60b1b4 \ + --hash=sha256:5bcdaf370f03adaf4171d6405a89fa66cb3c09399d75fc02e1230a78cd2759e4 \ + --hash=sha256:7de19264b1d49a178bf8035406d0ae77831f3bfaa3ce02942964a81a202abb03 \ + --hash=sha256:8ea55c6a4a60fcbf6a0fdce40df6e254451ce636988323a34b9c94b583fc11e5 \ + --hash=sha256:cec6d48f75f7ac328ae1b6fbb372dde8c8a57c89559172277f66e01ff08d4d42 \ + --hash=sha256:dadf8713ea51d91444d14ad4104a5493fa7ecc401bbb5f4a203ff6448fadb113 +bs4==0.0.2 \ + --hash=sha256:a48685c58f50fe127722417bae83fe6badf500d54b55f7e39ffe43b798653925 \ + --hash=sha256:abf8742c0805ef7f662dce4b51cca104cffe52b835238afc169142ab9b3fbccc +catalogue==2.0.10 \ + --hash=sha256:4f56daa940913d3f09d589c191c74e5a6d51762b3a9e37dd53b7437afd6cda15 \ + --hash=sha256:58c2de0020aa90f4a2da7dfad161bf7b3b054c86a5f09fcedc0b2b740c109a9f +certifi==2024.12.14 \ + --hash=sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56 \ + --hash=sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db +cffi==1.17.1 \ + --hash=sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2 \ + --hash=sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36 \ + --hash=sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824 \ + --hash=sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3 \ + --hash=sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed \ + --hash=sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8 \ + --hash=sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903 \ + --hash=sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683 \ + --hash=sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9 \ + --hash=sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c \ + --hash=sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4 \ + --hash=sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65 \ + --hash=sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93 \ + --hash=sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4 \ + --hash=sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3 \ + --hash=sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff \ + --hash=sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5 \ + --hash=sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd \ + --hash=sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5 \ + --hash=sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d \ + --hash=sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e \ + --hash=sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a \ + --hash=sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99 +cfgv==3.4.0 \ + --hash=sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9 \ + --hash=sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560 +charset-normalizer==3.4.1 \ + --hash=sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd \ + --hash=sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601 \ + --hash=sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d \ + --hash=sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313 \ + --hash=sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa \ + --hash=sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2 \ + --hash=sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b \ + --hash=sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3 \ + --hash=sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f \ + --hash=sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9 \ + --hash=sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f \ + --hash=sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545 \ + --hash=sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b \ + --hash=sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9 \ + --hash=sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11 \ + --hash=sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35 \ + --hash=sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda \ + --hash=sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971 \ + --hash=sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d \ + --hash=sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757 \ + --hash=sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a \ + --hash=sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886 \ + --hash=sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85 \ + --hash=sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7 \ + --hash=sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1 \ + --hash=sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407 \ + --hash=sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd \ + --hash=sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616 +click==8.1.8 \ + --hash=sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2 \ + --hash=sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a +cloudpathlib==0.20.0 \ + --hash=sha256:7af3bcefbf73392ae7f31c08b3660ec31607f8c01b7f6262d4d73469a845f641 \ + --hash=sha256:f6ef7ca409a510f7ba4639ba50ab3fc5b6dee82d6dff0d7f5715fd0c9ab35891 +colorama==0.4.6 ; sys_platform == 'win32' \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 +comm==0.2.2 \ + --hash=sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e \ + --hash=sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3 +confection==0.1.5 \ + --hash=sha256:8e72dd3ca6bd4f48913cd220f10b8275978e740411654b6e8ca6d7008c590f0e \ + --hash=sha256:e29d3c3f8eac06b3f77eb9dfb4bf2fc6bcc9622a98ca00a698e3d019c6430b14 +cryptography==44.0.0 \ + --hash=sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7 \ + --hash=sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b \ + --hash=sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc \ + --hash=sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543 \ + --hash=sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591 \ + --hash=sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede \ + --hash=sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb \ + --hash=sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f \ + --hash=sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123 \ + --hash=sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c \ + --hash=sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285 \ + --hash=sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd \ + --hash=sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092 \ + --hash=sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289 \ + --hash=sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02 \ + --hash=sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64 \ + --hash=sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053 \ + --hash=sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417 \ + --hash=sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e \ + --hash=sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e \ + --hash=sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7 +cymem==2.0.11 \ + --hash=sha256:02ed92bead896cca36abad00502b14fa651bdf5d8319461126a2d5ac8c9674c5 \ + --hash=sha256:04ee6b4041ddec24512d6e969ed6445e57917f01e73b9dabbe17b7e6b27fef05 \ + --hash=sha256:0c269c7a867d74adeb9db65fa1d226342aacf44d64b7931282f0b0eb22eb6275 \ + --hash=sha256:25da111adf425c29af0cfd9fecfec1c71c8d82e2244a85166830a0817a66ada7 \ + --hash=sha256:44ddd3588379f8f376116384af99e3fb5f90091d90f520c341942618bf22f05e \ + --hash=sha256:5461e65340d6572eb64deadce79242a446a1d39cb7bf70fe7b7e007eb0d799b0 \ + --hash=sha256:5b02f2b17d760dc3fe5812737b1ce4f684641cdd751d67761d333a3b5ea97b83 \ + --hash=sha256:87ec985623624bbd298762d8163fc194a096cb13282731a017e09ff8a60bb8b1 \ + --hash=sha256:a0fbe19ce653cd688842d81e5819dc63f911a26e192ef30b0b89f0ab2b192ff2 \ + --hash=sha256:bee4395917f6588b8ac1699499128842768b391fe8896e8626950b4da5f9a406 \ + --hash=sha256:de72101dc0e6326f6a2f73e05a438d1f3c6110d41044236d0fbe62925091267d \ + --hash=sha256:e1048dae7e627ee25f22c87bb670b13e06bc0aecc114b89b959a798d487d1bf4 \ + --hash=sha256:e3385a47285435848e0ed66cfd29b35f3ed8703218e2b17bd7a0c053822f26bf \ + --hash=sha256:efe49a349d4a518be6b6c6b255d4a80f740a341544bde1a807707c058b88d0bd \ + --hash=sha256:f4a311c82f743275c84f708df89ac5bf60ddefe4713d532000c887931e22941f +debugpy==1.8.12 \ + --hash=sha256:086b32e233e89a2740c1615c2f775c34ae951508b28b308681dbbb87bba97d06 \ + --hash=sha256:22a11c493c70413a01ed03f01c3c3a2fc4478fc6ee186e340487b2edcd6f4180 \ + --hash=sha256:274b6a2040349b5c9864e475284bce5bb062e63dce368a394b8cc865ae3b00c6 \ + --hash=sha256:2ae5df899732a6051b49ea2632a9ea67f929604fd2b036613a9f12bc3163b92d \ + --hash=sha256:39dfbb6fa09f12fae32639e3286112fc35ae976114f1f3d37375f3130a820969 \ + --hash=sha256:646530b04f45c830ceae8e491ca1c9320a2d2f0efea3141487c82130aba70dce \ + --hash=sha256:696d8ae4dff4cbd06bf6b10d671e088b66669f110c7c4e18a44c43cf75ce966f \ + --hash=sha256:7e94b643b19e8feb5215fa508aee531387494bf668b2eca27fa769ea11d9f498 \ + --hash=sha256:898fba72b81a654e74412a67c7e0a81e89723cfe2a3ea6fcd3feaa3395138ca9 \ + --hash=sha256:fdb3c6d342825ea10b90e43d7f20f01535a72b3a1997850c0c3cefa5c27a4a2c +decorator==5.1.1 \ + --hash=sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330 \ + --hash=sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186 +defusedxml==0.7.1 \ + --hash=sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69 \ + --hash=sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61 +distlib==0.3.9 \ + --hash=sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87 \ + --hash=sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403 +distro==1.9.0 \ + --hash=sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed \ + --hash=sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2 +en-core-web-md @ https://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.7.1/en_core_web_md-3.7.1.tar.gz \ + --hash=sha256:3273a1335fcb688be09949c5cdb73e85eb584ec3dfc50d4338c17daf6ccd4628 +et-xmlfile==2.0.0 \ + --hash=sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa \ + --hash=sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54 +executing==2.1.0 \ + --hash=sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf \ + --hash=sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab +fastjsonschema==2.21.1 \ + --hash=sha256:794d4f0a58f848961ba16af7b9c85a3e88cd360df008c59aac6fc5ae9323b5d4 \ + --hash=sha256:c9e5b7e908310918cf494a434eeb31384dd84a98b57a30bcb1f535015b554667 +filelock==3.17.0 \ + --hash=sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338 \ + --hash=sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e +fqdn==1.5.1 \ + --hash=sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f \ + --hash=sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014 +frozenlist==1.5.0 \ + --hash=sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e \ + --hash=sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28 \ + --hash=sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b \ + --hash=sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9 \ + --hash=sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2 \ + --hash=sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8 \ + --hash=sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6 \ + --hash=sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21 \ + --hash=sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c \ + --hash=sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608 \ + --hash=sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de \ + --hash=sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f \ + --hash=sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641 \ + --hash=sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9 \ + --hash=sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f \ + --hash=sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a \ + --hash=sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784 \ + --hash=sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d \ + --hash=sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03 \ + --hash=sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e \ + --hash=sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953 \ + --hash=sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee \ + --hash=sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817 \ + --hash=sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039 \ + --hash=sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f \ + --hash=sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439 \ + --hash=sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631 \ + --hash=sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840 \ + --hash=sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3 \ + --hash=sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0 \ + --hash=sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e \ + --hash=sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a +fsspec==2024.12.0 \ + --hash=sha256:670700c977ed2fb51e0d9f9253177ed20cbde4a3e5c0283cc5385b5870c8533f \ + --hash=sha256:b520aed47ad9804237ff878b504267a3b0b441e97508bd6d2d8774e3db85cee2 +h11==0.14.0 \ + --hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \ + --hash=sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761 +httpcore==1.0.7 \ + --hash=sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c \ + --hash=sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd +httpx==0.28.1 \ + --hash=sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc \ + --hash=sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad +huggingface-hub==0.27.1 \ + --hash=sha256:1c5155ca7d60b60c2e2fc38cbb3ffb7f7c3adf48f824015b219af9061771daec \ + --hash=sha256:c004463ca870283909d715d20f066ebd6968c2207dae9393fdffb3c1d4d8f98b +identify==2.6.6 \ + --hash=sha256:7bec12768ed44ea4761efb47806f0a41f86e7c0a5fdf5950d4648c90eca7e251 \ + --hash=sha256:cbd1810bce79f8b671ecb20f53ee0ae8e86ae84b557de31d89709dc2a48ba881 +idna==3.10 \ + --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \ + --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3 +ipykernel==6.29.5 \ + --hash=sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5 \ + --hash=sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215 +ipython==8.31.0 \ + --hash=sha256:46ec58f8d3d076a61d128fe517a51eb730e3aaf0c184ea8c17d16e366660c6a6 \ + --hash=sha256:b6a2274606bec6166405ff05e54932ed6e5cfecaca1fc05f2cacde7bb074d70b +ipywidgets==8.1.5 \ + --hash=sha256:3290f526f87ae6e77655555baba4f36681c555b8bdbbff430b70e52c34c86245 \ + --hash=sha256:870e43b1a35656a80c18c9503bbf2d16802db1cb487eec6fab27d683381dde17 +isodate==0.7.2 \ + --hash=sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15 \ + --hash=sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6 +isoduration==20.11.0 \ + --hash=sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9 \ + --hash=sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042 +jedi==0.19.2 \ + --hash=sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0 \ + --hash=sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9 +jinja2==3.1.5 \ + --hash=sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb \ + --hash=sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb +jiter==0.8.2 \ + --hash=sha256:025337859077b41548bdcbabe38698bcd93cfe10b06ff66617a48ff92c9aec60 \ + --hash=sha256:14601dcac4889e0a1c75ccf6a0e4baf70dbc75041e51bcf8d0e9274519df6887 \ + --hash=sha256:180a8aea058f7535d1c84183c0362c710f4750bef66630c05f40c93c2b152a0f \ + --hash=sha256:37b2998606d6dadbb5ccda959a33d6a5e853252d921fec1792fc902351bb4e2c \ + --hash=sha256:3ac9f578c46f22405ff7f8b1f5848fb753cc4b8377fbec8470a7dc3997ca7566 \ + --hash=sha256:4ab9a87f3784eb0e098f84a32670cfe4a79cb6512fd8f42ae3d0709f06405d18 \ + --hash=sha256:5672a86d55416ccd214c778efccf3266b84f87b89063b582167d803246354be4 \ + --hash=sha256:58dc9bc9767a1101f4e5e22db1b652161a225874d66f0e5cb8e2c7d1c438b587 \ + --hash=sha256:653cf462db4e8c41995e33d865965e79641ef45369d8a11f54cd30888b7e6ff1 \ + --hash=sha256:711e408732d4e9a0208008e5892c2966b485c783cd2d9a681f3eb147cf36c7ef \ + --hash=sha256:76e324da7b5da060287c54f2fabd3db5f76468006c811831f051942bf68c9d44 \ + --hash=sha256:789361ed945d8d42850f919342a8665d2dc79e7e44ca1c97cc786966a21f627a \ + --hash=sha256:79aec8172b9e3c6d05fd4b219d5de1ac616bd8da934107325a6c0d0e866a21b6 \ + --hash=sha256:7efe4853ecd3d6110301665a5178b9856be7e2a9485f49d91aa4d737ad2ae49e \ + --hash=sha256:83c0efd80b29695058d0fd2fa8a556490dbce9804eac3e281f373bbc99045f6c \ + --hash=sha256:92249669925bc1c54fcd2ec73f70f2c1d6a817928480ee1c65af5f6b81cdf12d \ + --hash=sha256:9c63eaef32b7bebac8ebebf4dabebdbc6769a09c127294db6babee38e9f405b9 \ + --hash=sha256:ab7f43235d71e03b941c1630f4b6e3055d46b6cb8728a17663eaac9d8e83a865 \ + --hash=sha256:b2dd880785088ff2ad21ffee205e58a8c1ddabc63612444ae41e5e4b321b39c0 \ + --hash=sha256:b426f72cd77da3fec300ed3bc990895e2dd6b49e3bfe6c438592a3ba660e41ca \ + --hash=sha256:bf55846c7b7a680eebaf9c3c48d630e1bf51bdf76c68a5f654b8524335b0ad29 \ + --hash=sha256:ca1f08b8e43dc3bd0594c992fb1fd2f7ce87f7bf0d44358198d6da8034afdf84 \ + --hash=sha256:cd73d3e740666d0e639f678adb176fad25c1bcbdae88d8d7b857e1783bb4212d \ + --hash=sha256:e6ec2be506e7d6f9527dae9ff4b7f54e68ea44a0ef6b098256ddf895218a2f8f \ + --hash=sha256:e725edd0929fa79f8349ab4ec7f81c714df51dc4e991539a578e5018fa4a7152 \ + --hash=sha256:eb21aaa9a200d0a80dacc7a81038d2e476ffe473ffdd9c91eb745d623561de05 \ + --hash=sha256:ecff0dc14f409599bbcafa7e470c00b80f17abc14d1405d38ab02e4b42e55b57 \ + --hash=sha256:ffd9fee7d0775ebaba131f7ca2e2d83839a62ad65e8e02fe2bd8fc975cedeb9e +joblib==1.4.2 \ + --hash=sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6 \ + --hash=sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e +json5==0.10.0 \ + --hash=sha256:19b23410220a7271e8377f81ba8aacba2fdd56947fbb137ee5977cbe1f5e8dfa \ + --hash=sha256:e66941c8f0a02026943c52c2eb34ebeb2a6f819a0be05920a6f5243cd30fd559 +jsonpointer==3.0.0 \ + --hash=sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942 \ + --hash=sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef +jsonschema==4.23.0 \ + --hash=sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4 \ + --hash=sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566 +jsonschema-specifications==2024.10.1 \ + --hash=sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272 \ + --hash=sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf +jupyter==1.1.1 \ + --hash=sha256:7a59533c22af65439b24bbe60373a4e95af8f16ac65a6c00820ad378e3f7cc83 \ + --hash=sha256:d55467bceabdea49d7e3624af7e33d59c37fff53ed3a350e1ac957bed731de7a +jupyter-client==8.6.3 \ + --hash=sha256:35b3a0947c4a6e9d589eb97d7d4cd5e90f910ee73101611f01283732bd6d9419 \ + --hash=sha256:e8a19cc986cc45905ac3362915f410f3af85424b4c0905e94fa5f2cb08e8f23f +jupyter-console==6.6.3 \ + --hash=sha256:309d33409fcc92ffdad25f0bcdf9a4a9daa61b6f341177570fdac03de5352485 \ + --hash=sha256:566a4bf31c87adbfadf22cdf846e3069b59a71ed5da71d6ba4d8aaad14a53539 +jupyter-core==5.7.2 \ + --hash=sha256:4f7315d2f6b4bcf2e3e7cb6e46772eba760ae459cd1f59d29eb57b0a01bd7409 \ + --hash=sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9 +jupyter-events==0.11.0 \ + --hash=sha256:36399b41ce1ca45fe8b8271067d6a140ffa54cec4028e95491c93b78a855cacf \ + --hash=sha256:c0bc56a37aac29c1fbc3bcfbddb8c8c49533f9cf11f1c4e6adadba936574ab90 +jupyter-lsp==2.2.5 \ + --hash=sha256:45fbddbd505f3fbfb0b6cb2f1bc5e15e83ab7c79cd6e89416b248cb3c00c11da \ + --hash=sha256:793147a05ad446f809fd53ef1cd19a9f5256fd0a2d6b7ce943a982cb4f545001 +jupyter-server==2.15.0 \ + --hash=sha256:872d989becf83517012ee669f09604aa4a28097c0bd90b2f424310156c2cdae3 \ + --hash=sha256:9d446b8697b4f7337a1b7cdcac40778babdd93ba614b6d68ab1c0c918f1c4084 +jupyter-server-terminals==0.5.3 \ + --hash=sha256:41ee0d7dc0ebf2809c668e0fc726dfaf258fcd3e769568996ca731b6194ae9aa \ + --hash=sha256:5ae0295167220e9ace0edcfdb212afd2b01ee8d179fe6f23c899590e9b8a5269 +jupyterlab==4.3.4 \ + --hash=sha256:b754c2601c5be6adf87cb5a1d8495d653ffb945f021939f77776acaa94dae952 \ + --hash=sha256:f0bb9b09a04766e3423cccc2fc23169aa2ffedcdf8713e9e0fb33cac0b6859d0 +jupyterlab-pygments==0.3.0 \ + --hash=sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d \ + --hash=sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780 +jupyterlab-server==2.27.3 \ + --hash=sha256:e697488f66c3db49df675158a77b3b017520d772c6e1548c7d9bcc5df7944ee4 \ + --hash=sha256:eb36caca59e74471988f0ae25c77945610b887f777255aa21f8065def9e51ed4 +jupyterlab-widgets==3.0.13 \ + --hash=sha256:a2966d385328c1942b683a8cd96b89b8dd82c8b8f81dda902bb2bc06d46f5bed \ + --hash=sha256:e3cda2c233ce144192f1e29914ad522b2f4c40e77214b0cc97377ca3d323db54 +langcodes==3.5.0 \ + --hash=sha256:1eef8168d07e51e131a2497ffecad4b663f6208e7c3ae3b8dc15c51734a6f801 \ + --hash=sha256:853c69d1a35e0e13da2f427bb68fb2fa4a8f4fb899e0c62ad8df8d073dcfed33 +language-data==1.3.0 \ + --hash=sha256:7600ef8aa39555145d06c89f0c324bf7dab834ea0b0a439d8243762e3ebad7ec \ + --hash=sha256:e2ee943551b5ae5f89cd0e801d1fc3835bb0ef5b7e9c3a4e8e17b2b214548fbf +marisa-trie==1.2.1 \ + --hash=sha256:20948e40ab2038e62b7000ca6b4a913bc16c91a2c2e6da501bd1f917eeb28d51 \ + --hash=sha256:2428b495003c189695fb91ceeb499f9fcced3a2dce853e17fa475519433c67ff \ + --hash=sha256:36aa4401a1180615f74d575571a6550081d84fc6461e9aefc0bb7b2427af098e \ + --hash=sha256:3a27c408e2aefc03e0f1d25b2ff2afb85aac3568f6fa2ae2a53b57a2e87ce29d \ + --hash=sha256:3ad356442c2fea4c2a6f514738ddf213d23930f942299a2b2c05df464a00848a \ + --hash=sha256:46e528ee71808c961baf8c3ce1c46a8337ec7a96cc55389d11baafe5b632f8e9 \ + --hash=sha256:5e649f3dc8ab5476732094f2828cc90cac3be7c79bc0c8318b6fda0c1d248db4 \ + --hash=sha256:638506eacf20ca503fff72221a7e66a6eadbf28d6a4a6f949fcf5b1701bb05ec \ + --hash=sha256:6532615111eec2c79e711965ece0bc95adac1ff547a7fff5ffca525463116deb \ + --hash=sha256:66b23e5b35dd547f85bf98db7c749bc0ffc57916ade2534a6bbc32db9a4abc44 \ + --hash=sha256:6704adf0247d2dda42e876b793be40775dff46624309ad99bc7537098bee106d \ + --hash=sha256:735c363d9aaac82eaf516a28f7c6b95084c2e176d8231c87328dc80e112a9afa \ + --hash=sha256:98042040d1d6085792e8d0f74004fc0f5f9ca6091c298f593dd81a22a4643854 \ + --hash=sha256:9f627f4e41be710b6cb6ed54b0128b229ac9d50e2054d9cde3af0fef277c23cf \ + --hash=sha256:aa7cd17e1c690ce96c538b2f4aae003d9a498e65067dd433c52dd069009951d4 \ + --hash=sha256:b2a7d00f53f4945320b551bccb826b3fb26948bde1a10d50bb9802fabb611b10 \ + --hash=sha256:b5ea16e69bfda0ac028c921b58de1a4aaf83d43934892977368579cd3c0a2554 \ + --hash=sha256:ce59bcd2cda9bb52b0e90cc7f36413cd86c3d0ce7224143447424aafb9f4aa48 \ + --hash=sha256:de1665eaafefa48a308e4753786519888021740501a15461c77bdfd57638e6b4 \ + --hash=sha256:eba6ca45500ca1a042466a0684aacc9838e7f20fe2605521ee19f2853062798f \ + --hash=sha256:f2806f75817392cedcacb24ac5d80b0350dde8d3861d67d045c1d9b109764114 \ + --hash=sha256:f4cd800704a5fc57e53c39c3a6b0c9b1519ebdbcb644ede3ee67a06eb542697d \ + --hash=sha256:f713af9b8aa66a34cd3a78c7d150a560a75734713abe818a69021fd269e927fa +markdown-it-py==3.0.0 \ + --hash=sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1 \ + --hash=sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb +markupsafe==3.0.2 \ + --hash=sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30 \ + --hash=sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9 \ + --hash=sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396 \ + --hash=sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028 \ + --hash=sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557 \ + --hash=sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a \ + --hash=sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c \ + --hash=sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c \ + --hash=sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22 \ + --hash=sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094 \ + --hash=sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5 \ + --hash=sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225 \ + --hash=sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c \ + --hash=sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87 \ + --hash=sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf \ + --hash=sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb \ + --hash=sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48 \ + --hash=sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c \ + --hash=sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6 \ + --hash=sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd \ + --hash=sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1 \ + --hash=sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d \ + --hash=sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca \ + --hash=sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a \ + --hash=sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe \ + --hash=sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8 \ + --hash=sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f \ + --hash=sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f \ + --hash=sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0 \ + --hash=sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79 \ + --hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430 +matplotlib-inline==0.1.7 \ + --hash=sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90 \ + --hash=sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca +mdurl==0.1.2 \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ + --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba +mistune==3.1.0 \ + --hash=sha256:b05198cf6d671b3deba6c87ec6cf0d4eb7b72c524636eddb6dbf13823b52cee1 \ + --hash=sha256:dbcac2f78292b9dc066cd03b7a3a26b62d85f8159f2ea5fd28e55df79908d667 +model2vec==0.3.7 \ + --hash=sha256:1f13532fcbad57da524fd3ae1580597cdd2bc5d76077dd4f87dfd2b5a411540e \ + --hash=sha256:5000a19d86e76f20afa4b403946f512a4c17496e35295b8855e728f4ba04ec89 +msal==1.31.1 \ + --hash=sha256:11b5e6a3f802ffd3a72107203e20c4eac6ef53401961b880af2835b723d80578 \ + --hash=sha256:29d9882de247e96db01386496d59f29035e5e841bcac892e6d7bf4390bf6bd17 +msal-extensions==1.2.0 \ + --hash=sha256:6f41b320bfd2933d631a215c91ca0dd3e67d84bd1a2f50ce917d5874ec646bef \ + --hash=sha256:cf5ba83a2113fa6dc011a254a72f1c223c88d7dfad74cc30617c4679a417704d +msrest==0.7.1 \ + --hash=sha256:21120a810e1233e5e6cc7fe40b474eeb4ec6f757a15d7cf86702c369f9567c32 \ + --hash=sha256:6e7661f46f3afd88b75667b7187a92829924446c7ea1d169be8c4bb7eeb788b9 +multidict==6.1.0 \ + --hash=sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f \ + --hash=sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761 \ + --hash=sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3 \ + --hash=sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6 \ + --hash=sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966 \ + --hash=sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1 \ + --hash=sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305 \ + --hash=sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a \ + --hash=sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c \ + --hash=sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4 \ + --hash=sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81 \ + --hash=sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3 \ + --hash=sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506 \ + --hash=sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925 \ + --hash=sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6 \ + --hash=sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e \ + --hash=sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95 \ + --hash=sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2 \ + --hash=sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133 \ + --hash=sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa \ + --hash=sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3 \ + --hash=sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436 \ + --hash=sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2 \ + --hash=sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2 \ + --hash=sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa \ + --hash=sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b \ + --hash=sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa \ + --hash=sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef \ + --hash=sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44 \ + --hash=sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008 \ + --hash=sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774 \ + --hash=sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28 +murmurhash==1.0.12 \ + --hash=sha256:19de30edaaa2217cd0c41b6cf6bbfa418be5d7fdf267ca92e5e3710d4daac593 \ + --hash=sha256:1a4c97c8ffbedb62b760c3c2f77b5b8cb0e0ac0ec83a74d2f289e113e3e92ed5 \ + --hash=sha256:467b7ee31c1f79f46d00436a1957fc52a0e5801369dd2f30eb7655f380735b5f \ + --hash=sha256:63f10c6d6ef9ee85073dd896d2c4e0ab161bc6b8e7e9201c69f8061f9f1b6468 \ + --hash=sha256:66356f6308fd2a44a8ab056f020acd5bc22302f23ef5cce3705f2493e0fe9c3c \ + --hash=sha256:701cc0ce91809b4d7c2e0518be759635205e1e181325792044f5a8118019f716 \ + --hash=sha256:7a7ef5fb37e72536458ac4a6f486fb374c60ac4c4862d9195d3d4b58239a91de \ + --hash=sha256:7dc4ebdfed7ef8ed70519962ac9b704e91978ee14e049f1ff37bca2f579ce84d \ + --hash=sha256:7e1c9de2167a9d408d121ebc918bcb20b2718ec956f3aae0ded53d9bb224bb8e \ + --hash=sha256:8bd5524de195991ce3551b14286ec0b730cc9dd2e10565dad2ae470eec082028 \ + --hash=sha256:8c5b8804c07a76f779e67f83aad37bc2189a0e65ebdd3f2b305242d489d31e03 \ + --hash=sha256:94a52972835bdae8af18147c67c398ff3ea1d875f5b8dca1e1aa0fadb892f546 \ + --hash=sha256:9574f0b634f059158bb89734a811e435ac9ad2335c02a7abb59f1875dcce244c \ + --hash=sha256:bdb2104aa3471324724abf5a3a76fc94bcbeaf023bb6a6dd94da567b8633d8a6 \ + --hash=sha256:cc88004c8615dcabe31d21142689f719fdf549ba782850bef389cf227a1df575 +mypy-extensions==1.0.0 \ + --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \ + --hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782 +nbclient==0.10.2 \ + --hash=sha256:4ffee11e788b4a27fabeb7955547e4318a5298f34342a4bfd01f2e1faaeadc3d \ + --hash=sha256:90b7fc6b810630db87a6d0c2250b1f0ab4cf4d3c27a299b0cde78a4ed3fd9193 +nbconvert==7.16.5 \ + --hash=sha256:c83467bb5777fdfaac5ebbb8e864f300b277f68692ecc04d6dab72f2d8442344 \ + --hash=sha256:e12eac052d6fd03040af4166c563d76e7aeead2e9aadf5356db552a1784bd547 +nbformat==5.10.4 \ + --hash=sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a \ + --hash=sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b +nest-asyncio==1.6.0 \ + --hash=sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe \ + --hash=sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c +nodeenv==1.9.1 \ + --hash=sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f \ + --hash=sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9 +notebook==7.3.2 \ + --hash=sha256:705e83a1785f45b383bf3ee13cb76680b92d24f56fb0c7d2136fe1d850cd3ca8 \ + --hash=sha256:e5f85fc59b69d3618d73cf27544418193ff8e8058d5bf61d315ce4f473556288 +notebook-shim==0.2.4 \ + --hash=sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef \ + --hash=sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb +numpy==1.26.4 \ + --hash=sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b \ + --hash=sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818 \ + --hash=sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0 \ + --hash=sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010 \ + --hash=sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110 \ + --hash=sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed \ + --hash=sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b \ + --hash=sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a \ + --hash=sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218 +oauthlib==3.2.2 \ + --hash=sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca \ + --hash=sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918 +openai==1.59.9 \ + --hash=sha256:61a0608a1313c08ddf92fe793b6dbd1630675a1fe3866b2f96447ce30050c448 \ + --hash=sha256:ec1a20b0351b4c3e65c6292db71d8233515437c6065efd4fd50edeb55df5f5d2 +openpyxl==3.1.5 \ + --hash=sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2 \ + --hash=sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050 +overrides==7.7.0 \ + --hash=sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a \ + --hash=sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49 +packaging==24.2 \ + --hash=sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759 \ + --hash=sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f +pandas==2.2.3 \ + --hash=sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a \ + --hash=sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d \ + --hash=sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4 \ + --hash=sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0 \ + --hash=sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28 \ + --hash=sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18 \ + --hash=sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468 \ + --hash=sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667 \ + --hash=sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13 \ + --hash=sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3 \ + --hash=sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d \ + --hash=sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb \ + --hash=sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8 \ + --hash=sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659 \ + --hash=sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4 \ + --hash=sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a \ + --hash=sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9 \ + --hash=sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2 \ + --hash=sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015 \ + --hash=sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24 \ + --hash=sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319 +pandocfilters==1.5.1 \ + --hash=sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e \ + --hash=sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc +parso==0.8.4 \ + --hash=sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18 \ + --hash=sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d +pathspec==0.12.1 \ + --hash=sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08 \ + --hash=sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712 +pexpect==4.9.0 ; sys_platform != 'emscripten' and sys_platform != 'win32' \ + --hash=sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523 \ + --hash=sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f +pillow==11.1.0 \ + --hash=sha256:11633d58b6ee5733bde153a8dafd25e505ea3d32e261accd388827ee987baf65 \ + --hash=sha256:2062ffb1d36544d42fcaa277b069c88b01bb7298f4efa06731a7fd6cc290b81a \ + --hash=sha256:31eba6bbdd27dde97b0174ddf0297d7a9c3a507a8a1480e1e60ef914fe23d352 \ + --hash=sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20 \ + --hash=sha256:36ba10b9cb413e7c7dfa3e189aba252deee0602c86c309799da5a74009ac7a1c \ + --hash=sha256:3764d53e09cdedd91bee65c2527815d315c6b90d7b8b79759cc48d7bf5d4f114 \ + --hash=sha256:3cdcdb0b896e981678eee140d882b70092dac83ac1cdf6b3a60e2216a73f2b91 \ + --hash=sha256:4dd43a78897793f60766563969442020e90eb7847463eca901e41ba186a7d4a5 \ + --hash=sha256:593c5fd6be85da83656b93ffcccc2312d2d149d251e98588b14fbc288fd8909c \ + --hash=sha256:67cd427c68926108778a9005f2a04adbd5e67c442ed21d95389fe1d595458756 \ + --hash=sha256:70ca5ef3b3b1c4a0812b5c63c57c23b63e53bc38e758b37a951e5bc466449861 \ + --hash=sha256:758e9d4ef15d3560214cddbc97b8ef3ef86ce04d62ddac17ad39ba87e89bd3b1 \ + --hash=sha256:7fdadc077553621911f27ce206ffcbec7d3f8d7b50e0da39f10997e8e2bb7f6a \ + --hash=sha256:8000376f139d4d38d6851eb149b321a52bb8893a88dae8ee7d95840431977081 \ + --hash=sha256:9044b5e4f7083f209c4e35aa5dd54b1dd5b112b108648f5c902ad586d4f945c5 \ + --hash=sha256:93a18841d09bcdd774dcdc308e4537e1f867b3dec059c131fde0327899734aa1 \ + --hash=sha256:9409c080586d1f683df3f184f20e36fb647f2e0bc3988094d4fd8c9f4eb1b3b3 \ + --hash=sha256:9aa9aeddeed452b2f616ff5507459e7bab436916ccb10961c4a382cd3e03f47f \ + --hash=sha256:9ee85f0696a17dd28fbcfceb59f9510aa71934b483d1f5601d1030c3c8304f3c \ + --hash=sha256:a697cd8ba0383bba3d2d3ada02b34ed268cb548b369943cd349007730c92bddf \ + --hash=sha256:a85b653980faad27e88b141348707ceeef8a1186f75ecc600c395dcac19f385b \ + --hash=sha256:ad5db5781c774ab9a9b2c4302bbf0c1014960a0a7be63278d13ae6fdf88126fe \ + --hash=sha256:ae98e14432d458fc3de11a77ccb3ae65ddce70f730e7c76140653048c71bfcbc \ + --hash=sha256:b523466b1a31d0dcef7c5be1f20b942919b62fd6e9a9be199d035509cbefc0ec \ + --hash=sha256:b5d658fbd9f0d6eea113aea286b21d3cd4d3fd978157cbf2447a6035916506d3 \ + --hash=sha256:cc1331b6d5a6e144aeb5e626f4375f5b7ae9934ba620c0ac6b3e43d5e683a0f0 \ + --hash=sha256:cfd5cd998c2e36a862d0e27b2df63237e67273f2fc78f47445b14e73a810e7e6 \ + --hash=sha256:dd0e081319328928531df7a0e63621caf67652c8464303fd102141b785ef9547 \ + --hash=sha256:dda60aa465b861324e65a78c9f5cf0f4bc713e4309f83bc387be158b077963d9 \ + --hash=sha256:e63e4e5081de46517099dc30abe418122f54531a6ae2ebc8680bcd7096860eab \ + --hash=sha256:f86d3a7a9af5d826744fabf4afd15b9dfef44fe69a98541f666f66fbb8d3fef9 +platformdirs==4.3.6 \ + --hash=sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907 \ + --hash=sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb +portalocker==2.10.1 \ + --hash=sha256:53a5984ebc86a025552264b459b46a2086e269b21823cb572f8f28ee759e45bf \ + --hash=sha256:ef1bf844e878ab08aee7e40184156e1151f228f103aa5c6bd0724cc330960f8f +pre-commit==4.1.0 \ + --hash=sha256:ae3f018575a588e30dfddfab9a05448bfbd6b73d78709617b5a2b853549716d4 \ + --hash=sha256:d29e7cb346295bcc1cc75fc3e92e343495e3ea0196c9ec6ba53f49f10ab6ae7b +preshed==3.0.9 \ + --hash=sha256:24229c77364628743bc29c5620c5d6607ed104f0e02ae31f8a030f99a78a5ceb \ + --hash=sha256:4a55091d0e395f1fdb62ab43401bb9f8b46c7d7794d5b071813c29dc1ab22fd0 \ + --hash=sha256:721863c5244ffcd2651ad0928951a2c7c77b102f4e11a251ad85d37ee7621660 \ + --hash=sha256:7de8f5138bcac7870424e09684dc3dd33c8e30e81b269f6c9ede3d8c7bb8e257 \ + --hash=sha256:b4fe6720012c62e6d550d6a5c1c7ad88cacef8388d186dad4bafea4140d9d198 \ + --hash=sha256:e04f05758875be9751e483bd3c519c22b00d3b07f5a64441ec328bb9e3c03700 +prometheus-client==0.21.1 \ + --hash=sha256:252505a722ac04b0456be05c05f75f45d760c2911ffc45f2a06bcaed9f3ae3fb \ + --hash=sha256:594b45c410d6f4f8888940fe80b5cc2521b305a1fafe1c58609ef715a001f301 +prompt-toolkit==3.0.50 \ + --hash=sha256:544748f3860a2623ca5cd6d2795e7a14f3d0e1c3c9728359013f79877fc89bab \ + --hash=sha256:9b6427eb19e479d98acff65196a307c555eb567989e6d88ebbb1b509d9779198 +propcache==0.2.1 \ + --hash=sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4 \ + --hash=sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a \ + --hash=sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f \ + --hash=sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9 \ + --hash=sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d \ + --hash=sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6 \ + --hash=sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d \ + --hash=sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30 \ + --hash=sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95 \ + --hash=sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348 \ + --hash=sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64 \ + --hash=sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce \ + --hash=sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629 \ + --hash=sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54 \ + --hash=sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1 \ + --hash=sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf \ + --hash=sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b \ + --hash=sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24 \ + --hash=sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5 \ + --hash=sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc \ + --hash=sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce \ + --hash=sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518 \ + --hash=sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536 \ + --hash=sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052 \ + --hash=sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff \ + --hash=sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1 \ + --hash=sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246 \ + --hash=sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0 \ + --hash=sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f \ + --hash=sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439 \ + --hash=sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6 \ + --hash=sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec \ + --hash=sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d \ + --hash=sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6 +psutil==6.1.1 \ + --hash=sha256:0bdd4eab935276290ad3cb718e9809412895ca6b5b334f5a9111ee6d9aff9377 \ + --hash=sha256:33431e84fee02bc84ea36d9e2c4a6d395d479c9dd9bba2376c1f6ee8f3a4e0b3 \ + --hash=sha256:97f7cb9921fbec4904f522d972f0c0e1f4fabbdd4e0287813b21215074a0f160 \ + --hash=sha256:b6e06c20c05fe95a3d7302d74e7097756d4ba1247975ad6905441ae1b5b66003 \ + --hash=sha256:cf8496728c18f2d0b45198f06895be52f36611711746b7f30c464b422b50e2f5 \ + --hash=sha256:eaa912e0b11848c4d9279a93d7e2783df352b082f40111e078388701fd479e53 \ + --hash=sha256:f35cfccb065fff93529d2afb4a2e89e363fe63ca1e4a5da22b603a85833c2649 \ + --hash=sha256:fc0ed7fe2231a444fc219b9c42d0376e0a9a1a72f16c5cfa0f68d19f1a0663e8 +ptyprocess==0.7.0 ; os_name != 'nt' or (sys_platform != 'emscripten' and sys_platform != 'win32') \ + --hash=sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35 \ + --hash=sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220 +pure-eval==0.2.3 \ + --hash=sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0 \ + --hash=sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42 +pycparser==2.22 \ + --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ + --hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc +pydantic==2.10.5 \ + --hash=sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff \ + --hash=sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53 +pydantic-core==2.27.2 \ + --hash=sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6 \ + --hash=sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7 \ + --hash=sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee \ + --hash=sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc \ + --hash=sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130 \ + --hash=sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4 \ + --hash=sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4 \ + --hash=sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b \ + --hash=sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934 \ + --hash=sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2 \ + --hash=sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9 \ + --hash=sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27 \ + --hash=sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b \ + --hash=sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154 \ + --hash=sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef \ + --hash=sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4 \ + --hash=sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee \ + --hash=sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c \ + --hash=sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0 \ + --hash=sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57 \ + --hash=sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b \ + --hash=sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1 \ + --hash=sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e \ + --hash=sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9 \ + --hash=sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1 \ + --hash=sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3 \ + --hash=sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39 \ + --hash=sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a \ + --hash=sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9 +pygments==2.19.1 \ + --hash=sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f \ + --hash=sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c +pyjwt==2.10.1 \ + --hash=sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953 \ + --hash=sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb +pymupdf==1.25.2 \ + --hash=sha256:1b4ca6f5780d319a08dff885a5a0e3585c5d7af04dcfa063c535b88371fd91c1 \ + --hash=sha256:295505fe1ecb7c7b57d4124d373e207ea311d8e40bc7ac3016d8ec2d60b091e9 \ + --hash=sha256:59dea22b633cc4fc13670b4c5db50d71f8cd4f420814420f33ce47ddcb61e1f6 \ + --hash=sha256:9ea88ff1b3ccb359620f106a6fd5ba6877d959d21d78272052c3496ceede6eec \ + --hash=sha256:ae8cfa7a97d78f813d286ecba32369059d88073edd1e5cf105f4cd0811f71925 \ + --hash=sha256:b9488c8b82bb9be36fb13ee0c8d43b0ddcc50af83b61da01e6040413d9e67da6 \ + --hash=sha256:e8b8a874497cd0deee89a6a4fb76a3a08173c8d39e88fc7cf715764ec5a243e9 \ + --hash=sha256:f61e5cdb25b86eb28d34aa3557b49ecf9e361d5f5cd3b1660406f8f0bf813af7 +python-dateutil==2.9.0.post0 \ + --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ + --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 +python-dotenv==1.0.1 \ + --hash=sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca \ + --hash=sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a +python-json-logger==3.2.1 \ + --hash=sha256:8eb0554ea17cb75b05d2848bc14fb02fbdbd9d6972120781b974380bfa162008 \ + --hash=sha256:cdc17047eb5374bd311e748b42f99d71223f3b0e186f4206cc5d52aefe85b090 +pytz==2024.2 \ + --hash=sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a \ + --hash=sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725 +pywin32==308 ; sys_platform == 'win32' \ + --hash=sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47 \ + --hash=sha256:1c44539a37a5b7b21d02ab34e6a4d314e0788f1690d65b48e9b0b89f31abbbed \ + --hash=sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897 \ + --hash=sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091 \ + --hash=sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd \ + --hash=sha256:fd380990e792eaf6827fcb7e187b2b4b1cede0585e3d0c9e84201ec27b9905e4 +pywinpty==2.0.14 ; os_name == 'nt' \ + --hash=sha256:074fb988a56ec79ca90ed03a896d40707131897cefb8f76f926e3834227f2819 \ + --hash=sha256:18bd9529e4a5daf2d9719aa17788ba6013e594ae94c5a0c27e83df3278b0660e \ + --hash=sha256:55dad362ef3e9408ade68fd173e4f9032b3ce08f68cfe7eacb2c263ea1179737 +pyyaml==6.0.2 \ + --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \ + --hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \ + --hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \ + --hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \ + --hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \ + --hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \ + --hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \ + --hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \ + --hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \ + --hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \ + --hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \ + --hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \ + --hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \ + --hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \ + --hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \ + --hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \ + --hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \ + --hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \ + --hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba +pyzmq==26.2.0 \ + --hash=sha256:007137c9ac9ad5ea21e6ad97d3489af654381324d5d3ba614c323f60dab8fae6 \ + --hash=sha256:034da5fc55d9f8da09015d368f519478a52675e558c989bfcb5cf6d4e16a7d2a \ + --hash=sha256:070672c258581c8e4f640b5159297580a9974b026043bd4ab0470be9ed324f1f \ + --hash=sha256:17bf5a931c7f6618023cdacc7081f3f266aecb68ca692adac015c383a134ca52 \ + --hash=sha256:23f4aad749d13698f3f7b64aad34f5fc02d6f20f05999eebc96b89b01262fb18 \ + --hash=sha256:25bf2374a2a8433633c65ccb9553350d5e17e60c8eb4de4d92cc6bd60f01d306 \ + --hash=sha256:28c812d9757fe8acecc910c9ac9dafd2ce968c00f9e619db09e9f8f54c3a68a3 \ + --hash=sha256:29c6a4635eef69d68a00321e12a7d2559fe2dfccfa8efae3ffb8e91cd0b36a8b \ + --hash=sha256:2a50625acdc7801bc6f74698c5c583a491c61d73c6b7ea4dee3901bb99adb27a \ + --hash=sha256:2ae90ff9dad33a1cfe947d2c40cb9cb5e600d759ac4f0fd22616ce6540f72797 \ + --hash=sha256:31507f7b47cc1ead1f6e86927f8ebb196a0bab043f6345ce070f412a59bf87b5 \ + --hash=sha256:43a47408ac52647dfabbc66a25b05b6a61700b5165807e3fbd40063fcaf46386 \ + --hash=sha256:4661c88db4a9e0f958c8abc2b97472e23061f0bc737f6f6179d7a27024e1faa5 \ + --hash=sha256:470d4a4f6d48fb34e92d768b4e8a5cc3780db0d69107abf1cd7ff734b9766eb0 \ + --hash=sha256:4d29ab8592b6ad12ebbf92ac2ed2bedcfd1cec192d8e559e2e099f648570e19b \ + --hash=sha256:4d80b1dd99c1942f74ed608ddb38b181b87476c6a966a88a950c7dee118fdf50 \ + --hash=sha256:55cf66647e49d4621a7e20c8d13511ef1fe1efbbccf670811864452487007e08 \ + --hash=sha256:6b274e0762c33c7471f1a7471d1a2085b1a35eba5cdc48d2ae319f28b6fc4de3 \ + --hash=sha256:70fc7fcf0410d16ebdda9b26cbd8bf8d803d220a7f3522e060a69a9c87bf7bad \ + --hash=sha256:794a4562dcb374f7dbbfb3f51d28fb40123b5a2abadee7b4091f93054909add5 \ + --hash=sha256:7ad1bc8d1b7a18497dda9600b12dc193c577beb391beae5cd2349184db40f187 \ + --hash=sha256:7f98f6dfa8b8ccaf39163ce872bddacca38f6a67289116c8937a02e30bbe9711 \ + --hash=sha256:8c997098cc65e3208eca09303630e84d42718620e83b733d0fd69543a9cab9cb \ + --hash=sha256:989d842dc06dc59feea09e58c74ca3e1678c812a4a8a2a419046d711031f69c7 \ + --hash=sha256:9dd8cd1aeb00775f527ec60022004d030ddc51d783d056e3e23e74e623e33726 \ + --hash=sha256:a4f96f0d88accc3dbe4a9025f785ba830f968e21e3e2c6321ccdfc9aef755115 \ + --hash=sha256:aee22939bb6075e7afededabad1a56a905da0b3c4e3e0c45e75810ebe3a52672 \ + --hash=sha256:bea2acdd8ea4275e1278350ced63da0b166421928276c7c8e3f9729d7402a57b \ + --hash=sha256:c3789bd5768ab5618ebf09cef6ec2b35fed88709b104351748a63045f0ff9797 \ + --hash=sha256:c92d73464b886931308ccc45b2744e5968cbaade0b1d6aeb40d8ab537765f5bc \ + --hash=sha256:ced65e5a985398827cc9276b93ef6dfabe0273c23de8c7931339d7e141c2818e \ + --hash=sha256:ded0fc7d90fe93ae0b18059930086c51e640cdd3baebdc783a695c77f123dcd9 \ + --hash=sha256:e3e0210287329272539eea617830a6a28161fbbd8a3271bf4150ae3e58c5d0e6 \ + --hash=sha256:ea7f69de383cb47522c9c208aec6dd17697db7875a4674c4af3f8cfdac0bdeae +referencing==0.35.1 \ + --hash=sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c \ + --hash=sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de +regex==2024.11.6 \ + --hash=sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0 \ + --hash=sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad \ + --hash=sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe \ + --hash=sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3 \ + --hash=sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4 \ + --hash=sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39 \ + --hash=sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7 \ + --hash=sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a \ + --hash=sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54 \ + --hash=sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c \ + --hash=sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d \ + --hash=sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4 \ + --hash=sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a \ + --hash=sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07 \ + --hash=sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff \ + --hash=sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e \ + --hash=sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519 \ + --hash=sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2 \ + --hash=sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e \ + --hash=sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84 \ + --hash=sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29 \ + --hash=sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b \ + --hash=sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3 \ + --hash=sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7 \ + --hash=sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4 \ + --hash=sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e \ + --hash=sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577 \ + --hash=sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0 \ + --hash=sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51 \ + --hash=sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6 \ + --hash=sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9 +requests==2.32.3 \ + --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \ + --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6 +requests-oauthlib==2.0.0 \ + --hash=sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36 \ + --hash=sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9 +rfc3339-validator==0.1.4 \ + --hash=sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b \ + --hash=sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa +rfc3986-validator==0.1.1 \ + --hash=sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9 \ + --hash=sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055 +rich==13.9.4 \ + --hash=sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098 \ + --hash=sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90 +rpds-py==0.22.3 \ + --hash=sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518 \ + --hash=sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059 \ + --hash=sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61 \ + --hash=sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5 \ + --hash=sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56 \ + --hash=sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd \ + --hash=sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b \ + --hash=sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4 \ + --hash=sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d \ + --hash=sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1 \ + --hash=sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e \ + --hash=sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc \ + --hash=sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38 \ + --hash=sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b \ + --hash=sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c \ + --hash=sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83 \ + --hash=sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1 \ + --hash=sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627 \ + --hash=sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16 \ + --hash=sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45 \ + --hash=sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730 \ + --hash=sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25 \ + --hash=sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7 \ + --hash=sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f \ + --hash=sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd \ + --hash=sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333 \ + --hash=sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9 \ + --hash=sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4 \ + --hash=sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d \ + --hash=sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15 \ + --hash=sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84 \ + --hash=sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e \ + --hash=sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf \ + --hash=sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b \ + --hash=sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2 \ + --hash=sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3 \ + --hash=sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130 \ + --hash=sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b \ + --hash=sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de \ + --hash=sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e +ruff==0.9.2 \ + --hash=sha256:1a605fdcf6e8b2d39f9436d343d1f0ff70c365a1e681546de0104bef81ce88df \ + --hash=sha256:3292c5a22ea9a5f9a185e2d131dc7f98f8534a32fb6d2ee7b9944569239c648d \ + --hash=sha256:492a5e44ad9b22a0ea98cf72e40305cbdaf27fac0d927f8bc9e1df316dcc96eb \ + --hash=sha256:71cbe22e178c5da20e1514e1e01029c73dc09288a8028a5d3446e6bba87a5145 \ + --hash=sha256:80605a039ba1454d002b32139e4970becf84b5fee3a3c3bf1c2af6f61a784347 \ + --hash=sha256:82b35259b0cbf8daa22a498018e300b9bb0174c2bbb7bcba593935158a78054d \ + --hash=sha256:8b6a9701d1e371bf41dca22015c3f89769da7576884d2add7317ec1ec8cb9c3c \ + --hash=sha256:8efd9da7a1ee314b910da155ca7e8953094a7c10d0c0a39bfde3fcfd2a015684 \ + --hash=sha256:9cc53e68b3c5ae41e8faf83a3b89f4a5d7b2cb666dff4b366bb86ed2a85b481f \ + --hash=sha256:a1b63fa24149918f8b37cef2ee6fff81f24f0d74b6f0bdc37bc3e1f2143e41c6 \ + --hash=sha256:af1e9e9fe7b1f767264d26b1075ac4ad831c7db976911fa362d09b2d0356426a \ + --hash=sha256:b338edc4610142355ccf6b87bd356729b62bf1bc152a2fad5b0c7dc04af77bfe \ + --hash=sha256:b5eceb334d55fae5f316f783437392642ae18e16dcf4f1858d55d3c2a0f8f5d0 \ + --hash=sha256:b9aab82bb20afd5f596527045c01e6ae25a718ff1784cb92947bff1f83068b00 \ + --hash=sha256:c547f7f256aa366834829a08375c297fa63386cbe5f1459efaf174086b564247 \ + --hash=sha256:c5e1d6abc798419cf46eed03f54f2e0c3adb1ad4b801119dedf23fcaf69b55b5 \ + --hash=sha256:d18bba3d3353ed916e882521bc3e0af403949dbada344c20c16ea78f47af965e \ + --hash=sha256:fbd337bac1cfa96be615f6efcd4bc4d077edbc127ef30e2b8ba2a27e18c054d4 +safetensors==0.5.2 \ + --hash=sha256:03c937100f38c9ff4c1507abea9928a6a9b02c9c1c9c3609ed4fb2bf413d4975 \ + --hash=sha256:1506e4c2eda1431099cebe9abf6c76853e95d0b7a95addceaa74c6019c65d8cf \ + --hash=sha256:3ab696dfdc060caffb61dbe4066b86419107a24c804a4e373ba59be699ebd8d5 \ + --hash=sha256:3dfa7c2f3fe55db34eba90c29df94bcdac4821043fc391cb5d082d9922013869 \ + --hash=sha256:45b6092997ceb8aa3801693781a71a99909ab9cc776fbc3fa9322d29b1d3bef2 \ + --hash=sha256:46ff2116150ae70a4e9c490d2ab6b6e1b1b93f25e520e540abe1b81b48560c3a \ + --hash=sha256:5c5b5d9da594f638a259fca766046f44c97244cc7ab8bef161b3e80d04becc76 \ + --hash=sha256:6d0d6a8ee2215a440e1296b843edf44fd377b055ba350eaba74655a2fe2c4bae \ + --hash=sha256:78abdddd03a406646107f973c7843276e7b64e5e32623529dc17f3d94a20f589 \ + --hash=sha256:86016d40bcaa3bcc9a56cd74d97e654b5f4f4abe42b038c71e4f00a089c4526c \ + --hash=sha256:990833f70a5f9c7d3fc82c94507f03179930ff7d00941c287f73b6fcbf67f19e \ + --hash=sha256:a00e737948791b94dad83cf0eafc09a02c4d8c2171a239e8c8572fe04e25960e \ + --hash=sha256:cb4a8d98ba12fa016f4241932b1fc5e702e5143f5374bba0bbcf7ddc1c4cf2b8 \ + --hash=sha256:d3a06fae62418ec8e5c635b61a8086032c9e281f16c63c3af46a6efbab33156f \ + --hash=sha256:fe55c039d97090d1f85277d402954dd6ad27f63034fa81985a9cc59655ac3ee2 +send2trash==1.8.3 \ + --hash=sha256:0c31227e0bd08961c7665474a3d1ef7193929fedda4233843689baa056be46c9 \ + --hash=sha256:b18e7a3966d99871aefeb00cfbcfdced55ce4871194810fc71f4aa484b953abf +setuptools==75.8.0 \ + --hash=sha256:c5afc8f407c626b8313a86e10311dd3f661c6cd9c09d4bf8c15c0e11f9f2b0e6 \ + --hash=sha256:e3982f444617239225d675215d51f6ba05f845d4eec313da4418fdbb56fb27e3 +shellingham==1.5.4 \ + --hash=sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686 \ + --hash=sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de +six==1.17.0 \ + --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ + --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81 +smart-open==7.1.0 \ + --hash=sha256:4b8489bb6058196258bafe901730c7db0dcf4f083f316e97269c66f45502055b \ + --hash=sha256:a4f09f84f0f6d3637c6543aca7b5487438877a21360e7368ccf1f704789752ba +sniffio==1.3.1 \ + --hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \ + --hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc +soupsieve==2.6 \ + --hash=sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb \ + --hash=sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9 +spacy==3.7.5 \ + --hash=sha256:07677e270a6d729453cc04b5e2247a96a86320b8845e6428d9f90f217eff0f56 \ + --hash=sha256:262f8ebb71f7ed5ffe8e4f384b2594b7a296be50241ce9fbd9277b5da2f46f38 \ + --hash=sha256:4145cea7f9814fa7d86b2028c2dd83e02f13f80d5ac604a400b2f7d7b26a0e8c \ + --hash=sha256:a648c6cbf2acc7a55a69ee9e7fa4f22bdf69aa828a587a1bc5cfff08cf3c2dd3 \ + --hash=sha256:bf54c3c2425428b328b53a65913d47eb4cb27a1429aa4e8ed979ffc97d4663e0 \ + --hash=sha256:faa1e2b6234ae33c0b1f8dfa5a8dcb66fb891f19231725dfcff4b2666125c250 +spacy-legacy==3.0.12 \ + --hash=sha256:476e3bd0d05f8c339ed60f40986c07387c0a71479245d6d0f4298dbd52cda55f \ + --hash=sha256:b37d6e0c9b6e1d7ca1cf5bc7152ab64a4c4671f59c85adaf7a3fcb870357a774 +spacy-loggers==1.0.5 \ + --hash=sha256:196284c9c446cc0cdb944005384270d775fdeaf4f494d8e269466cfa497ef645 \ + --hash=sha256:d60b0bdbf915a60e516cc2e653baeff946f0cfc461b452d11a4d5458c6fe5f24 +srsly==2.5.1 \ + --hash=sha256:00c2a3e4856e63b7efd47591d049aaee8e5a250e098917f50d93ea68853fab78 \ + --hash=sha256:184e3c98389aab68ff04aab9095bd5f1a8e5a72cc5edcba9d733bac928f5cf9f \ + --hash=sha256:366b4708933cd8d6025c13c2cea3331f079c7bb5c25ec76fca392b6fc09818a0 \ + --hash=sha256:459d987130e57e83ce9e160899afbeb871d975f811e6958158763dd9a8a20f23 \ + --hash=sha256:6118f9c4b221cde0a990d06a42c8a4845218d55b425d8550746fe790acf267e9 \ + --hash=sha256:683b54ed63d7dfee03bc2abc4b4a5f2152f81ec217bbadbac01ef1aaf2a75790 \ + --hash=sha256:6ac3944c112acb3347a39bfdc2ebfc9e2d4bace20fe1c0b764374ac5b83519f2 \ + --hash=sha256:6e57b8138082f09e35db60f99757e16652489e9e3692471d8e0c39aa95180688 \ + --hash=sha256:7481460110d9986781d9e4ac0f5f991f1d6839284a80ad268625f9a23f686950 \ + --hash=sha256:7952538f6bba91b9d8bf31a642ac9e8b9ccc0ccbb309feb88518bfb84bb0dc0d \ + --hash=sha256:84b372f7ef1604b4a5b3cee1571993931f845a5b58652ac01bcb32c52586d2a8 \ + --hash=sha256:ab1b4bf6cf3e29da23dae0493dd1517fb787075206512351421b89b4fc27c77e \ + --hash=sha256:bab90b85a63a1fe0bbc74d373c8bb9bb0499ddfa89075e0ebe8d670f12d04691 \ + --hash=sha256:c8a0b03c64eb6e150d772c5149befbadd981cc734ab13184b0561c17c8cef9b1 \ + --hash=sha256:e73712be1634b5e1de6f81c273a7d47fe091ad3c79dc779c03d3416a5c117cee +stack-data==0.6.3 \ + --hash=sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9 \ + --hash=sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695 +tenacity==9.0.0 \ + --hash=sha256:807f37ca97d62aa361264d497b0e31e92b8027044942bfa756160d908320d73b \ + --hash=sha256:93de0c98785b27fcf659856aa9f54bfbd399e29969b0621bc7f762bd441b4539 +terminado==0.18.1 \ + --hash=sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0 \ + --hash=sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e +thinc==8.2.5 \ + --hash=sha256:87e729f33c76ec6df9b375989743252ab880d79f3a2b4175169b21dece90f102 \ + --hash=sha256:8e299d4dc41107385d6d14d8604a060825798a031cabe2b894b22f9d75d9eaad \ + --hash=sha256:9fc26697e2358c71a5fe243d52e98ae67ee1a3b314eead5031845b6d1c0d121c \ + --hash=sha256:c2963791c934cc7fbd8f9b942d571cac79892ad11630bfca690a868c32752b75 \ + --hash=sha256:c5f750ea2dd32ca6d46947025dacfc0f6037340c4e5f7adb9af84c75f65aa7d8 \ + --hash=sha256:e8a8f2f249f2be9a5ce2a81a6efe7503b68be7b57e47ad54ab28204e1f0c723b +tiktoken==0.8.0 \ + --hash=sha256:02be1666096aff7da6cbd7cdaa8e7917bfed3467cd64b38b1f112e96d3b06a24 \ + --hash=sha256:18228d624807d66c87acd8f25fc135665617cab220671eb65b50f5d70fa51f69 \ + --hash=sha256:294440d21a2a51e12d4238e68a5972095534fe9878be57d905c476017bff99fc \ + --hash=sha256:4177faa809bd55f699e88c96d9bb4635d22e3f59d635ba6fd9ffedf7150b9953 \ + --hash=sha256:5376b6f8dc4753cd81ead935c5f518fa0fbe7e133d9e25f648d8c4dabdd4bad7 \ + --hash=sha256:6b231f5e8982c245ee3065cd84a4712d64692348bc609d84467c57b4b72dcbc5 \ + --hash=sha256:881839cfeae051b3628d9823b2e56b5cc93a9e2efb435f4cf15f17dc45f21586 \ + --hash=sha256:9a58deb7075d5b69237a3ff4bb51a726670419db6ea62bdcd8bd80c78497d7ab \ + --hash=sha256:9ccbb2740f24542534369c5635cfd9b2b3c2490754a78ac8831d99f89f94eeb2 \ + --hash=sha256:c94ff53c5c74b535b2cbf431d907fc13c678bbd009ee633a2aca269a04389f9a \ + --hash=sha256:d2908c0d043a7d03ebd80347266b0e58440bdef5564f84f4d29fb235b5df3b04 \ + --hash=sha256:d8f3192733ac4d77977432947d563d7e1b310b96497acd3c196c9bddb36ed9db \ + --hash=sha256:fe9399bdc3f29d428f16a2f86c3c8ec20be3eac5f53693ce4980371c3245729b +tinycss2==1.4.0 \ + --hash=sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7 \ + --hash=sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289 +tokenizers==0.21.0 \ + --hash=sha256:089d56db6782a73a27fd8abf3ba21779f5b85d4a9f35e3b493c7bbcbbf0d539b \ + --hash=sha256:3c4c93eae637e7d2aaae3d376f06085164e1660f89304c0ab2b1d08a406636b2 \ + --hash=sha256:400832c0904f77ce87c40f1a8a27493071282f785724ae62144324f171377273 \ + --hash=sha256:4145505a973116f91bc3ac45988a92e618a6f83eb458f49ea0790df94ee243ff \ + --hash=sha256:6b177fb54c4702ef611de0c069d9169f0004233890e0c4c5bd5508ae05abf193 \ + --hash=sha256:6b43779a269f4629bebb114e19c3fca0223296ae9fea8bb9a7a6c6fb0657ff8e \ + --hash=sha256:87841da5a25a3a5f70c102de371db120f41873b854ba65e52bccd57df5a3780c \ + --hash=sha256:9aeb255802be90acfd363626753fda0064a8df06031012fe7d52fd9a905eb00e \ + --hash=sha256:c87ca3dc48b9b1222d984b6b7490355a6fdb411a2d810f6f05977258400ddb74 \ + --hash=sha256:d8b09dbeb7a8d73ee204a70f94fc06ea0f17dcf0844f16102b9f414f0b7463ba \ + --hash=sha256:e84ca973b3a96894d1707e189c14a774b701596d579ffc7e69debfc036a61a04 \ + --hash=sha256:eb1702c2f27d25d9dd5b389cc1f2f51813e99f8ca30d9e25348db6585a97e24a \ + --hash=sha256:eb7202d231b273c34ec67767378cd04c767e967fda12d4a9e36208a34e2f137e \ + --hash=sha256:ee0894bf311b75b0c03079f33859ae4b2334d675d4e93f5a4132e1eae2834fe4 \ + --hash=sha256:f53ea537c925422a2e0e92a24cce96f6bc5046bbef24a1652a5edc8ba975f62e +tornado==6.4.2 \ + --hash=sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803 \ + --hash=sha256:1a017d239bd1bb0919f72af256a970624241f070496635784d9bf0db640d3fec \ + --hash=sha256:2876cef82e6c5978fde1e0d5b1f919d756968d5b4282418f3146b79b58556482 \ + --hash=sha256:304463bd0772442ff4d0f5149c6f1c2135a1fae045adf070821c6cdc76980634 \ + --hash=sha256:908b71bf3ff37d81073356a5fadcc660eb10c1476ee6e2725588626ce7e5ca38 \ + --hash=sha256:92bad5b4746e9879fd7bf1eb21dce4e3fc5128d71601f80005afa39237ad620b \ + --hash=sha256:932d195ca9015956fa502c6b56af9eb06106140d844a335590c1ec7f5277d10c \ + --hash=sha256:bca9eb02196e789c9cb5c3c7c0f04fb447dc2adffd95265b2c7223a8a615ccbf \ + --hash=sha256:c36e62ce8f63409301537222faffcef7dfc5284f27eec227389f2ad11b09d946 \ + --hash=sha256:c82c46813ba483a385ab2a99caeaedf92585a1f90defb5693351fa7e4ea0bf73 \ + --hash=sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1 +tqdm==4.67.1 \ + --hash=sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2 \ + --hash=sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2 +traitlets==5.14.3 \ + --hash=sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7 \ + --hash=sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f +typer==0.15.1 \ + --hash=sha256:7994fb7b8155b64d3402518560648446072864beefd44aa2dc36972a5972e847 \ + --hash=sha256:a0588c0a7fa68a1978a069818657778f86abe6ff5ea6abf472f940a08bfe4f0a +types-python-dateutil==2.9.0.20241206 \ + --hash=sha256:18f493414c26ffba692a72369fea7a154c502646301ebfe3d56a04b3767284cb \ + --hash=sha256:e248a4bc70a486d3e3ec84d0dc30eec3a5f979d6e7ee4123ae043eedbb987f53 +typing-extensions==4.12.2 \ + --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ + --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 +tzdata==2025.1 \ + --hash=sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694 \ + --hash=sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639 +uri-template==1.3.0 \ + --hash=sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7 \ + --hash=sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363 +urllib3==2.3.0 \ + --hash=sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df \ + --hash=sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d +virtualenv==20.29.1 \ + --hash=sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779 \ + --hash=sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35 +wasabi==1.1.3 \ + --hash=sha256:4bb3008f003809db0c3e28b4daf20906ea871a2bb43f9914197d540f4f2e0878 \ + --hash=sha256:f76e16e8f7e79f8c4c8be49b4024ac725713ab10cd7f19350ad18a8e3f71728c +wcwidth==0.2.13 \ + --hash=sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859 \ + --hash=sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5 +weasel==0.4.1 \ + --hash=sha256:24140a090ea1ac512a2b2f479cc64192fd1d527a7f3627671268d08ed5ac418c \ + --hash=sha256:aabc210f072e13f6744e5c3a28037f93702433405cd35673f7c6279147085aa9 +webcolors==24.11.1 \ + --hash=sha256:515291393b4cdf0eb19c155749a096f779f7d909f7cceea072791cb9095b92e9 \ + --hash=sha256:ecb3d768f32202af770477b8b65f318fa4f566c22948673a977b00d589dd80f6 +webencodings==0.5.1 \ + --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ + --hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923 +websocket-client==1.8.0 \ + --hash=sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526 \ + --hash=sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da +widgetsnbextension==4.0.13 \ + --hash=sha256:74b2692e8500525cc38c2b877236ba51d34541e6385eeed5aec15a70f88a6c71 \ + --hash=sha256:ffcb67bc9febd10234a362795f643927f4e0c05d9342c727b65d2384f8feacb6 +wrapt==1.17.2 \ + --hash=sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555 \ + --hash=sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b \ + --hash=sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998 \ + --hash=sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392 \ + --hash=sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306 \ + --hash=sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3 \ + --hash=sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9 \ + --hash=sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6 \ + --hash=sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192 \ + --hash=sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f \ + --hash=sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d \ + --hash=sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8 \ + --hash=sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845 \ + --hash=sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82 \ + --hash=sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125 \ + --hash=sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504 \ + --hash=sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b \ + --hash=sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc \ + --hash=sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6 \ + --hash=sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40 \ + --hash=sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681 \ + --hash=sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae \ + --hash=sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2 \ + --hash=sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb \ + --hash=sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5 \ + --hash=sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a \ + --hash=sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8 \ + --hash=sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98 \ + --hash=sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b \ + --hash=sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925 \ + --hash=sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6 \ + --hash=sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0 \ + --hash=sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9 \ + --hash=sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c \ + --hash=sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991 +yarl==1.18.3 \ + --hash=sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba \ + --hash=sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186 \ + --hash=sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50 \ + --hash=sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640 \ + --hash=sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8 \ + --hash=sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58 \ + --hash=sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2 \ + --hash=sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393 \ + --hash=sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c \ + --hash=sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272 \ + --hash=sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d \ + --hash=sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576 \ + --hash=sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477 \ + --hash=sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2 \ + --hash=sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512 \ + --hash=sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a \ + --hash=sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0 \ + --hash=sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8 \ + --hash=sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb \ + --hash=sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa \ + --hash=sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1 \ + --hash=sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10 \ + --hash=sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b \ + --hash=sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e \ + --hash=sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb \ + --hash=sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6 \ + --hash=sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285 \ + --hash=sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb \ + --hash=sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482 \ + --hash=sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75 \ + --hash=sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782 \ + --hash=sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53 \ + --hash=sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2 \ + --hash=sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1 From 84f9572319ef7abaa29421eb0d6f57b03176aa40 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Tue, 21 Jan 2025 21:11:39 +0000 Subject: [PATCH 26/64] Update readme and model --- README.md | 2 +- .../.env.example | 7 +-- .../README.md | 0 .../pyproject.toml | 0 .../deploy_ai_search_indexes}/ai_search.py | 0 .../src/deploy_ai_search_indexes}/deploy.py | 0 .../deploy_ai_search_indexes}/environment.py | 52 ++----------------- .../image_processing.py | 0 .../text_2_sql_column_value_store.py | 0 .../text_2_sql_query_cache.py | 0 .../text_2_sql_schema_store.py | 0 image_processing/.env.example | 7 ++- image_processing/GETTING_STARTED.md | 2 +- image_processing/README.md | 2 +- pyproject.toml | 2 +- text_2_sql/GETTING_STARTED.md | 6 +-- text_2_sql/data_dictionary/README.md | 2 +- 17 files changed, 18 insertions(+), 64 deletions(-) rename {deploy_ai_search => deploy_ai_search_indexes}/.env.example (81%) rename {deploy_ai_search => deploy_ai_search_indexes}/README.md (100%) rename {deploy_ai_search => deploy_ai_search_indexes}/pyproject.toml (100%) rename {deploy_ai_search/src/deploy_ai_search => deploy_ai_search_indexes/src/deploy_ai_search_indexes}/ai_search.py (100%) rename {deploy_ai_search/src/deploy_ai_search => deploy_ai_search_indexes/src/deploy_ai_search_indexes}/deploy.py (100%) rename {deploy_ai_search/src/deploy_ai_search => deploy_ai_search_indexes/src/deploy_ai_search_indexes}/environment.py (77%) rename {deploy_ai_search/src/deploy_ai_search => deploy_ai_search_indexes/src/deploy_ai_search_indexes}/image_processing.py (100%) rename {deploy_ai_search/src/deploy_ai_search => deploy_ai_search_indexes/src/deploy_ai_search_indexes}/text_2_sql_column_value_store.py (100%) rename {deploy_ai_search/src/deploy_ai_search => deploy_ai_search_indexes/src/deploy_ai_search_indexes}/text_2_sql_query_cache.py (100%) rename {deploy_ai_search/src/deploy_ai_search => deploy_ai_search_indexes/src/deploy_ai_search_indexes}/text_2_sql_schema_store.py (100%) diff --git a/README.md b/README.md index f872d60b..c9f19a98 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ It is intended that the plugins and skills provided in this repository, are adap - `./text_2_sql` contains an three Multi-Shot implementations for Text2SQL generation and querying which can be used to answer questions backed by a database as a knowledge base. A **prompt based** and **vector based** approach are shown, both of which exhibit great performance in answering sql queries. Additionally, a further iteration on the vector based approach is shown which uses a **query cache** to further speed up generation. With these plugins, your RAG application can now access and pull data from any SQL table exposed to it to answer questions. - `./image_processing` contains code for linking **Azure Document Intelligence** with AI Search to process complex documents with charts and images, and uses **multi-modal models (gpt4o)** to interpret and understand these. With this custom skill, the RAG application can **draw insights from complex charts** and images during the vector search. This function app also contains a **Semantic Text Chunking** method that aims to intelligently group similar sentences, retaining figures and tables together, whilst separating out distinct sentences. -- `./deploy_ai_search` provides an easy Python based utility for deploying an index, indexer and corresponding skillset for AI Search and for Text2SQL. +- `./deploy_ai_search_indexes` provides an easy Python based utility for deploying an index, indexer and corresponding skillset for AI Search and for Text2SQL. The above components have been successfully used on production RAG projects to increase the quality of responses. diff --git a/deploy_ai_search/.env.example b/deploy_ai_search_indexes/.env.example similarity index 81% rename from deploy_ai_search/.env.example rename to deploy_ai_search_indexes/.env.example index 0cad1743..2da48207 100644 --- a/deploy_ai_search/.env.example +++ b/deploy_ai_search_indexes/.env.example @@ -1,11 +1,6 @@ - +# Environment variables for the deploying AI Search Indexes FunctionApp__Endpoint= FunctionApp__Key= -FunctionApp__LayoutAnalysis__FunctionName=layout_analysis -FunctionApp__FigureAnalysis__FunctionName=figure_analysis -FunctionApp__LayoutAndFigureMerger__FunctionName=layout_and_figure_merger -FunctionApp__MarkUpCleaner__FunctionName=mark_up_cleaner -FunctionApp__SemanticTextChunker__FunctionName=semantic_text_chunker FunctionApp__AppRegistrationResourceId= IdentityType=key # system_assigned or user_assigned or key AIService__AzureSearchOptions__Endpoint= diff --git a/deploy_ai_search/README.md b/deploy_ai_search_indexes/README.md similarity index 100% rename from deploy_ai_search/README.md rename to deploy_ai_search_indexes/README.md diff --git a/deploy_ai_search/pyproject.toml b/deploy_ai_search_indexes/pyproject.toml similarity index 100% rename from deploy_ai_search/pyproject.toml rename to deploy_ai_search_indexes/pyproject.toml diff --git a/deploy_ai_search/src/deploy_ai_search/ai_search.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/ai_search.py similarity index 100% rename from deploy_ai_search/src/deploy_ai_search/ai_search.py rename to deploy_ai_search_indexes/src/deploy_ai_search_indexes/ai_search.py diff --git a/deploy_ai_search/src/deploy_ai_search/deploy.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/deploy.py similarity index 100% rename from deploy_ai_search/src/deploy_ai_search/deploy.py rename to deploy_ai_search_indexes/src/deploy_ai_search_indexes/deploy.py diff --git a/deploy_ai_search/src/deploy_ai_search/environment.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/environment.py similarity index 77% rename from deploy_ai_search/src/deploy_ai_search/environment.py rename to deploy_ai_search_indexes/src/deploy_ai_search_indexes/environment.py index a99f5907..0fc1f332 100644 --- a/deploy_ai_search/src/deploy_ai_search/environment.py +++ b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/environment.py @@ -205,41 +205,6 @@ def function_app_app_registration_resource_id(self) -> str: """ return os.environ.get("FunctionApp__AppRegistrationResourceId") - @property - def function_app_mark_up_cleaner_route(self) -> str: - """ - This function returns function app data cleanup function name - """ - return os.environ.get("FunctionApp__MarkUpCleaner__FunctionName") - - @property - def function_app_semantic_text_chunker_route(self) -> str: - """ - This function returns function app semantic text chunker name - """ - return os.environ.get("FunctionApp__SemanticTextChunker__FunctionName") - - @property - def function_app_layout_analysis_route(self) -> str: - """ - This function returns function app adi name - """ - return os.environ.get("FunctionApp__LayoutAnalysis__FunctionName") - - @property - def function_app_figure_analysis_route(self) -> str: - """ - This function returns function app figure analysis name - """ - return os.environ.get("FunctionApp__FigureAnalysis__FunctionName") - - @property - def function_app_layout_and_figure_merger_route(self) -> str: - """ - This function returns function app layout and figure merger name - """ - return os.environ.get("FunctionApp__LayoutAndFigureMerger__FunctionName") - @property def open_ai_embedding_dimensions(self) -> str: """ @@ -257,7 +222,8 @@ def use_private_endpoint(self) -> bool: This function returns true if private endpoint is used """ return ( - os.environ.get("AIService__AzureSearchOptions__UsePrivateEndpoint").lower() + os.environ.get( + "AIService__AzureSearchOptions__UsePrivateEndpoint").lower() == "true" ) @@ -265,21 +231,9 @@ def get_custom_skill_function_url(self, skill_type: str): """ Get the function app url that is hosting the custom skill """ - if skill_type == "mark_up_cleaner": - route = self.function_app_mark_up_cleaner_route - elif skill_type == "layout_analysis": - route = self.function_app_layout_analysis_route - elif skill_type == "figure_analysis": - route = self.function_app_figure_analysis - elif skill_type == "layout_and_figure_merger": - route = self.function_app_layout_and_figure_merger - elif skill_type == "semantic_text_chunker": - route = self.function_app_semantic_text_chunker_route - else: - raise ValueError(f"Invalid skill type: {skill_type}") full_url = ( - f"{self.function_app_end_point}/api/{route}?code={self.function_app_key}" + f"{self.function_app_end_point}/api/{skill_type}?code={self.function_app_key}" ) return full_url diff --git a/deploy_ai_search/src/deploy_ai_search/image_processing.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py similarity index 100% rename from deploy_ai_search/src/deploy_ai_search/image_processing.py rename to deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py diff --git a/deploy_ai_search/src/deploy_ai_search/text_2_sql_column_value_store.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/text_2_sql_column_value_store.py similarity index 100% rename from deploy_ai_search/src/deploy_ai_search/text_2_sql_column_value_store.py rename to deploy_ai_search_indexes/src/deploy_ai_search_indexes/text_2_sql_column_value_store.py diff --git a/deploy_ai_search/src/deploy_ai_search/text_2_sql_query_cache.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/text_2_sql_query_cache.py similarity index 100% rename from deploy_ai_search/src/deploy_ai_search/text_2_sql_query_cache.py rename to deploy_ai_search_indexes/src/deploy_ai_search_indexes/text_2_sql_query_cache.py diff --git a/deploy_ai_search/src/deploy_ai_search/text_2_sql_schema_store.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/text_2_sql_schema_store.py similarity index 100% rename from deploy_ai_search/src/deploy_ai_search/text_2_sql_schema_store.py rename to deploy_ai_search_indexes/src/deploy_ai_search_indexes/text_2_sql_schema_store.py diff --git a/image_processing/.env.example b/image_processing/.env.example index a51185d3..e7f68d38 100644 --- a/image_processing/.env.example +++ b/image_processing/.env.example @@ -1,5 +1,10 @@ +# Environment variables for Image Processing Function Apps OpenAI__Endpoint= OpenAI__MiniCompletionDeployment= OpenAI__ApiVersion= + +# Azure AI Services Connection Details AIService__DocumentIntelligence__Endpoint= -StorageAccount__Name= + +# Azure Storage Account Connection Details +StorageAccount__Name= diff --git a/image_processing/GETTING_STARTED.md b/image_processing/GETTING_STARTED.md index 1b818637..a9d45483 100644 --- a/image_processing/GETTING_STARTED.md +++ b/image_processing/GETTING_STARTED.md @@ -3,7 +3,7 @@ To get started, perform the following steps: 1. Setup Azure OpenAI in your subscription with **gpt-4o-mini** & an embedding model, an Python Function App, AI Search and a storage account. -2. Clone this repository and deploy the AI Search rag documents indexes from `deploy_ai_search`. +2. Clone this repository and deploy the AI Search rag documents indexes from `deploy_ai_search_indexes`. 3. Run `uv sync` within the image_processing directory to install dependencies (or used the synced `requirements.txt`) 4. Use the `.env.example` to add the required environmental variables to your function app. Not all values are required dependent on whether you are using System / User Assigned Identities or a Key based authentication. Use this template to update the environment variables in the function app. 5. [Package your Azure Function and upload to your Function App.](https://learn.microsoft.com/en-us/azure/azure-functions/functions-deployment-technologies?tabs=windows) and test with a HTTP request. diff --git a/image_processing/README.md b/image_processing/README.md index 9ce082cd..10664828 100644 --- a/image_processing/README.md +++ b/image_processing/README.md @@ -62,7 +62,7 @@ The Figure 4 content has been interpreted and added into the extracted chunk to ## Deploying AI Search Setup -To deploy the pre-built index and associated indexer / skillset setup, see instructions in `./deploy_ai_search/README.md`. +To deploy the pre-built index and associated indexer / skillset setup, see instructions in `./deploy_ai_search_indexes/README.md`. ## Custom Skills diff --git a/pyproject.toml b/pyproject.toml index b79fff70..97aabc6d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,7 @@ dev = [ ] [tool.uv.workspace] -members = ["text_2_sql/text_2_sql_core", "text_2_sql/autogen", "deploy_ai_search", "image_processing", "text_2_sql/semantic_kernel"] +members = ["text_2_sql/text_2_sql_core", "text_2_sql/autogen", "deploy_ai_search_indexes", "image_processing", "text_2_sql/semantic_kernel"] [tool.uv.sources] text-2-sql-core = { workspace = true } diff --git a/text_2_sql/GETTING_STARTED.md b/text_2_sql/GETTING_STARTED.md index 43382382..d6916406 100644 --- a/text_2_sql/GETTING_STARTED.md +++ b/text_2_sql/GETTING_STARTED.md @@ -2,11 +2,11 @@ To get started, perform the following steps: -**Execute the following commands in the `deploy_ai_search` directory:** +**Execute the following commands in the `deploy_ai_search_indexes` directory:** 1. Setup Azure OpenAI in your subscription with **gpt-4o-mini** & an embedding model, alongside a SQL Server sample database, AI Search and a storage account. -2. Create your `.env` file based on the provided sample `deploy_ai_search/.env.example`. Place this file in the same place in `deploy_ai_search/.env`. -3. Clone this repository and deploy the AI Search text2sql indexes from `deploy_ai_search`. See the instructions in the **Steps for Text2SQL Index Deployment (For Structured RAG)** section of the `deploy_ai_search/README.md`. +2. Create your `.env` file based on the provided sample `deploy_ai_search_indexes/.env.example`. Place this file in the same place in `deploy_ai_search_indexes/.env`. +3. Clone this repository and deploy the AI Search text2sql indexes from `deploy_ai_search_indexes`. See the instructions in the **Steps for Text2SQL Index Deployment (For Structured RAG)** section of the `deploy_ai_search_indexes/README.md`. **Execute the following commands in the `text_2_sql_core` directory:** diff --git a/text_2_sql/data_dictionary/README.md b/text_2_sql/data_dictionary/README.md index d2002aeb..9660bd74 100644 --- a/text_2_sql/data_dictionary/README.md +++ b/text_2_sql/data_dictionary/README.md @@ -203,7 +203,7 @@ This avoids having to index the fact tables, saving storage, and allows us to st ## Indexing -`./deploy_ai_search/text_2_sql.py` & `./deploy_ai_search/text_2_sql_query_cache.py` contains the scripts to deploy and index the data dictionary for use within the plugin. See instructions in `./deploy_ai_search/README.md`. There is **no automatic mechanism** to upload these .json files currently to a storage account, once generated, you must automatically upload them to the appropriate storage account that the indexer is connected to. +`./deploy_ai_search_indexes/text_2_sql.py` & `./deploy_ai_search_indexes/text_2_sql_query_cache.py` contains the scripts to deploy and index the data dictionary for use within the plugin. See instructions in `./deploy_ai_search_indexes/README.md`. There is **no automatic mechanism** to upload these .json files currently to a storage account, once generated, you must automatically upload them to the appropriate storage account that the indexer is connected to. ## Automatic Generation From 967ccfb9ff97158db78a355635edb7129ba3bb59 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Tue, 21 Jan 2025 21:15:29 +0000 Subject: [PATCH 27/64] Update example --- deploy_ai_search_indexes/.env.example | 26 ++++++++++++++++++-------- uv.lock | 2 +- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/deploy_ai_search_indexes/.env.example b/deploy_ai_search_indexes/.env.example index 2da48207..a656e85b 100644 --- a/deploy_ai_search_indexes/.env.example +++ b/deploy_ai_search_indexes/.env.example @@ -1,22 +1,32 @@ # Environment variables for the deploying AI Search Indexes +IdentityType= # system_assigned or user_assigned or key FunctionApp__Endpoint= FunctionApp__Key= FunctionApp__AppRegistrationResourceId= -IdentityType=key # system_assigned or user_assigned or key + +# Open AI Connection Details +OpenAI__ApiKey= +OpenAI__Endpoint= +OpenAI__EmbeddingModel="text-embedding-ada-002" +OpenAI__EmbeddingDeployment="text-embedding-ada-002" +OpenAI__EmbeddingDimensions=1536 + +# Azure AI Search Connection Details AIService__AzureSearchOptions__Endpoint= AIService__AzureSearchOptions__Identity__ClientId= -AIService__AzureSearchOptions__Key= +AIService__AzureSearchOptions__Key= AIService__AzureSearchOptions__UsePrivateEndpoint=false AIService__AzureSearchOptions__Identity__FQName= + +# Azure Storage Account Connection Details StorageAccount__FQEndpoint= StorageAccount__ConnectionString= -OpenAI__ApiKey= -OpenAI__Endpoint= -OpenAI__EmbeddingModel="text-embedding-ada-002" -OpenAI__EmbeddingDeployment="text-embedding-ada-002" -OpenAI__EmbeddingDimensions=1536 + +# Image Processing Index Specific Configurations +StorageAccount__ImageProcessing__Container= + +# Text2Sql Index Specific Configurations Text2Sql__DatabaseEngine= -StorageAccount__RagDocuments__Container= StorageAccount__Text2SqlQueryCache__Container= StorageAccount__Text2SqlSchemaStore__Container= StorageAccount__Text2SqlColumnValueStore__Container= diff --git a/uv.lock b/uv.lock index c3c1c22f..c4f06c86 100644 --- a/uv.lock +++ b/uv.lock @@ -882,7 +882,7 @@ wheels = [ [[package]] name = "deploy-ai-search" version = "0.1.0" -source = { virtual = "deploy_ai_search" } +source = { virtual = "deploy_ai_search_indexes" } dependencies = [ { name = "azure-identity" }, { name = "azure-mgmt-web" }, From 37f3a6b48cadfcab136b0614bc0de7f8ba61390a Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 18:13:32 +0000 Subject: [PATCH 28/64] Update mappings --- .../src/deploy_ai_search_indexes/ai_search.py | 106 +++++++++++++----- .../image_processing.py | 101 +++++++++++------ 2 files changed, 144 insertions(+), 63 deletions(-) diff --git a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/ai_search.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/ai_search.py index bec31bb3..8ad90b68 100644 --- a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/ai_search.py +++ b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/ai_search.py @@ -196,7 +196,7 @@ def get_data_source(self) -> SearchIndexerDataSourceConnection: return data_source_connection - def get_mark_up_cleaner_skill(self, context, source) -> WebApiSkill: + def get_mark_up_cleaner_skill(self, chunk_by_page: False) -> WebApiSkill: """Get the custom skill for data cleanup. Args: @@ -215,29 +215,47 @@ def get_mark_up_cleaner_skill(self, context, source) -> WebApiSkill: batch_size = 16 degree_of_parallelism = 16 - mark_up_cleaner_skill_inputs = [ - InputFieldMappingEntry(name="chunk", source=source), - InputFieldMappingEntry( - name="figure_storage_prefix", source="/document/metadata_storage_path" - ), - ] + if chunk_by_page: + mark_up_cleaner_context = "/document/page_wise_layout/*" + inputs = [ + InputFieldMappingEntry( + name="chunk", source="/document/page_wise_layout/*/merged_content" + ), + InputFieldMappingEntry( + name="figures", + source="/document/page_wise_layout/*/figures/*/updated_figure", + ), + ] + else: + mark_up_cleaner_context = "/document/chunk_mark_ups/*" + inputs = [ + InputFieldMappingEntry( + name="chunk", source="/document/chunk_mark_ups/*" + ), + InputFieldMappingEntry( + name="figures", source="/document/layout/figures/*/updated_figure" + ), + ] mark_up_cleaner_skill_outputs = [ - OutputFieldMappingEntry(name="cleaned_chunk", target_name="cleaned_chunk"), - OutputFieldMappingEntry(name="chunk", target_name="chunk"), - OutputFieldMappingEntry(name="sections", target_name="sections"), + OutputFieldMappingEntry(name="chunk_cleaned", target_name="chunk_cleaned"), + OutputFieldMappingEntry( + name="chunk_sections", target_name="chunk_sections" + ), + OutputFieldMappingEntry(name="chunk_mark_up", target_name="chunk_mark_up"), + OutputFieldMappingEntry(name="chunk_figures", target_name="chunk_figures"), ] mark_up_cleaner_skill = WebApiSkill( name="Mark Up Cleaner Skill", description="Skill to clean the data before sending to embedding", - context=context, + context=mark_up_cleaner_context, uri=self.environment.get_custom_skill_function_url("mark_up_cleaner"), timeout="PT230S", batch_size=batch_size, degree_of_parallelism=degree_of_parallelism, http_method="POST", - inputs=mark_up_cleaner_skill_inputs, + inputs=inputs, outputs=mark_up_cleaner_skill_outputs, ) @@ -255,8 +273,6 @@ def get_mark_up_cleaner_skill(self, context, source) -> WebApiSkill: def get_semantic_chunker_skill( self, - context, - source, num_surrounding_sentences: int = 1, similarity_threshold: float = 0.8, max_chunk_tokens: int = 200, @@ -284,17 +300,17 @@ def get_semantic_chunker_skill( degree_of_parallelism = 16 semantic_text_chunker_skill_inputs = [ - InputFieldMappingEntry(name="content", source=source) + InputFieldMappingEntry(name="content", source="/document/merged_content") ] semantic_text_chunker_skill_outputs = [ - OutputFieldMappingEntry(name="chunks", target_name="chunks"), + OutputFieldMappingEntry(name="chunks", target_name="chunk_mark_ups"), ] semantic_text_chunker_skill = WebApiSkill( name="Semantic Chunker Skill", description="Skill to clean the data before sending to embedding", - context=context, + context="/document", uri=self.environment.get_custom_skill_function_url("semantic_text_chunker"), timeout="PT230S", batch_size=batch_size, @@ -345,7 +361,9 @@ def get_layout_analysis_skill( if chunk_by_page: output = [ - OutputFieldMappingEntry(name="layout", target_name="page_wise_layout") + OutputFieldMappingEntry( + name="page_wise_layout", target_name="page_wise_layout" + ) ] else: output = [OutputFieldMappingEntry(name="layout", target_name="layout")] @@ -383,7 +401,7 @@ def get_layout_analysis_skill( return layout_analysis_skill - def get_figure_analysis_skill(self, figure_source) -> WebApiSkill: + def get_figure_analysis_skill(self, chunk_by_page=False) -> WebApiSkill: """Get the custom skill for figure analysis. Args: @@ -406,16 +424,32 @@ def get_figure_analysis_skill(self, figure_source) -> WebApiSkill: OutputFieldMappingEntry(name="updated_figure", target_name="updated_figure") ] + if chunk_by_page: + figure_context = "/document/page_wise_layout/*" + inputs = [ + InputFieldMappingEntry( + name="figure", source="/document/page_wise_layout/*/figures/*" + ) + ] + else: + figure_context = "/document/layout/figures/*" + + inputs = [ + InputFieldMappingEntry( + name="figure", source="/document/layout/figures/*" + ) + ] + figure_analysis_skill = WebApiSkill( name="Figure Analysis Skill", description="Skill to generate figure analysis", - context=figure_source, + context=figure_context, uri=self.environment.get_custom_skill_function_url("figure_analysis"), timeout="PT230S", batch_size=batch_size, degree_of_parallelism=degree_of_parallelism, http_method="POST", - inputs=[InputFieldMappingEntry(name="figure", source=figure_source)], + inputs=inputs, outputs=output, ) @@ -431,7 +465,7 @@ def get_figure_analysis_skill(self, figure_source) -> WebApiSkill: return figure_analysis_skill - def get_layout_and_figure_merger_skill(self, figure_source) -> WebApiSkill: + def get_layout_and_figure_merger_skill(self, chunk_by_page=False) -> WebApiSkill: """Get the custom skill for layout and figure merger. Args: @@ -450,14 +484,32 @@ def get_layout_and_figure_merger_skill(self, figure_source) -> WebApiSkill: batch_size = 1 degree_of_parallelism = 8 - output = [ - OutputFieldMappingEntry(name="updated_figure", target_name="updated_figure") - ] + output = [OutputFieldMappingEntry(name="content", target_name="merged_content")] + if chunk_by_page: + merger_context = "/document/page_wise_layout/*" + inputs = [ + InputFieldMappingEntry( + name="layout", source="/document/page_wise_layout/*" + ), + InputFieldMappingEntry( + name="figures", + source="/document/page_wise_layout/*/figures/*/updated_figure", + ), + ] + else: + merger_context = "/document/layout" + + inputs = [ + InputFieldMappingEntry(name="layout", source="/document/layout"), + InputFieldMappingEntry( + name="figures", source="/document/layout/figures/*/updated_figure" + ), + ] figure_analysis_skill = WebApiSkill( name="Layout and Figure Merger Skill", description="Skill to merge layout and figure analysis", - context=figure_source, + context=merger_context, uri=self.environment.get_custom_skill_function_url( "layout_and_figure_merger" ), @@ -465,7 +517,7 @@ def get_layout_and_figure_merger_skill(self, figure_source) -> WebApiSkill: batch_size=batch_size, degree_of_parallelism=degree_of_parallelism, http_method="POST", - inputs=[InputFieldMappingEntry(name="figure", source=figure_source)], + inputs=inputs, outputs=output, ) diff --git a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py index e2abed2c..9e8fe753 100644 --- a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py +++ b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py @@ -181,21 +181,27 @@ def get_skills(self) -> list: layout_skill = self.get_layout_analysis_skill(self.enable_page_by_chunking) - figure_skill = self.get_figure_analysis_skill() + figure_skill = self.get_figure_analysis_skill(self.enable_page_by_chunking) - merger_skill = self.get_layout_and_figure_merger_skill() - - text_split_skill = self.get_semantic_chunker_skill( - "/document", "/document/extracted_content/content" + merger_skill = self.get_layout_and_figure_merger_skill( + self.enable_page_by_chunking ) + text_split_skill = self.get_semantic_chunker_skill(self.enable_page_by_chunking) + mark_up_cleaner_skill = self.get_mark_up_cleaner_skill( - "/document/chunks/*", "/document/chunks/*/content" + self.enable_page_by_chunking ) - embedding_skill = self.get_vector_skill( - "/document/chunks/*", "/document/chunks/*/cleaned_chunk" - ) + if self.enable_page_by_chunking: + embedding_skill = self.get_vector_skill( + "/document/page_wise_layout/*", + "/document/page_wise_layout/*/chunk_cleaned", + ) + else: + embedding_skill = self.get_vector_skill( + "/document/chunk_mark_ups/*", "/document/chunk_mark_ups/*/chunk_cleaned" + ) if self.enable_page_by_chunking: skills = [ @@ -219,41 +225,64 @@ def get_skills(self) -> list: def get_index_projections(self) -> SearchIndexerIndexProjection: """This function returns the index projections for rag document.""" - mappings = [ - InputFieldMappingEntry(name="Chunk", source="/document/chunks/*/chunk"), - InputFieldMappingEntry( - name="ChunkEmbedding", - source="/document/chunks/*/vector", - ), - InputFieldMappingEntry(name="Title", source="/document/Title"), - InputFieldMappingEntry(name="SourceUri", source="/document/SourceUri"), - InputFieldMappingEntry( - name="Sections", source="/document/chunks/*/sections" - ), - InputFieldMappingEntry( - name="Figures", - source_context="/document/chunks/*/chunk_figures/*", - ), - InputFieldMappingEntry( - name="DateLastModified", source="/document/DateLastModified" - ), - ] if self.enable_page_by_chunking: - mappings.extend( - [ - InputFieldMappingEntry( - name="PageNumber", source="/document/chunks/*/pageNumber" - ) - ] - ) + source_context = "/document/page_wise_layout/*" + mappings = [ + InputFieldMappingEntry( + name="Chunk", source="/document/page_wise_layout/*/chunk_mark_up" + ), + InputFieldMappingEntry( + name="ChunkEmbedding", + source="/document/page_wise_layout/*/vector", + ), + InputFieldMappingEntry(name="Title", source="/document/Title"), + InputFieldMappingEntry(name="SourceUri", source="/document/SourceUri"), + InputFieldMappingEntry( + name="Sections", + source="/document/page_wise_layout/*/chunk_sections", + ), + InputFieldMappingEntry( + name="Figures", + source_context="/document/page_wise_layout/*/chunk_figures/*", + ), + InputFieldMappingEntry( + name="DateLastModified", source="/document/DateLastModified" + ), + InputFieldMappingEntry( + name="PageNumber", source="/document/page_wise_layout/*/#" + ), + ] + else: + source_context = "/document/chunks/*" + mappings = [ + InputFieldMappingEntry( + name="Chunk", source="/document/chunk_mark_ups/*/chunk_mark_up" + ), + InputFieldMappingEntry( + name="ChunkEmbedding", + source="/document/chunk_mark_ups/*/vector", + ), + InputFieldMappingEntry(name="Title", source="/document/Title"), + InputFieldMappingEntry(name="SourceUri", source="/document/SourceUri"), + InputFieldMappingEntry( + name="Sections", source="/document/chunk_mark_ups/*/chunk_sections" + ), + InputFieldMappingEntry( + name="Figures", + source_context="/document/chunk_mark_ups/*/chunk_figures/*", + ), + InputFieldMappingEntry( + name="DateLastModified", source="/document/DateLastModified" + ), + ] index_projections = SearchIndexerIndexProjection( selectors=[ SearchIndexerIndexProjectionSelector( target_index_name=self.index_name, parent_key_field_name="Id", - source_context="/document/chunks/*", + source_context=source_context, mappings=mappings, ), ], From a4ef19bd30f71a5dbc3e634e64617d326719fa3a Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 18:15:47 +0000 Subject: [PATCH 29/64] Update chunker --- .../src/image_processing/semantic_text_chunker.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/image_processing/src/image_processing/semantic_text_chunker.py b/image_processing/src/image_processing/semantic_text_chunker.py index 3cfd1614..5e9ec7bf 100644 --- a/image_processing/src/image_processing/semantic_text_chunker.py +++ b/image_processing/src/image_processing/semantic_text_chunker.py @@ -15,7 +15,7 @@ def __init__( num_surrounding_sentences: int = 1, similarity_threshold: float = 0.8, max_chunk_tokens: int = 200, - min_chunk_tokens: int = 50 + min_chunk_tokens: int = 50, ): self.num_surrounding_sentences = num_surrounding_sentences self.similarity_threshold = similarity_threshold @@ -266,7 +266,7 @@ def look_ahead_and_behind_sentences( next_sentence_is_table_or_figure, ) in enumerate( is_table_or_figure_map[ - current_sentence_index: current_sentence_index + current_sentence_index : current_sentence_index + surround_sentences_gap_to_test ] ): @@ -300,8 +300,7 @@ def retrive_current_chunk_at_n(n): else: return current_chunk[n] - current_chunk_tokens = self.num_tokens_from_string( - " ".join(current_chunk)) + current_chunk_tokens = self.num_tokens_from_string(" ".join(current_chunk)) if len(current_chunk) >= 2 and current_chunk_tokens >= self.min_chunk_tokens: logging.info("Comparing chunks") @@ -403,13 +402,13 @@ def retrieve_current_chunk(): new_is_table_or_figure_map.append(False) if forwards_direction: current_chunk = sentences[ - current_sentence_index: current_sentence_index + current_sentence_index : current_sentence_index + min_of_distance_to_next_figure_or_num_surrounding_sentences ] else: current_chunk = sentences[ - current_sentence_index: current_sentence_index - - min_of_distance_to_next_figure_or_num_surrounding_sentences: -1 + current_sentence_index : current_sentence_index + - min_of_distance_to_next_figure_or_num_surrounding_sentences : -1 ] index += min_of_distance_to_next_figure_or_num_surrounding_sentences continue @@ -490,7 +489,7 @@ async def process_semantic_text_chunker(record: dict, text_chunker) -> dict: logging.error("Chunking Error: %s", e) return { "recordId": record["recordId"], - "data": {}, + "data": None, "errors": [ { "message": "Failed to chunk data. Check function app logs for more details of exact failure." From 769e60f97abd726802c15f091799e349425cc32d Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 18:18:19 +0000 Subject: [PATCH 30/64] Update location of exported requirements --- .pre-commit-config.yaml | 2 +- image_processing/src/image_processing/host.json | 2 +- image_processing/{ => src/image_processing}/requirements.txt | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename image_processing/{ => src/image_processing}/requirements.txt (100%) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 09a9ce36..8e4cef5b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -57,5 +57,5 @@ repos: - id: compile-image-processing-requirements name: compile-image-processing-requirements language: system - entry: bash -c 'cd image_processing && exec uv export --all-extras > requirements.txt' + entry: bash -c 'cd image_processing && exec uv export --all-extras > src/image_processing/requirements.txt' pass_filenames: false diff --git a/image_processing/src/image_processing/host.json b/image_processing/src/image_processing/host.json index 20e5f3ce..a594c3d1 100644 --- a/image_processing/src/image_processing/host.json +++ b/image_processing/src/image_processing/host.json @@ -7,7 +7,7 @@ "logging": { "applicationInsights": { "samplingSettings": { - "excludedTypes": "Request", + "excludedTypes": "Request,Exception", "isEnabled": true } } diff --git a/image_processing/requirements.txt b/image_processing/src/image_processing/requirements.txt similarity index 100% rename from image_processing/requirements.txt rename to image_processing/src/image_processing/requirements.txt From 674bd80b7365a6ed308bf47ecf53ea29fd3c2ad7 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 18:48:30 +0000 Subject: [PATCH 31/64] Update toml --- deploy_ai_search_indexes/pyproject.toml | 3 +++ uv.lock | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/deploy_ai_search_indexes/pyproject.toml b/deploy_ai_search_indexes/pyproject.toml index 1e98e816..fffbbcfb 100644 --- a/deploy_ai_search_indexes/pyproject.toml +++ b/deploy_ai_search_indexes/pyproject.toml @@ -37,3 +37,6 @@ databricks = [ postgresql = [ "text_2_sql_core[postgresql]", ] +sqlite = [ + "text_2_sql_core[sqlite]", +] diff --git a/uv.lock b/uv.lock index c4f06c86..9d2526f6 100644 --- a/uv.lock +++ b/uv.lock @@ -902,6 +902,9 @@ postgresql = [ snowflake = [ { name = "text-2-sql-core", extra = ["snowflake"] }, ] +sqlite = [ + { name = "text-2-sql-core", extra = ["sqlite"] }, +] [package.dev-dependencies] dev = [ @@ -925,6 +928,7 @@ requires-dist = [ { name = "text-2-sql-core", extras = ["databricks"], marker = "extra == 'databricks'", editable = "text_2_sql/text_2_sql_core" }, { name = "text-2-sql-core", extras = ["postgresql"], marker = "extra == 'postgresql'", editable = "text_2_sql/text_2_sql_core" }, { name = "text-2-sql-core", extras = ["snowflake"], marker = "extra == 'snowflake'", editable = "text_2_sql/text_2_sql_core" }, + { name = "text-2-sql-core", extras = ["sqlite"], marker = "extra == 'sqlite'", editable = "text_2_sql/text_2_sql_core" }, ] [package.metadata.requires-dev] From 28c1076fa17f8bd961b3dabd6f0d3d2ea36a7e8a Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 18:54:22 +0000 Subject: [PATCH 32/64] Update README --- image_processing/GETTING_STARTED.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/image_processing/GETTING_STARTED.md b/image_processing/GETTING_STARTED.md index a9d45483..3b99567c 100644 --- a/image_processing/GETTING_STARTED.md +++ b/image_processing/GETTING_STARTED.md @@ -2,7 +2,11 @@ To get started, perform the following steps: -1. Setup Azure OpenAI in your subscription with **gpt-4o-mini** & an embedding model, an Python Function App, AI Search and a storage account. +1. Setup Azure OpenAI in your subscription with **gpt-4o-mini** & an embedding model, an Python Function App, AI Search, Document Intelligence and a Storage Account. + - Grant the Function App the following permissions: + - Cognitive Services Data Contributor (Preview) on the Document Intelligence Instance + - Cognitive Services OpenAI User on the Azure OpenAI Instance + - Storage Blob Data Contributor on the Storage Account Instance 2. Clone this repository and deploy the AI Search rag documents indexes from `deploy_ai_search_indexes`. 3. Run `uv sync` within the image_processing directory to install dependencies (or used the synced `requirements.txt`) 4. Use the `.env.example` to add the required environmental variables to your function app. Not all values are required dependent on whether you are using System / User Assigned Identities or a Key based authentication. Use this template to update the environment variables in the function app. From 908037dc54dd203725147a9b445fefea1fe3d68f Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 18:58:59 +0000 Subject: [PATCH 33/64] Update --- deploy_ai_search_indexes/pyproject.toml | 2 +- pyproject.toml | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/deploy_ai_search_indexes/pyproject.toml b/deploy_ai_search_indexes/pyproject.toml index fffbbcfb..13cc26cd 100644 --- a/deploy_ai_search_indexes/pyproject.toml +++ b/deploy_ai_search_indexes/pyproject.toml @@ -1,5 +1,5 @@ [project] -name = "deploy-ai-search" +name = "deploy_ai_search_indexes" version = "0.1.0" description = "Helper functions to deploy Azure AI Search" readme = "README.md" diff --git a/pyproject.toml b/pyproject.toml index 97aabc6d..6c09b4f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,11 +1,10 @@ [project] name = "dstoolkit-text2sql-and-imageprocessing" version = "0.1.0" -description = "Add your description here" +description = "This repo accelerates development of RAG applications with rich data sources including SQL Warehouses and documents analysed with Azure Document Intelligence." readme = "README.md" requires-python = ">=3.12" dependencies = [ - "text-2-sql-core[sqlite]", ] [dependency-groups] @@ -20,7 +19,7 @@ dev = [ ] [tool.uv.workspace] -members = ["text_2_sql/text_2_sql_core", "text_2_sql/autogen", "deploy_ai_search_indexes", "image_processing", "text_2_sql/semantic_kernel"] +members = ["text_2_sql/text_2_sql_core", "text_2_sql/autogen", "deploy_ai_search_indexes", "image_processing"] [tool.uv.sources] -text-2-sql-core = { workspace = true } +text_2_sql_core = { workspace = true } From d42d3c1d782617acf1dc8ce33fd498d09956b525 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 19:00:03 +0000 Subject: [PATCH 34/64] Update --- text_2_sql/semantic_kernel/.env | 20 ------------------ text_2_sql/semantic_kernel/README.md | 1 - text_2_sql/semantic_kernel/pyproject.toml | 25 ----------------------- 3 files changed, 46 deletions(-) delete mode 100644 text_2_sql/semantic_kernel/.env delete mode 100644 text_2_sql/semantic_kernel/README.md delete mode 100644 text_2_sql/semantic_kernel/pyproject.toml diff --git a/text_2_sql/semantic_kernel/.env b/text_2_sql/semantic_kernel/.env deleted file mode 100644 index 39fdcb31..00000000 --- a/text_2_sql/semantic_kernel/.env +++ /dev/null @@ -1,20 +0,0 @@ -OpenAI__CompletionDeployment= -OpenAI__EmbeddingModel= -OpenAI__Endpoint= -OpenAI__ApiKey= -OpenAI__ApiVersion= -Text2Sql__DatabaseEngine= -Text2Sql__UseQueryCache= -Text2Sql__PreRunQueryCache= -Text2Sql__DatabaseName= -Text2Sql__DatabaseConnectionString= -AIService__AzureSearchOptions__Endpoint= -AIService__AzureSearchOptions__Key= -AIService__AzureSearchOptions__RagDocuments__Index= -AIService__AzureSearchOptions__Text2Sql__Index= -AIService__AzureSearchOptions__Text2SqlQueryCache__Index= -AIService__AzureSearchOptions__RagDocuments__SemanticConfig= -AIService__AzureSearchOptions__Text2Sql__SemanticConfig= -AIService__AzureSearchOptions__Text2SqlQueryCache__SemanticConfig= -IdentityType= # system_assigned or user_assigned or key -ClientId= diff --git a/text_2_sql/semantic_kernel/README.md b/text_2_sql/semantic_kernel/README.md deleted file mode 100644 index 29b0a85c..00000000 --- a/text_2_sql/semantic_kernel/README.md +++ /dev/null @@ -1 +0,0 @@ -Coming soon. Refer to Autogen version for now diff --git a/text_2_sql/semantic_kernel/pyproject.toml b/text_2_sql/semantic_kernel/pyproject.toml deleted file mode 100644 index f68fe9ef..00000000 --- a/text_2_sql/semantic_kernel/pyproject.toml +++ /dev/null @@ -1,25 +0,0 @@ -[project] -name = "semantic_kernel_text_2_sql" -version = "0.1.0" -description = "Semantic Kernel Based Implementation" -readme = "README.md" -requires-python = ">=3.12" -dependencies = [ - "grpcio>=1.68.1", - "semantic-kernel==1.9.0", - "text_2_sql_core", -] - -[dependency-groups] -dev = [ - "black>=24.10.0", - "ipykernel>=6.29.5", - "jupyter>=1.1.1", - "pre-commit>=4.0.1", - "pygments>=2.18.0", - "ruff>=0.8.1", - "python-dotenv>=1.0.1", -] - -[tool.uv.sources] -text_2_sql_core = { workspace = true } From 7f1b72c0f1db58b387329a2eca7c7c47b5806907 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 19:07:08 +0000 Subject: [PATCH 35/64] Update lock --- .funcignore | 8 ++ uv.lock | 308 +--------------------------------------------------- 2 files changed, 10 insertions(+), 306 deletions(-) create mode 100644 .funcignore diff --git a/.funcignore b/.funcignore new file mode 100644 index 00000000..f1110d33 --- /dev/null +++ b/.funcignore @@ -0,0 +1,8 @@ +.git* +.vscode +__azurite_db*__.json +__blobstorage__ +__queuestorage__ +local.settings.json +test +.venv diff --git a/uv.lock b/uv.lock index 9d2526f6..7e91e4ba 100644 --- a/uv.lock +++ b/uv.lock @@ -4,10 +4,9 @@ requires-python = ">=3.12" [manifest] members = [ "autogen-text-2-sql", - "deploy-ai-search", + "deploy-ai-search-indexes", "dstoolkit-text2sql-and-imageprocessing", "image-processing", - "semantic-kernel-text-2-sql", "text-2-sql-core", ] @@ -672,15 +671,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249 }, ] -[[package]] -name = "chardet" -version = "5.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/f7b6ab21ec75897ed80c17d79b15951a719226b9fababf1e40ea74d69079/chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7", size = 2069618 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970", size = 199385 }, -] - [[package]] name = "charset-normalizer" version = "3.4.1" @@ -880,7 +870,7 @@ wheels = [ ] [[package]] -name = "deploy-ai-search" +name = "deploy-ai-search-indexes" version = "0.1.0" source = { virtual = "deploy_ai_search_indexes" } dependencies = [ @@ -976,9 +966,6 @@ wheels = [ name = "dstoolkit-text2sql-and-imageprocessing" version = "0.1.0" source = { virtual = "." } -dependencies = [ - { name = "text-2-sql-core", extra = ["sqlite"] }, -] [package.dev-dependencies] dev = [ @@ -992,7 +979,6 @@ dev = [ ] [package.metadata] -requires-dist = [{ name = "text-2-sql-core", extras = ["sqlite"], editable = "text_2_sql/text_2_sql_core" }] [package.metadata.requires-dev] dev = [ @@ -1505,21 +1491,6 @@ format-nongpl = [ { name = "webcolors" }, ] -[[package]] -name = "jsonschema-path" -version = "0.3.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pathable" }, - { name = "pyyaml" }, - { name = "referencing" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/85/39/3a58b63a997b0cf824536d6f84fff82645a1ca8de222ee63586adab44dfa/jsonschema_path-0.3.3.tar.gz", hash = "sha256:f02e5481a4288ec062f8e68c808569e427d905bedfecb7f2e4c69ef77957c382", size = 11589 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/53/b0/69237e85976916b2e37586b7ddc48b9547fc38b440e25103d084b2b02ab3/jsonschema_path-0.3.3-py3-none-any.whl", hash = "sha256:203aff257f8038cd3c67be614fe6b2001043408cb1b4e36576bc4921e09d83c4", size = 14817 }, -] - [[package]] name = "jsonschema-specifications" version = "2024.10.1" @@ -1755,22 +1726,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5d/e9/5a5ffd9b286db82be70d677d0a91e4d58f7912bb8dd026ddeeb4abe70679/language_data-1.3.0-py3-none-any.whl", hash = "sha256:e2ee943551b5ae5f89cd0e801d1fc3835bb0ef5b7e9c3a4e8e17b2b214548fbf", size = 5385760 }, ] -[[package]] -name = "lazy-object-proxy" -version = "1.10.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2c/f0/f02e2d150d581a294efded4020094a371bbab42423fe78625ac18854d89b/lazy-object-proxy-1.10.0.tar.gz", hash = "sha256:78247b6d45f43a52ef35c25b5581459e85117225408a4128a3daf8bf9648ac69", size = 43271 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d0/5d/768a7f2ccebb29604def61842fd54f6f5f75c79e366ee8748dda84de0b13/lazy_object_proxy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e98c8af98d5707dcdecc9ab0863c0ea6e88545d42ca7c3feffb6b4d1e370c7ba", size = 27560 }, - { url = "https://files.pythonhosted.org/packages/b3/ce/f369815549dbfa4bebed541fa4e1561d69e4f268a1f6f77da886df182dab/lazy_object_proxy-1.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:952c81d415b9b80ea261d2372d2a4a2332a3890c2b83e0535f263ddfe43f0d43", size = 72403 }, - { url = "https://files.pythonhosted.org/packages/44/46/3771e0a4315044aa7b67da892b2fb1f59dfcf0eaff2c8967b2a0a85d5896/lazy_object_proxy-1.10.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80b39d3a151309efc8cc48675918891b865bdf742a8616a337cb0090791a0de9", size = 72401 }, - { url = "https://files.pythonhosted.org/packages/81/39/84ce4740718e1c700bd04d3457ac92b2e9ce76529911583e7a2bf4d96eb2/lazy_object_proxy-1.10.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e221060b701e2aa2ea991542900dd13907a5c90fa80e199dbf5a03359019e7a3", size = 75375 }, - { url = "https://files.pythonhosted.org/packages/86/3b/d6b65da2b864822324745c0a73fe7fd86c67ccea54173682c3081d7adea8/lazy_object_proxy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:92f09ff65ecff3108e56526f9e2481b8116c0b9e1425325e13245abfd79bdb1b", size = 75466 }, - { url = "https://files.pythonhosted.org/packages/f5/33/467a093bf004a70022cb410c590d937134bba2faa17bf9dc42a48f49af35/lazy_object_proxy-1.10.0-cp312-cp312-win32.whl", hash = "sha256:3ad54b9ddbe20ae9f7c1b29e52f123120772b06dbb18ec6be9101369d63a4074", size = 25914 }, - { url = "https://files.pythonhosted.org/packages/77/ce/7956dc5ac2f8b62291b798c8363c81810e22a9effe469629d297d087e350/lazy_object_proxy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:127a789c75151db6af398b8972178afe6bda7d6f68730c057fbbc2e96b08d282", size = 27525 }, - { url = "https://files.pythonhosted.org/packages/31/8b/94dc8d58704ab87b39faed6f2fc0090b9d90e2e2aa2bbec35c79f3d2a054/lazy_object_proxy-1.10.0-pp310.pp311.pp312.pp38.pp39-none-any.whl", hash = "sha256:80fa48bd89c8f2f456fc0765c11c23bf5af827febacd2f523ca5bc1893fcc09d", size = 16405 }, -] - [[package]] name = "lz4" version = "4.3.3" @@ -1918,15 +1873,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4b/07/f35b07c2d721e634a9ccf7af4a8edabfda2a6accc777b4e8547f8a41d22e/model2vec-0.3.7-py3-none-any.whl", hash = "sha256:5000a19d86e76f20afa4b403946f512a4c17496e35295b8855e728f4ba04ec89", size = 27695 }, ] -[[package]] -name = "more-itertools" -version = "10.6.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/88/3b/7fa1fe835e2e93fd6d7b52b2f95ae810cf5ba133e1845f726f5a992d62c2/more-itertools-10.6.0.tar.gz", hash = "sha256:2cd7fad1009c31cc9fb6a035108509e6547547a7a738374f10bd49a09eb3ee3b", size = 125009 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/23/62/0fe302c6d1be1c777cab0616e6302478251dfbf9055ad426f5d0def75c89/more_itertools-10.6.0-py3-none-any.whl", hash = "sha256:6eb054cb4b6db1473f6e15fcc676a08e4732548acd47c708f0e179c2c7c01e89", size = 63038 }, -] - [[package]] name = "msal" version = "1.31.1" @@ -2209,54 +2155,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/07/b4/57f1954a4560092ad8c45f07ad183eab9c8e093e0a1db829f9b506b2d5d1/openai-1.59.9-py3-none-any.whl", hash = "sha256:61a0608a1313c08ddf92fe793b6dbd1630675a1fe3866b2f96447ce30050c448", size = 455527 }, ] -[[package]] -name = "openapi-core" -version = "0.19.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "isodate" }, - { name = "jsonschema" }, - { name = "jsonschema-path" }, - { name = "more-itertools" }, - { name = "openapi-schema-validator" }, - { name = "openapi-spec-validator" }, - { name = "parse" }, - { name = "werkzeug" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/34/b9/a769ae516c7f016465b2d9abc6e8dc4d5a1b54c57ab99b3cc95e9587955f/openapi_core-0.19.4.tar.gz", hash = "sha256:1150d9daa5e7b4cacfd7d7e097333dc89382d7d72703934128dcf8a1a4d0df49", size = 109095 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/b3/4534adc8bac68a5d743caa786f1443545faed4d7cc7a5650b2d49255adfc/openapi_core-0.19.4-py3-none-any.whl", hash = "sha256:38e8347b6ebeafe8d3beb588214ecf0171874bb65411e9d4efd23cb011687201", size = 103714 }, -] - -[[package]] -name = "openapi-schema-validator" -version = "0.6.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jsonschema" }, - { name = "jsonschema-specifications" }, - { name = "rfc3339-validator" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/8b/f3/5507ad3325169347cd8ced61c232ff3df70e2b250c49f0fe140edb4973c6/openapi_schema_validator-0.6.3.tar.gz", hash = "sha256:f37bace4fc2a5d96692f4f8b31dc0f8d7400fd04f3a937798eaf880d425de6ee", size = 11550 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/21/c6/ad0fba32775ae749016829dace42ed80f4407b171da41313d1a3a5f102e4/openapi_schema_validator-0.6.3-py3-none-any.whl", hash = "sha256:f3b9870f4e556b5a62a1c39da72a6b4b16f3ad9c73dc80084b1b11e74ba148a3", size = 8755 }, -] - -[[package]] -name = "openapi-spec-validator" -version = "0.7.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jsonschema" }, - { name = "jsonschema-path" }, - { name = "lazy-object-proxy" }, - { name = "openapi-schema-validator" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/67/fe/21954ff978239dc29ebb313f5c87eeb4ec929b694b9667323086730998e2/openapi_spec_validator-0.7.1.tar.gz", hash = "sha256:8577b85a8268685da6f8aa30990b83b7960d4d1117e901d451b5d572605e5ec7", size = 37985 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2b/4d/e744fff95aaf3aeafc968d5ba7297c8cda0d1ecb8e3acd21b25adae4d835/openapi_spec_validator-0.7.1-py3-none-any.whl", hash = "sha256:3c81825043f24ccbcd2f4b149b11e8231abce5ba84f37065e14ec947d8f4e959", size = 38998 }, -] - [[package]] name = "openpyxl" version = "3.1.5" @@ -2282,33 +2180,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/43/53/5249ea860d417a26a3a6f1bdedfc0748c4f081a3adaec3d398bc0f7c6a71/opentelemetry_api-1.29.0-py3-none-any.whl", hash = "sha256:5fcd94c4141cc49c736271f3e1efb777bebe9cc535759c54c936cca4f1b312b8", size = 64304 }, ] -[[package]] -name = "opentelemetry-sdk" -version = "1.29.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "opentelemetry-api" }, - { name = "opentelemetry-semantic-conventions" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0c/5a/1ed4c3cf6c09f80565fc085f7e8efa0c222712fd2a9412d07424705dcf72/opentelemetry_sdk-1.29.0.tar.gz", hash = "sha256:b0787ce6aade6ab84315302e72bd7a7f2f014b0fb1b7c3295b88afe014ed0643", size = 157229 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/1d/512b86af21795fb463726665e2f61db77d384e8779fdcf4cb0ceec47866d/opentelemetry_sdk-1.29.0-py3-none-any.whl", hash = "sha256:173be3b5d3f8f7d671f20ea37056710217959e774e2749d984355d1f9391a30a", size = 118078 }, -] - -[[package]] -name = "opentelemetry-semantic-conventions" -version = "0.50b0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "deprecated" }, - { name = "opentelemetry-api" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e7/4e/d7c7c91ff47cd96fe4095dd7231701aec7347426fd66872ff320d6cd1fcc/opentelemetry_semantic_conventions-0.50b0.tar.gz", hash = "sha256:02dc6dbcb62f082de9b877ff19a3f1ffaa3c306300fa53bfac761c4567c83d38", size = 100459 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/da/fb/dc15fad105450a015e913cfa4f5c27b6a5f1bea8fb649f8cae11e699c8af/opentelemetry_semantic_conventions-0.50b0-py3-none-any.whl", hash = "sha256:e87efba8fdb67fb38113efea6a349531e75ed7ffc01562f65b802fcecb5e115e", size = 166602 }, -] - [[package]] name = "overrides" version = "7.7.0" @@ -2370,15 +2241,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ef/af/4fbc8cab944db5d21b7e2a5b8e9211a03a79852b1157e2c102fcc61ac440/pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc", size = 8663 }, ] -[[package]] -name = "parse" -version = "1.20.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4f/78/d9b09ba24bb36ef8b83b71be547e118d46214735b6dfb39e4bfde0e9b9dd/parse-1.20.2.tar.gz", hash = "sha256:b41d604d16503c79d81af5165155c0b20f6c8d6c559efa66b4b695c3e5a0a0ce", size = 29391 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d0/31/ba45bf0b2aa7898d81cbbfac0e88c267befb59ad91a19e36e1bc5578ddb1/parse-1.20.2-py2.py3-none-any.whl", hash = "sha256:967095588cb802add9177d0c0b6133b5ba33b1ea9007ca800e526f42a85af558", size = 20126 }, -] - [[package]] name = "parso" version = "0.8.4" @@ -2388,15 +2250,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c6/ac/dac4a63f978e4dcb3c6d3a78c4d8e0192a113d288502a1216950c41b1027/parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", size = 103650 }, ] -[[package]] -name = "pathable" -version = "0.4.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/67/93/8f2c2075b180c12c1e9f6a09d1a985bc2036906b13dff1d8917e395f2048/pathable-0.4.4.tar.gz", hash = "sha256:6905a3cd17804edfac7875b5f6c9142a218c7caef78693c2dbbbfbac186d88b2", size = 8124 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7d/eb/b6260b31b1a96386c0a880edebe26f89669098acea8e0318bff6adb378fd/pathable-0.4.4-py3-none-any.whl", hash = "sha256:5ae9e94793b6ef5a4cbe0a7ce9dbbefc1eec38df253763fd0aeeacf2762dbbc2", size = 9592 }, -] - [[package]] name = "pathspec" version = "0.12.1" @@ -2477,22 +2330,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9b/fb/a70a4214956182e0d7a9099ab17d50bfcba1056188e9b14f35b9e2b62a0d/portalocker-2.10.1-py3-none-any.whl", hash = "sha256:53a5984ebc86a025552264b459b46a2086e269b21823cb572f8f28ee759e45bf", size = 18423 }, ] -[[package]] -name = "prance" -version = "23.6.21.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "chardet" }, - { name = "packaging" }, - { name = "requests" }, - { name = "ruamel-yaml" }, - { name = "six" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/73/f0/bcb5ffc8b7ab8e3d02dbef3bd945cf8fd6e12c146774f900659406b9fce1/prance-23.6.21.0.tar.gz", hash = "sha256:d8c15f8ac34019751cc4945f866d8d964d7888016d10de3592e339567177cabe", size = 2798776 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c9/db/4fb4901ee61274d0ab97746461fc5f2637e5d73aa73f34ee28e941a699a1/prance-23.6.21.0-py3-none-any.whl", hash = "sha256:6a4276fa07ed9f22feda4331097d7503c4adc3097e46ffae97425f2c1026bd9f", size = 36279 }, -] - [[package]] name = "pre-commit" version = "4.1.0" @@ -2666,15 +2503,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fa/2b/a0053f1304586f2976cb2c37ddb0e52cf4114220e805ebba272a1e231ccc/pyarrow-16.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:febde33305f1498f6df85e8020bca496d0e9ebf2093bab9e0f65e2b4ae2b3444", size = 25838156 }, ] -[[package]] -name = "pybars4" -version = "0.9.13" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pymeta3" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ee/52/9aa428633ef5aba4b096b2b2f8d046ece613cecab28b4ceed54126d25ea5/pybars4-0.9.13.tar.gz", hash = "sha256:425817da20d4ad320bc9b8e77a60cab1bb9d3c677df3dce224925c3310fcd635", size = 29907 } - [[package]] name = "pycparser" version = "2.22" @@ -2737,19 +2565,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186 }, ] -[[package]] -name = "pydantic-settings" -version = "2.7.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pydantic" }, - { name = "python-dotenv" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/73/7b/c58a586cd7d9ac66d2ee4ba60ca2d241fa837c02bca9bea80a9a8c3d22a9/pydantic_settings-2.7.1.tar.gz", hash = "sha256:10c9caad35e64bfb3c2fbf70a078c0e25cc92499782e5200747f942a065dec93", size = 79920 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b4/46/93416fdae86d40879714f72956ac14df9c7b76f7d41a4d68aa9f71a0028b/pydantic_settings-2.7.1-py3-none-any.whl", hash = "sha256:590be9e6e24d06db33a4262829edef682500ef008565a969c73d39d5f8bfb3fd", size = 29718 }, -] - [[package]] name = "pygments" version = "2.19.1" @@ -2773,12 +2588,6 @@ crypto = [ { name = "cryptography" }, ] -[[package]] -name = "pymeta3" -version = "0.5.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ce/af/409edba35fc597f1e386e3860303791ab5a28d6cc9a8aecbc567051b19a9/PyMeta3-0.5.1.tar.gz", hash = "sha256:18bda326d9a9bbf587bfc0ee0bc96864964d78b067288bcf55d4d98681d05bcb", size = 29566 } - [[package]] name = "pymupdf" version = "1.25.2" @@ -3118,44 +2927,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f8/30/7ac943f69855c2db77407ae363484b915d861702dbba1aa82d68d57f42be/rpds_py-0.22.3-cp313-cp313t-win_amd64.whl", hash = "sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf", size = 233794 }, ] -[[package]] -name = "ruamel-yaml" -version = "0.18.10" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "ruamel-yaml-clib", marker = "python_full_version < '3.13' and platform_python_implementation == 'CPython'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ea/46/f44d8be06b85bc7c4d8c95d658be2b68f27711f279bf9dd0612a5e4794f5/ruamel.yaml-0.18.10.tar.gz", hash = "sha256:20c86ab29ac2153f80a428e1254a8adf686d3383df04490514ca3b79a362db58", size = 143447 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c2/36/dfc1ebc0081e6d39924a2cc53654497f967a084a436bb64402dfce4254d9/ruamel.yaml-0.18.10-py3-none-any.whl", hash = "sha256:30f22513ab2301b3d2b577adc121c6471f28734d3d9728581245f1e76468b4f1", size = 117729 }, -] - -[[package]] -name = "ruamel-yaml-clib" -version = "0.2.12" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/20/84/80203abff8ea4993a87d823a5f632e4d92831ef75d404c9fc78d0176d2b5/ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f", size = 225315 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/48/41/e7a405afbdc26af961678474a55373e1b323605a4f5e2ddd4a80ea80f628/ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632", size = 133433 }, - { url = "https://files.pythonhosted.org/packages/ec/b0/b850385604334c2ce90e3ee1013bd911aedf058a934905863a6ea95e9eb4/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:943f32bc9dedb3abff9879edc134901df92cfce2c3d5c9348f172f62eb2d771d", size = 647362 }, - { url = "https://files.pythonhosted.org/packages/44/d0/3f68a86e006448fb6c005aee66565b9eb89014a70c491d70c08de597f8e4/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c3829bb364fdb8e0332c9931ecf57d9be3519241323c5274bd82f709cebc0c", size = 754118 }, - { url = "https://files.pythonhosted.org/packages/52/a9/d39f3c5ada0a3bb2870d7db41901125dbe2434fa4f12ca8c5b83a42d7c53/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd", size = 706497 }, - { url = "https://files.pythonhosted.org/packages/b0/fa/097e38135dadd9ac25aecf2a54be17ddf6e4c23e43d538492a90ab3d71c6/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31", size = 698042 }, - { url = "https://files.pythonhosted.org/packages/ec/d5/a659ca6f503b9379b930f13bc6b130c9f176469b73b9834296822a83a132/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680", size = 745831 }, - { url = "https://files.pythonhosted.org/packages/db/5d/36619b61ffa2429eeaefaab4f3374666adf36ad8ac6330d855848d7d36fd/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b82a7c94a498853aa0b272fd5bc67f29008da798d4f93a2f9f289feb8426a58d", size = 715692 }, - { url = "https://files.pythonhosted.org/packages/b1/82/85cb92f15a4231c89b95dfe08b09eb6adca929ef7df7e17ab59902b6f589/ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5", size = 98777 }, - { url = "https://files.pythonhosted.org/packages/d7/8f/c3654f6f1ddb75daf3922c3d8fc6005b1ab56671ad56ffb874d908bfa668/ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4", size = 115523 }, - { url = "https://files.pythonhosted.org/packages/29/00/4864119668d71a5fa45678f380b5923ff410701565821925c69780356ffa/ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a", size = 132011 }, - { url = "https://files.pythonhosted.org/packages/7f/5e/212f473a93ae78c669ffa0cb051e3fee1139cb2d385d2ae1653d64281507/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux2014_aarch64.whl", hash = "sha256:e7e3736715fbf53e9be2a79eb4db68e4ed857017344d697e8b9749444ae57475", size = 642488 }, - { url = "https://files.pythonhosted.org/packages/1f/8f/ecfbe2123ade605c49ef769788f79c38ddb1c8fa81e01f4dbf5cf1a44b16/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7e75b4965e1d4690e93021adfcecccbca7d61c7bddd8e22406ef2ff20d74ef", size = 745066 }, - { url = "https://files.pythonhosted.org/packages/e2/a9/28f60726d29dfc01b8decdb385de4ced2ced9faeb37a847bd5cf26836815/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6", size = 701785 }, - { url = "https://files.pythonhosted.org/packages/84/7e/8e7ec45920daa7f76046578e4f677a3215fe8f18ee30a9cb7627a19d9b4c/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf", size = 693017 }, - { url = "https://files.pythonhosted.org/packages/c5/b3/d650eaade4ca225f02a648321e1ab835b9d361c60d51150bac49063b83fa/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1", size = 741270 }, - { url = "https://files.pythonhosted.org/packages/87/b8/01c29b924dcbbed75cc45b30c30d565d763b9c4d540545a0eeecffb8f09c/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f6f3eac23941b32afccc23081e1f50612bdbe4e982012ef4f5797986828cd01", size = 709059 }, - { url = "https://files.pythonhosted.org/packages/30/8c/ed73f047a73638257aa9377ad356bea4d96125b305c34a28766f4445cc0f/ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6", size = 98583 }, - { url = "https://files.pythonhosted.org/packages/b0/85/e8e751d8791564dd333d5d9a4eab0a7a115f7e349595417fd50ecae3395c/ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3", size = 115190 }, -] - [[package]] name = "ruff" version = "0.9.2" @@ -3203,69 +2974,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/86/ca/aa489392ec6fb59223ffce825461e1f811a3affd417121a2088be7a5758b/safetensors-0.5.2-cp38-abi3-win_amd64.whl", hash = "sha256:78abdddd03a406646107f973c7843276e7b64e5e32623529dc17f3d94a20f589", size = 303756 }, ] -[[package]] -name = "semantic-kernel" -version = "1.9.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "aiohttp" }, - { name = "defusedxml" }, - { name = "jinja2" }, - { name = "nest-asyncio" }, - { name = "numpy" }, - { name = "openai" }, - { name = "openapi-core" }, - { name = "opentelemetry-api" }, - { name = "opentelemetry-sdk" }, - { name = "prance" }, - { name = "pybars4" }, - { name = "pydantic" }, - { name = "pydantic-settings" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/92/4f/aee19af79ef24c125f13834dc5619776ec521ef8074ba0f83b2b65a94de4/semantic_kernel-1.9.0.tar.gz", hash = "sha256:a8e919ab5428e693b21337652901e7626f42281b9e03ea11352bdb6a4e86508f", size = 260226 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/54/112ae727ce0df570723b1a0c96f76036c9fda03e442a56b7119780212f25/semantic_kernel-1.9.0-py3-none-any.whl", hash = "sha256:8484c3395d3d469958ed3560120eb4ffa73e6dd5b31b24bf8d50322349ab796d", size = 459668 }, -] - -[[package]] -name = "semantic-kernel-text-2-sql" -version = "0.1.0" -source = { virtual = "text_2_sql/semantic_kernel" } -dependencies = [ - { name = "grpcio" }, - { name = "semantic-kernel" }, - { name = "text-2-sql-core" }, -] - -[package.dev-dependencies] -dev = [ - { name = "black" }, - { name = "ipykernel" }, - { name = "jupyter" }, - { name = "pre-commit" }, - { name = "pygments" }, - { name = "python-dotenv" }, - { name = "ruff" }, -] - -[package.metadata] -requires-dist = [ - { name = "grpcio", specifier = ">=1.68.1" }, - { name = "semantic-kernel", specifier = "==1.9.0" }, - { name = "text-2-sql-core", editable = "text_2_sql/text_2_sql_core" }, -] - -[package.metadata.requires-dev] -dev = [ - { name = "black", specifier = ">=24.10.0" }, - { name = "ipykernel", specifier = ">=6.29.5" }, - { name = "jupyter", specifier = ">=1.1.1" }, - { name = "pre-commit", specifier = ">=4.0.1" }, - { name = "pygments", specifier = ">=2.18.0" }, - { name = "python-dotenv", specifier = ">=1.0.1" }, - { name = "ruff", specifier = ">=0.8.1" }, -] - [[package]] name = "send2trash" version = "1.8.3" @@ -3922,18 +3630,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526", size = 58826 }, ] -[[package]] -name = "werkzeug" -version = "3.1.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markupsafe" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9f/69/83029f1f6300c5fb2471d621ab06f6ec6b3324685a2ce0f9777fd4a8b71e/werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746", size = 806925 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", size = 224498 }, -] - [[package]] name = "widgetsnbextension" version = "4.0.13" From c3aecf13c04e6575a9ef01c22fffe64c88a09c6f Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 19:09:39 +0000 Subject: [PATCH 36/64] Update lock --- deploy_ai_search_indexes/pyproject.toml | 3 +++ image_processing/pyproject.toml | 5 ++++- text_2_sql/autogen/pyproject.toml | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/deploy_ai_search_indexes/pyproject.toml b/deploy_ai_search_indexes/pyproject.toml index 13cc26cd..5ce4fe43 100644 --- a/deploy_ai_search_indexes/pyproject.toml +++ b/deploy_ai_search_indexes/pyproject.toml @@ -3,6 +3,9 @@ name = "deploy_ai_search_indexes" version = "0.1.0" description = "Helper functions to deploy Azure AI Search" readme = "README.md" +authors = [ + { name = "Ben Constable", email = "benconstable@microsoft.com" } +] requires-python = ">=3.12" dependencies = [ "azure-identity>=1.19.0", diff --git a/image_processing/pyproject.toml b/image_processing/pyproject.toml index 4fb94d7f..cf376f18 100644 --- a/image_processing/pyproject.toml +++ b/image_processing/pyproject.toml @@ -1,8 +1,11 @@ [project] name = "image_processing" version = "0.1.0" -description = "Add your description here" +description = "Image processing for documents with Document Intelligence and OpenAI" readme = "README.md" +authors = [ + { name = "Ben Constable", email = "benconstable@microsoft.com" } +] requires-python = ">=3.12" dependencies = [ "azure-functions>=1.21.3", diff --git a/text_2_sql/autogen/pyproject.toml b/text_2_sql/autogen/pyproject.toml index 8d754eee..4d4273b1 100644 --- a/text_2_sql/autogen/pyproject.toml +++ b/text_2_sql/autogen/pyproject.toml @@ -3,6 +3,9 @@ name = "autogen_text_2_sql" version = "0.1.0" description = "AutoGen Based Implementation" readme = "README.md" +authors = [ + { name = "Ben Constable", email = "benconstable@microsoft.com" } +] requires-python = ">=3.12" dependencies = [ "aiostream>=0.6.4", @@ -18,7 +21,6 @@ dependencies = [ [dependency-groups] dev = [ - "autogen-text-2-sql", "black>=24.10.0", "ipykernel>=6.29.5", "jupyter>=1.1.1", From 63c4915d193128baa0953be3498770b319a05791 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 19:30:49 +0000 Subject: [PATCH 37/64] Update req --- deploy_ai_search_indexes/README.md | 57 ++++++++++++++----- .../src/deploy_ai_search_indexes/deploy.py | 4 +- .../image_processing.py | 8 +-- .../src/image_processing/requirements.txt | 24 ++++---- text_2_sql/GETTING_STARTED.md | 8 +-- uv.lock | 38 ++++++------- 6 files changed, 84 insertions(+), 55 deletions(-) diff --git a/deploy_ai_search_indexes/README.md b/deploy_ai_search_indexes/README.md index 11fac63c..8676061f 100644 --- a/deploy_ai_search_indexes/README.md +++ b/deploy_ai_search_indexes/README.md @@ -4,12 +4,19 @@ The associated scripts in this portion of the repository contains pre-built scri ## Steps for Image Processing Index Deployment (For Image Processing) -1. Update `.env` file with the associated values. Not all values are required dependent on whether you are using System / User Assigned Identities or a Key based authentication. -2. Adjust `image_processing.py` with any changes to the index / indexer. The `get_skills()` method implements the skills pipeline. Make any adjustments here in the skills needed to enrich the data source. -3. Run `deploy.py` with the following args: +**Execute the following commands in the `deploy_ai_search_indexes` directory:** +1. Create your `.env` file based on the provided sample `deploy_ai_search_indexes/.env.example`. Place this file in the same place in `deploy_ai_search_indexes/.env`. +2. Run `uv sync` within the `deploy_ai_search_indexes` directory to install dependencies. + - Install the optional dependencies if you need a database connector other than TSQL. `uv sync --extra ` + - See the supported connectors in `text_2_sql_core/src/text_2_sql_core/connectors`. + +**Execute the following commands in the `deploy_ai_search_indexes/src/deploy_ai_search_indexes` directory:** + +3. Adjust `image_processing.py` with any changes to the index / indexer. The `get_skills()` method implements the skills pipeline. Make any adjustments here in the skills needed to enrich the data source. +4. Run `deploy.py` with the following args: - `index_type image_processing`. This selects the `ImageProcessingAISearch` sub class. - - `enable_page_chunking True`. This determines whether page wise chunking is applied in ADI, or whether the inbuilt skill is used for TextSplit. This suits documents that are inheritely page-wise e.g. pptx files. + - `enable_page_wise_chunking True`. This determines whether page wise chunking is applied in ADI, or whether the inbuilt skill is used for TextSplit. This suits documents that are inheritely page-wise e.g. pptx files. - `rebuild`. Whether to delete and rebuild the index. - `suffix`. Optional parameter that will apply a suffix onto the deployed index and indexer. This is useful if you want deploy a test version, before overwriting the main version. @@ -17,9 +24,17 @@ The associated scripts in this portion of the repository contains pre-built scri ### Schema Store Index -1. Update `.env` file with the associated values. Not all values are required dependent on whether you are using System / User Assigned Identities or a Key based authentication. -2. Adjust `text_2_sql_schema_store.py` with any changes to the index / indexer. The `get_skills()` method implements the skills pipeline. Make any adjustments here in the skills needed to enrich the data source. -3. Run `deploy.py` with the following args: +**Execute the following commands in the `deploy_ai_search_indexes` directory:** + +1. Create your `.env` file based on the provided sample `deploy_ai_search_indexes/.env.example`. Place this file in the same place in `deploy_ai_search_indexes/.env`. +2. Run `uv sync` within the `deploy_ai_search_indexes` directory to install dependencies. + - Install the optional dependencies if you need a database connector other than TSQL. `uv sync --extra ` + - See the supported connectors in `text_2_sql_core/src/text_2_sql_core/connectors`. + +**Execute the following commands in the `deploy_ai_search_indexes/src/deploy_ai_search_indexes` directory:** + +3. Adjust `text_2_sql_schema_store.py` with any changes to the index / indexer. The `get_skills()` method implements the skills pipeline. Make any adjustments here in the skills needed to enrich the data source. +4. Run `deploy.py` with the following args: - `index_type text_2_sql_schema_store`. This selects the `Text2SQLSchemaStoreAISearch` sub class. - `rebuild`. Whether to delete and rebuild the index. @@ -28,9 +43,17 @@ The associated scripts in this portion of the repository contains pre-built scri ### Column Value Store Index -1. Update `.env` file with the associated values. Not all values are required dependent on whether you are using System / User Assigned Identities or a Key based authentication. -2. Adjust `text_2_sql_column_value_store.py` with any changes to the index / indexer. -3. Run `deploy.py` with the following args: +**Execute the following commands in the `deploy_ai_search_indexes` directory:** + +1. Create your `.env` file based on the provided sample `deploy_ai_search_indexes/.env.example`. Place this file in the same place in `deploy_ai_search_indexes/.env`. +2. Run `uv sync` within the `deploy_ai_search_indexes` directory to install dependencies. + - Install the optional dependencies if you need a database connector other than TSQL. `uv sync --extra ` + - See the supported connectors in `text_2_sql_core/src/text_2_sql_core/connectors`. + +**Execute the following commands in the `deploy_ai_search_indexes/src/deploy_ai_search_indexes` directory:** + +3. Adjust `text_2_sql_column_value_store.py` with any changes to the index / indexer. +4. Run `deploy.py` with the following args: - `index_type text_2_sql_column_value_store`. This selects the `Text2SQLColumnValueStoreAISearch` sub class. - `rebuild`. Whether to delete and rebuild the index. @@ -38,9 +61,17 @@ The associated scripts in this portion of the repository contains pre-built scri ### Query Cache Index -1. Update `.env` file with the associated values. Not all values are required dependent on whether you are using System / User Assigned Identities or a Key based authentication. -2. Adjust `text_2_sql_query_cache.py` with any changes to the index. **There is an optional provided indexer or skillset for this cache. You may instead want the application code will write directly to it. See the details in the Text2SQL README for different cache strategies.** -3. Run `deploy.py` with the following args: +**Execute the following commands in the `deploy_ai_search_indexes` directory:** + +1. Create your `.env` file based on the provided sample `deploy_ai_search_indexes/.env.example`. Place this file in the same place in `deploy_ai_search_indexes/.env`. +2. Run `uv sync` within the `deploy_ai_search_indexes` directory to install dependencies. + - Install the optional dependencies if you need a database connector other than TSQL. `uv sync --extra ` + - See the supported connectors in `text_2_sql_core/src/text_2_sql_core/connectors`. + +**Execute the following commands in the `deploy_ai_search_indexes/src/deploy_ai_search_indexes` directory:** + +3. Adjust `text_2_sql_query_cache.py` with any changes to the index. **There is an optional provided indexer or skillset for this cache. You may instead want the application code will write directly to it. See the details in the Text2SQL README for different cache strategies.** +4. Run `deploy.py` with the following args: - `index_type text_2_sql_query_cache`. This selects the `Text2SQLQueryCacheAISearch` sub class. - `rebuild`. Whether to delete and rebuild the index. diff --git a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/deploy.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/deploy.py index 41689f6e..492bbed1 100644 --- a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/deploy.py +++ b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/deploy.py @@ -21,7 +21,7 @@ def deploy_config(arguments: argparse.Namespace): index_config = ImageProcessingAISearch( suffix=suffix, rebuild=arguments.rebuild, - enable_page_by_chunking=arguments.enable_page_chunking, + enable_page_by_chunking=arguments.enable_page_wise_chunking, ) elif arguments.index_type == "text_2_sql_schema_store": index_config = Text2SqlSchemaStoreAISearch( @@ -65,7 +65,7 @@ def deploy_config(arguments: argparse.Namespace): help="Whether want to delete and rebuild the index", ) parser.add_argument( - "--enable_page_chunking", + "--enable_page_wise_chunking", type=bool, required=False, help="Whether want to enable chunking by page in adi skill, if no value is passed considered False", diff --git a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py index 9e8fe753..dcc3e2ba 100644 --- a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py +++ b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py @@ -243,8 +243,8 @@ def get_index_projections(self) -> SearchIndexerIndexProjection: source="/document/page_wise_layout/*/chunk_sections", ), InputFieldMappingEntry( - name="Figures", - source_context="/document/page_wise_layout/*/chunk_figures/*", + name="ChunkFigures", + source="/document/page_wise_layout/*/chunk_figures/*", ), InputFieldMappingEntry( name="DateLastModified", source="/document/DateLastModified" @@ -269,8 +269,8 @@ def get_index_projections(self) -> SearchIndexerIndexProjection: name="Sections", source="/document/chunk_mark_ups/*/chunk_sections" ), InputFieldMappingEntry( - name="Figures", - source_context="/document/chunk_mark_ups/*/chunk_figures/*", + name="ChunkFigures", + source="/document/chunk_mark_ups/*/chunk_figures/*", ), InputFieldMappingEntry( name="DateLastModified", source="/document/DateLastModified" diff --git a/image_processing/src/image_processing/requirements.txt b/image_processing/src/image_processing/requirements.txt index f0c790ae..1707fbc8 100644 --- a/image_processing/src/image_processing/requirements.txt +++ b/image_processing/src/image_processing/requirements.txt @@ -44,7 +44,7 @@ annotated-types==0.7.0 \ anyio==4.8.0 \ --hash=sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a \ --hash=sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a -appnope==0.1.4 ; sys_platform == 'darwin' \ +appnope==0.1.4 ; platform_system == 'Darwin' \ --hash=sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee \ --hash=sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c argon2-cffi==23.1.0 \ @@ -202,7 +202,7 @@ click==8.1.8 \ cloudpathlib==0.20.0 \ --hash=sha256:7af3bcefbf73392ae7f31c08b3660ec31607f8c01b7f6262d4d73469a845f641 \ --hash=sha256:f6ef7ca409a510f7ba4639ba50ab3fc5b6dee82d6dff0d7f5715fd0c9ab35891 -colorama==0.4.6 ; sys_platform == 'win32' \ +colorama==0.4.6 ; sys_platform == 'win32' or platform_system == 'Windows' \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 comm==0.2.2 \ @@ -277,9 +277,9 @@ en-core-web-md @ https://github.com/explosion/spacy-models/releases/download/en_ et-xmlfile==2.0.0 \ --hash=sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa \ --hash=sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54 -executing==2.1.0 \ - --hash=sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf \ - --hash=sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab +executing==2.2.0 \ + --hash=sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa \ + --hash=sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755 fastjsonschema==2.21.1 \ --hash=sha256:794d4f0a58f848961ba16af7b9c85a3e88cd360df008c59aac6fc5ae9323b5d4 \ --hash=sha256:c9e5b7e908310918cf494a434eeb31384dd84a98b57a30bcb1f535015b554667 @@ -616,9 +616,9 @@ numpy==1.26.4 \ oauthlib==3.2.2 \ --hash=sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca \ --hash=sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918 -openai==1.59.9 \ - --hash=sha256:61a0608a1313c08ddf92fe793b6dbd1630675a1fe3866b2f96447ce30050c448 \ - --hash=sha256:ec1a20b0351b4c3e65c6292db71d8233515437c6065efd4fd50edeb55df5f5d2 +openai==1.60.0 \ + --hash=sha256:7fa536cd4b644718645b874d2706e36dbbef38b327e42ca0623275da347ee1a9 \ + --hash=sha256:df06c43be8018274980ac363da07d4b417bd835ead1c66e14396f6f15a0d5dda openpyxl==3.1.5 \ --hash=sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2 \ --hash=sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050 @@ -829,7 +829,7 @@ python-json-logger==3.2.1 \ pytz==2024.2 \ --hash=sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a \ --hash=sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725 -pywin32==308 ; sys_platform == 'win32' \ +pywin32==308 ; (platform_python_implementation != 'PyPy' and sys_platform == 'win32') or platform_system == 'Windows' \ --hash=sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47 \ --hash=sha256:1c44539a37a5b7b21d02ab34e6a4d314e0788f1690d65b48e9b0b89f31abbbed \ --hash=sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897 \ @@ -895,9 +895,9 @@ pyzmq==26.2.0 \ --hash=sha256:ded0fc7d90fe93ae0b18059930086c51e640cdd3baebdc783a695c77f123dcd9 \ --hash=sha256:e3e0210287329272539eea617830a6a28161fbbd8a3271bf4150ae3e58c5d0e6 \ --hash=sha256:ea7f69de383cb47522c9c208aec6dd17697db7875a4674c4af3f8cfdac0bdeae -referencing==0.35.1 \ - --hash=sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c \ - --hash=sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de +referencing==0.36.1 \ + --hash=sha256:363d9c65f080d0d70bc41c721dce3c7f3e77fc09f269cd5c8813da18069a6794 \ + --hash=sha256:ca2e6492769e3602957e9b831b94211599d2aade9477f5d44110d2530cf9aade regex==2024.11.6 \ --hash=sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0 \ --hash=sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad \ diff --git a/text_2_sql/GETTING_STARTED.md b/text_2_sql/GETTING_STARTED.md index d6916406..2d54d35b 100644 --- a/text_2_sql/GETTING_STARTED.md +++ b/text_2_sql/GETTING_STARTED.md @@ -5,13 +5,13 @@ To get started, perform the following steps: **Execute the following commands in the `deploy_ai_search_indexes` directory:** 1. Setup Azure OpenAI in your subscription with **gpt-4o-mini** & an embedding model, alongside a SQL Server sample database, AI Search and a storage account. -2. Create your `.env` file based on the provided sample `deploy_ai_search_indexes/.env.example`. Place this file in the same place in `deploy_ai_search_indexes/.env`. -3. Clone this repository and deploy the AI Search text2sql indexes from `deploy_ai_search_indexes`. See the instructions in the **Steps for Text2SQL Index Deployment (For Structured RAG)** section of the `deploy_ai_search_indexes/README.md`. +2. Clone this repository and deploy the AI Search text2sql indexes from `deploy_ai_search_indexes`. See the instructions in the **Steps for Text2SQL Index Deployment (For Structured RAG)** section of the `deploy_ai_search_indexes/README.md`. +3. Create your `.env` file based on the provided sample `deploy_ai_search_indexes/.env.example`. Place this file in the same place in `deploy_ai_search_indexes/.env`. **Execute the following commands in the `text_2_sql_core` directory:** 4. Create your `.env` file based on the provided sample `text_2_sql/.env.example`. Place this file in the same place in `text_2_sql/.env`. -5. Run `uv sync` within the text_2_sql directory to install dependencies. +5. Run `uv sync` within the `text_2_sql_core` directory to install dependencies. - Install the optional dependencies if you need a database connector other than TSQL. `uv sync --extra ` - See the supported connectors in `text_2_sql_core/src/text_2_sql_core/connectors`. 6. Create your `.env` file based on the provided sample `text_2_sql/.env.example`. Place this file in the same place in `text_2_sql/.env`. @@ -20,7 +20,7 @@ To get started, perform the following steps: **Execute the following commands in the `autogen` directory:** -9. Run `uv sync` within the text_2_sql directory to install dependencies. +9. Run `uv sync` within the `autogen` directory to install dependencies. - Install the optional dependencies if you need a database connector other than TSQL. `uv sync --extra ` - See the supported connectors in `text_2_sql_core/src/text_2_sql_core/connectors`. 10. Navigate to `autogen` directory to view the AutoGen implementation. Follow the steps in `Iteration 5 - Agentic Vector Based Text2SQL.ipynb` to get started. diff --git a/uv.lock b/uv.lock index 7e91e4ba..d13ddff7 100644 --- a/uv.lock +++ b/uv.lock @@ -321,7 +321,6 @@ sqlite = [ [package.dev-dependencies] dev = [ - { name = "autogen-text-2-sql" }, { name = "black" }, { name = "ipykernel" }, { name = "jupyter" }, @@ -350,7 +349,6 @@ requires-dist = [ [package.metadata.requires-dev] dev = [ - { name = "autogen-text-2-sql" }, { name = "black", specifier = ">=24.10.0" }, { name = "ipykernel", specifier = ">=6.29.5" }, { name = "jupyter", specifier = ">=1.1.1" }, @@ -711,7 +709,7 @@ name = "click" version = "8.1.8" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "platform_system == 'Windows'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } wheels = [ @@ -816,7 +814,7 @@ wheels = [ [[package]] name = "databricks-sql-connector" -version = "3.7.1" +version = "4.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "lz4" }, @@ -824,14 +822,13 @@ dependencies = [ { name = "oauthlib" }, { name = "openpyxl" }, { name = "pandas" }, - { name = "pyarrow" }, { name = "requests" }, { name = "thrift" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/77/62/22db394c7d99d8a942fdc10c63f6e6fb6d9625664a4d67f176ad4a51b432/databricks_sql_connector-3.7.1.tar.gz", hash = "sha256:b0e48b2acc73b6ab4e63b1a8688f3e7e0eed538bebee67526960239f873b99ef", size = 414196 } +sdist = { url = "https://files.pythonhosted.org/packages/1d/9d/1ae930a513debad79a5fecf9542d1aaf1e37090025a0a29e1eb2a90dd550/databricks_sql_connector-4.0.0.tar.gz", hash = "sha256:3634fe3d19ee4641cdf76a77854573d9fe234ccdebd20230aaf94053397bc693", size = 315978 } wheels = [ - { url = "https://files.pythonhosted.org/packages/4e/a2/5a6215f0539176ef1fe3213631455d3a39f05c3820014ccba73540ca56cd/databricks_sql_connector-3.7.1-py3-none-any.whl", hash = "sha256:ffcb840f31246ce636a70374c89c5c22e7553225c64cada8ec8d90d377080266", size = 430721 }, + { url = "https://files.pythonhosted.org/packages/40/5f/9682d4ba3e46964c8934a2481fcd8a0740c276af0c765d027a9c1cf7af9c/databricks_sql_connector-4.0.0-py3-none-any.whl", hash = "sha256:798ebc740e992eaf435754510d1035872d3ebbc8c5cb597aa939217220463236", size = 324593 }, ] [[package]] @@ -998,7 +995,7 @@ source = { url = "https://github.com/explosion/spacy-models/releases/download/en dependencies = [ { name = "spacy" }, ] -sdist = { hash = "sha256:3273a1335fcb688be09949c5cdb73e85eb584ec3dfc50d4338c17daf6ccd4628" } +sdist = { url = "https://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.7.1/en_core_web_md-3.7.1.tar.gz", hash = "sha256:3273a1335fcb688be09949c5cdb73e85eb584ec3dfc50d4338c17daf6ccd4628" } [package.metadata] requires-dist = [{ name = "spacy", specifier = ">=3.7.2,<3.8.0" }] @@ -1014,11 +1011,11 @@ wheels = [ [[package]] name = "executing" -version = "2.1.0" +version = "2.2.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8c/e3/7d45f492c2c4a0e8e0fad57d081a7c8a0286cdd86372b070cca1ec0caa1e/executing-2.1.0.tar.gz", hash = "sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab", size = 977485 } +sdist = { url = "https://files.pythonhosted.org/packages/91/50/a9d80c47ff289c611ff12e63f7c5d13942c65d68125160cefd768c73e6e4/executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755", size = 978693 } wheels = [ - { url = "https://files.pythonhosted.org/packages/b5/fd/afcd0496feca3276f509df3dbd5dae726fcc756f1a08d9e25abe1733f962/executing-2.1.0-py2.py3-none-any.whl", hash = "sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf", size = 25805 }, + { url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702 }, ] [[package]] @@ -1293,7 +1290,7 @@ name = "ipykernel" version = "6.29.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "appnope", marker = "sys_platform == 'darwin'" }, + { name = "appnope", marker = "platform_system == 'Darwin'" }, { name = "comm" }, { name = "debugpy" }, { name = "ipython" }, @@ -2138,7 +2135,7 @@ wheels = [ [[package]] name = "openai" -version = "1.59.9" +version = "1.60.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -2150,9 +2147,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ec/2d/04faa92bac0341649223398503db4415d2f658a757d9d32bb68f3378ddd0/openai-1.59.9.tar.gz", hash = "sha256:ec1a20b0351b4c3e65c6292db71d8233515437c6065efd4fd50edeb55df5f5d2", size = 347134 } +sdist = { url = "https://files.pythonhosted.org/packages/d4/2d/9bdf4435d7669b4d027d6d69b4ac82f6be76153d9e90d3155d4224626a29/openai-1.60.0.tar.gz", hash = "sha256:7fa536cd4b644718645b874d2706e36dbbef38b327e42ca0623275da347ee1a9", size = 347844 } wheels = [ - { url = "https://files.pythonhosted.org/packages/07/b4/57f1954a4560092ad8c45f07ad183eab9c8e093e0a1db829f9b506b2d5d1/openai-1.59.9-py3-none-any.whl", hash = "sha256:61a0608a1313c08ddf92fe793b6dbd1630675a1fe3866b2f96447ce30050c448", size = 455527 }, + { url = "https://files.pythonhosted.org/packages/c0/53/782008d94f5f3141795e65bd7f87afaebb97e7516342299c1b1a08d5aaf8/openai-1.60.0-py3-none-any.whl", hash = "sha256:df06c43be8018274980ac363da07d4b417bd835ead1c66e14396f6f15a0d5dda", size = 456109 }, ] [[package]] @@ -2323,7 +2320,7 @@ name = "portalocker" version = "2.10.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "pywin32", marker = "platform_system == 'Windows'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ed/d3/c6c64067759e87af98cc668c1cc75171347d0f1577fab7ca3749134e3cd4/portalocker-2.10.1.tar.gz", hash = "sha256:ef1bf844e878ab08aee7e40184156e1151f228f103aa5c6bd0724cc330960f8f", size = 40891 } wheels = [ @@ -2769,15 +2766,16 @@ wheels = [ [[package]] name = "referencing" -version = "0.35.1" +version = "0.36.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "rpds-py" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/99/5b/73ca1f8e72fff6fa52119dbd185f73a907b1989428917b24cff660129b6d/referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c", size = 62991 } +sdist = { url = "https://files.pythonhosted.org/packages/27/32/fd98246df7a0f309b58cae68b10b6b219ef2eb66747f00dfb34422687087/referencing-0.36.1.tar.gz", hash = "sha256:ca2e6492769e3602957e9b831b94211599d2aade9477f5d44110d2530cf9aade", size = 74661 } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/59/2056f61236782a2c86b33906c025d4f4a0b17be0161b63b70fd9e8775d36/referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de", size = 26684 }, + { url = "https://files.pythonhosted.org/packages/cc/fa/9f193ef0c9074b659009f06d7cbacc6f25b072044815bcf799b76533dbb8/referencing-0.36.1-py3-none-any.whl", hash = "sha256:363d9c65f080d0d70bc41c721dce3c7f3e77fc09f269cd5c8813da18069a6794", size = 26777 }, ] [[package]] @@ -3472,7 +3470,7 @@ name = "tqdm" version = "4.67.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "platform_system == 'Windows'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737 } wheels = [ From e0005696530f304378d895f26f691465b615a278 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 19:33:24 +0000 Subject: [PATCH 38/64] Update --- .../src/deploy_ai_search_indexes/environment.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/environment.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/environment.py index 0fc1f332..ad39d1ef 100644 --- a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/environment.py +++ b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/environment.py @@ -222,8 +222,7 @@ def use_private_endpoint(self) -> bool: This function returns true if private endpoint is used """ return ( - os.environ.get( - "AIService__AzureSearchOptions__UsePrivateEndpoint").lower() + os.environ.get("AIService__AzureSearchOptions__UsePrivateEndpoint").lower() == "true" ) @@ -232,8 +231,6 @@ def get_custom_skill_function_url(self, skill_type: str): Get the function app url that is hosting the custom skill """ - full_url = ( - f"{self.function_app_end_point}/api/{skill_type}?code={self.function_app_key}" - ) + full_url = f"{self.function_app_end_point}/api/{skill_type}?code={self.function_app_key}" return full_url From f270a57857894e57bdc0e0f57780017876b7c4e0 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 19:36:31 +0000 Subject: [PATCH 39/64] Update func ignore --- .funcignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.funcignore b/.funcignore index f1110d33..6fd5d88e 100644 --- a/.funcignore +++ b/.funcignore @@ -6,3 +6,10 @@ __queuestorage__ local.settings.json test .venv +.github/* +.devcontainer/* +.ruff_cache/* +deploy_ai_search_indexes/* +text_2_sql/* +documentation/* +images/ From 8c463642375cffa7813471185cbc4d212336dc44 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 19:47:17 +0000 Subject: [PATCH 40/64] Update settings --- .pre-commit-config.yaml | 12 ++++++------ .vscode/settings.json | 1 + .vscode/tasks.json | 2 +- pyproject.toml | 7 +++++++ uv.lock | 12 ++++++++++++ 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8e4cef5b..651afd39 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -45,12 +45,12 @@ repos: args: [--fix, --ignore, UP007] exclude: samples - # - repo: https://github.com/astral-sh/uv-pre-commit - # # uv version. - # rev: 0.5.20 - # hooks: - # # Update the uv lockfile - # - id: uv-lock + - repo: https://github.com/astral-sh/uv-pre-commit + # uv version. + rev: 0.5.20 + hooks: + # Update the uv lockfile + - id: uv-lock - repo: local hooks: diff --git a/.vscode/settings.json b/.vscode/settings.json index 4d62d59b..3156ab10 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { + "azureFunctions.deploySubpath": "/image_processing/src/image_processing", "azureFunctions.projectLanguage": "Python", "azureFunctions.projectLanguageModel": 2, "azureFunctions.projectRuntime": "~4", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index dd3b781a..f0890c38 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -5,7 +5,7 @@ "isBackground": true, "label": "func: host start", "options": { - "cwd": "${workspaceFolder}/ai_search_with_image_processing" + "cwd": "${workspaceFolder}/image_processing/src/image_processing" }, "problemMatcher": "$func-python-watch", "type": "func" diff --git a/pyproject.toml b/pyproject.toml index 6c09b4f4..5bd2d5ce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,10 @@ description = "This repo accelerates development of RAG applications with rich d readme = "README.md" requires-python = ">=3.12" dependencies = [ + "deploy_ai_search_indexes", + "image_processing", + "text_2_sql_core", + "autogen_text_2_sql", ] [dependency-groups] @@ -23,3 +27,6 @@ members = ["text_2_sql/text_2_sql_core", "text_2_sql/autogen", "deploy_ai_search [tool.uv.sources] text_2_sql_core = { workspace = true } +autogen_text_2_sql = { workspace = true } +deploy_ai_search_indexes = { workspace = true } +image_processing = { workspace = true } diff --git a/uv.lock b/uv.lock index d13ddff7..d25e1ea5 100644 --- a/uv.lock +++ b/uv.lock @@ -963,6 +963,12 @@ wheels = [ name = "dstoolkit-text2sql-and-imageprocessing" version = "0.1.0" source = { virtual = "." } +dependencies = [ + { name = "autogen-text-2-sql" }, + { name = "deploy-ai-search-indexes" }, + { name = "image-processing" }, + { name = "text-2-sql-core" }, +] [package.dev-dependencies] dev = [ @@ -976,6 +982,12 @@ dev = [ ] [package.metadata] +requires-dist = [ + { name = "autogen-text-2-sql", virtual = "text_2_sql/autogen" }, + { name = "deploy-ai-search-indexes", virtual = "deploy_ai_search_indexes" }, + { name = "image-processing", virtual = "image_processing" }, + { name = "text-2-sql-core", editable = "text_2_sql/text_2_sql_core" }, +] [package.metadata.requires-dev] dev = [ From 4a2bf999a3c21d1f2084213644acadc5a2c38269 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 19:56:46 +0000 Subject: [PATCH 41/64] Update requirements --- .pre-commit-config.yaml | 2 +- .../src/image_processing/local.settings.json | 3 + .../src/image_processing/requirements.txt | 1442 +++-------------- 3 files changed, 194 insertions(+), 1253 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 651afd39..7c94bb18 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -57,5 +57,5 @@ repos: - id: compile-image-processing-requirements name: compile-image-processing-requirements language: system - entry: bash -c 'cd image_processing && exec uv export --all-extras > src/image_processing/requirements.txt' + entry: bash -c 'cd image_processing && exec uv export --all-extras --frozen --no-hashes > src/image_processing/requirements.txt' pass_filenames: false diff --git a/image_processing/src/image_processing/local.settings.json b/image_processing/src/image_processing/local.settings.json index 0c7e1812..08ab8000 100644 --- a/image_processing/src/image_processing/local.settings.json +++ b/image_processing/src/image_processing/local.settings.json @@ -2,10 +2,13 @@ "IsEncrypted": false, "Values": { "AIService__DocumentIntelligence__Endpoint": "", + "AzureWebJobsStorage": "UseDevelopmentStorage=true", + "FUNCTIONS_WORKER_RUNTIME": "python", "OpenAI__ApiKey": "", "OpenAI__ApiVersion": "", "OpenAI__CompletionDeployment": "", "OpenAI__Endpoint": "", + "SCM_DO_BUILD_DURING_DEPLOYMENT": "true", "StorageAccount__Name": "" } } diff --git a/image_processing/src/image_processing/requirements.txt b/image_processing/src/image_processing/requirements.txt index 1707fbc8..33079beb 100644 --- a/image_processing/src/image_processing/requirements.txt +++ b/image_processing/src/image_processing/requirements.txt @@ -1,1253 +1,191 @@ # This file was autogenerated by uv via the following command: -# uv export --all-extras -aiohappyeyeballs==2.4.4 \ - --hash=sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745 \ - --hash=sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8 -aiohttp==3.11.11 \ - --hash=sha256:0882c2820fd0132240edbb4a51eb8ceb6eef8181db9ad5291ab3332e0d71df5f \ - --hash=sha256:0b7fb429ab1aafa1f48578eb315ca45bd46e9c37de11fe45c7f5f4138091e2f1 \ - --hash=sha256:1e69966ea6ef0c14ee53ef7a3d68b564cc408121ea56c0caa2dc918c1b2f553d \ - --hash=sha256:3499c7ffbfd9c6a3d8d6a2b01c26639da7e43d47c7b4f788016226b1e711caa8 \ - --hash=sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2 \ - --hash=sha256:541d823548ab69d13d23730a06f97460f4238ad2e5ed966aaf850d7c369782d9 \ - --hash=sha256:620598717fce1b3bd14dd09947ea53e1ad510317c85dda2c9c65b622edc96b12 \ - --hash=sha256:6fba278063559acc730abf49845d0e9a9e1ba74f85f0ee6efd5803f08b285853 \ - --hash=sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c \ - --hash=sha256:8e2bf8029dbf0810c7bfbc3e594b51c4cc9101fbffb583a3923aea184724203c \ - --hash=sha256:929f3ed33743a49ab127c58c3e0a827de0664bfcda566108989a14068f820194 \ - --hash=sha256:92fc484e34b733704ad77210c7957679c5c3877bd1e6b6d74b185e9320cc716e \ - --hash=sha256:9d73ee3725b7a737ad86c2eac5c57a4a97793d9f442599bea5ec67ac9f4bdc3d \ - --hash=sha256:9f5b3c1ed63c8fa937a920b6c1bec78b74ee09593b3f5b979ab2ae5ef60d7600 \ - --hash=sha256:a344d5dc18074e3872777b62f5f7d584ae4344cd6006c17ba12103759d407af3 \ - --hash=sha256:a8f5f7515f3552d899c61202d99dcb17d6e3b0de777900405611cd747cecd1b8 \ - --hash=sha256:a9b7371665d4f00deb8f32208c7c5e652059b0fda41cf6dbcac6114a041f1cc2 \ - --hash=sha256:aa54f8ef31d23c506910c21163f22b124facb573bff73930735cf9fe38bf7dff \ - --hash=sha256:b6212a60e5c482ef90f2d788835387070a88d52cf6241d3916733c9176d39eab \ - --hash=sha256:b63de12e44935d5aca7ed7ed98a255a11e5cb47f83a9fded7a5e41c40277d104 \ - --hash=sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e \ - --hash=sha256:bd7227b87a355ce1f4bf83bfae4399b1f5bb42e0259cb9405824bd03d2f4336a \ - --hash=sha256:bf8d9bfee991d8acc72d060d53860f356e07a50f0e0d09a8dfedea1c554dd0d5 \ - --hash=sha256:c341c7d868750e31961d6d8e60ff040fb9d3d3a46d77fd85e1ab8e76c3e9a5c4 \ - --hash=sha256:c7a06301c2fb096bdb0bd25fe2011531c1453b9f2c163c8031600ec73af1cc99 \ - --hash=sha256:d119fafe7b634dbfa25a8c597718e69a930e4847f0b88e172744be24515140da \ - --hash=sha256:d40f9da8cabbf295d3a9dae1295c69975b86d941bc20f0a087f0477fa0a66231 \ - --hash=sha256:de8d38f1c2810fa2a4f1d995a2e9c70bb8737b18da04ac2afbf3971f65781d87 \ - --hash=sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886 \ - --hash=sha256:ed9ee95614a71e87f1a70bc81603f6c6760128b140bc4030abe6abaa988f1c3d \ - --hash=sha256:ffb3dc385f6bb1568aa974fe65da84723210e5d9707e360e9ecb51f59406cd2e -aiosignal==1.3.2 \ - --hash=sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5 \ - --hash=sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54 -annotated-types==0.7.0 \ - --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ - --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 -anyio==4.8.0 \ - --hash=sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a \ - --hash=sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a -appnope==0.1.4 ; platform_system == 'Darwin' \ - --hash=sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee \ - --hash=sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c -argon2-cffi==23.1.0 \ - --hash=sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08 \ - --hash=sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea -argon2-cffi-bindings==21.2.0 \ - --hash=sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c \ - --hash=sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082 \ - --hash=sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f \ - --hash=sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d \ - --hash=sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f \ - --hash=sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae \ - --hash=sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3 \ - --hash=sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86 \ - --hash=sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367 \ - --hash=sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93 \ - --hash=sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e -arrow==1.3.0 \ - --hash=sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80 \ - --hash=sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85 -asttokens==3.0.0 \ - --hash=sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7 \ - --hash=sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2 -async-lru==2.0.4 \ - --hash=sha256:b8a59a5df60805ff63220b2a0c5b5393da5521b113cd5465a44eb037d81a5627 \ - --hash=sha256:ff02944ce3c288c5be660c42dbcca0742b32c3b279d6dceda655190240b99224 -attrs==24.3.0 \ - --hash=sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff \ - --hash=sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308 -azure-ai-documentintelligence==1.0.0 \ - --hash=sha256:c8b6efc0fc7e65d7892c9585cfd256f7d8b3f2b46cecf92c75ab82e629eac253 \ - --hash=sha256:cdedb1a67c075f58f47a413ec5846bf8d532a83a71f0c51ec49ce9b5bfe2a519 -azure-ai-textanalytics==5.3.0 \ - --hash=sha256:4f7d067d5bb08422599ca6175510d39b0911c711301647e5f18e904a5027bf58 \ - --hash=sha256:69bb736d93de81060e9075d42b6f0b92c25be0fb106da5cb6a6d30e772168221 -azure-ai-vision-imageanalysis==1.0.0 \ - --hash=sha256:9a7e4aed611d8b4b5fbe528e4e56257d3543b26affe98914f5fd2c53381c264d \ - --hash=sha256:a79bbbb9c6992fef3be53395d339c9db850719583ef96ac64e054b00b545b3b6 -azure-common==1.1.28 \ - --hash=sha256:4ac0cd3214e36b6a1b6a442686722a5d8cc449603aa833f3f0f40bda836704a3 \ - --hash=sha256:5c12d3dcf4ec20599ca6b0d3e09e86e146353d443e7fcc050c9a19c1f9df20ad -azure-core==1.32.0 \ - --hash=sha256:22b3c35d6b2dae14990f6c1be2912bf23ffe50b220e708a28ab1bb92b1c730e5 \ - --hash=sha256:eac191a0efb23bfa83fddf321b27b122b4ec847befa3091fa736a5c32c50d7b4 -azure-functions==1.21.3 \ - --hash=sha256:6c45f5e61fe59328c81928a428d43c838e9ead52f1cde1628fcabb372fa10cc8 \ - --hash=sha256:c359b9dbd2998c84d8595e31a28ffad4e8ca8dcfb4a3798327f776a67f964351 -azure-identity==1.19.0 \ - --hash=sha256:500144dc18197d7019b81501165d4fa92225f03778f17d7ca8a2a180129a9c83 \ - --hash=sha256:e3f6558c181692d7509f09de10cca527c7dce426776454fb97df512a46527e81 -azure-search==1.0.0b2 \ - --hash=sha256:49cbb1937b2e256f6631d467f62f8a1c94a14c5fed84f6625d24bc7b210a25d4 \ - --hash=sha256:ba3974224be1329d26e58e63df9c8561b416e7536b79a1c5576055dfb6c472ae -azure-search-documents==11.6.0b8 \ - --hash=sha256:5fa84bacbf72b9778ab7a2a43ab5df335fc5516eeb169c36d78ced39a29cfe69 \ - --hash=sha256:edd7af876dc9353d1ede46429547df0a3891beed182308636f0f86a97cce94b5 -azure-storage-blob==12.24.0 \ - --hash=sha256:4f0bb4592ea79a2d986063696514c781c9e62be240f09f6397986e01755bc071 \ - --hash=sha256:eaaaa1507c8c363d6e1d1342bd549938fdf1adec9b1ada8658c8f5bf3aea844e -babel==2.16.0 \ - --hash=sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b \ - --hash=sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316 -beautifulsoup4==4.12.3 \ - --hash=sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051 \ - --hash=sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed -black==24.10.0 \ - --hash=sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f \ - --hash=sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981 \ - --hash=sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b \ - --hash=sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8 \ - --hash=sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d \ - --hash=sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b \ - --hash=sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875 \ - --hash=sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3 \ - --hash=sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65 \ - --hash=sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2 -bleach==6.2.0 \ - --hash=sha256:117d9c6097a7c3d22fd578fcd8d35ff1e125df6736f554da4e432fdd63f31e5e \ - --hash=sha256:123e894118b8a599fd80d3ec1a6d4cc7ce4e5882b1317a7e1ba69b56e95f991f -blis==0.7.11 \ - --hash=sha256:5a305dbfc96d202a20d0edd6edf74a406b7e1404f4fa4397d24c68454e60b1b4 \ - --hash=sha256:5bcdaf370f03adaf4171d6405a89fa66cb3c09399d75fc02e1230a78cd2759e4 \ - --hash=sha256:7de19264b1d49a178bf8035406d0ae77831f3bfaa3ce02942964a81a202abb03 \ - --hash=sha256:8ea55c6a4a60fcbf6a0fdce40df6e254451ce636988323a34b9c94b583fc11e5 \ - --hash=sha256:cec6d48f75f7ac328ae1b6fbb372dde8c8a57c89559172277f66e01ff08d4d42 \ - --hash=sha256:dadf8713ea51d91444d14ad4104a5493fa7ecc401bbb5f4a203ff6448fadb113 -bs4==0.0.2 \ - --hash=sha256:a48685c58f50fe127722417bae83fe6badf500d54b55f7e39ffe43b798653925 \ - --hash=sha256:abf8742c0805ef7f662dce4b51cca104cffe52b835238afc169142ab9b3fbccc -catalogue==2.0.10 \ - --hash=sha256:4f56daa940913d3f09d589c191c74e5a6d51762b3a9e37dd53b7437afd6cda15 \ - --hash=sha256:58c2de0020aa90f4a2da7dfad161bf7b3b054c86a5f09fcedc0b2b740c109a9f -certifi==2024.12.14 \ - --hash=sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56 \ - --hash=sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db -cffi==1.17.1 \ - --hash=sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2 \ - --hash=sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36 \ - --hash=sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824 \ - --hash=sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3 \ - --hash=sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed \ - --hash=sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8 \ - --hash=sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903 \ - --hash=sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683 \ - --hash=sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9 \ - --hash=sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c \ - --hash=sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4 \ - --hash=sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65 \ - --hash=sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93 \ - --hash=sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4 \ - --hash=sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3 \ - --hash=sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff \ - --hash=sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5 \ - --hash=sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd \ - --hash=sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5 \ - --hash=sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d \ - --hash=sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e \ - --hash=sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a \ - --hash=sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99 -cfgv==3.4.0 \ - --hash=sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9 \ - --hash=sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560 -charset-normalizer==3.4.1 \ - --hash=sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd \ - --hash=sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601 \ - --hash=sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d \ - --hash=sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313 \ - --hash=sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa \ - --hash=sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2 \ - --hash=sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b \ - --hash=sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3 \ - --hash=sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f \ - --hash=sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9 \ - --hash=sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f \ - --hash=sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545 \ - --hash=sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b \ - --hash=sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9 \ - --hash=sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11 \ - --hash=sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35 \ - --hash=sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda \ - --hash=sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971 \ - --hash=sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d \ - --hash=sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757 \ - --hash=sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a \ - --hash=sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886 \ - --hash=sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85 \ - --hash=sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7 \ - --hash=sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1 \ - --hash=sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407 \ - --hash=sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd \ - --hash=sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616 -click==8.1.8 \ - --hash=sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2 \ - --hash=sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a -cloudpathlib==0.20.0 \ - --hash=sha256:7af3bcefbf73392ae7f31c08b3660ec31607f8c01b7f6262d4d73469a845f641 \ - --hash=sha256:f6ef7ca409a510f7ba4639ba50ab3fc5b6dee82d6dff0d7f5715fd0c9ab35891 -colorama==0.4.6 ; sys_platform == 'win32' or platform_system == 'Windows' \ - --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ - --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 -comm==0.2.2 \ - --hash=sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e \ - --hash=sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3 -confection==0.1.5 \ - --hash=sha256:8e72dd3ca6bd4f48913cd220f10b8275978e740411654b6e8ca6d7008c590f0e \ - --hash=sha256:e29d3c3f8eac06b3f77eb9dfb4bf2fc6bcc9622a98ca00a698e3d019c6430b14 -cryptography==44.0.0 \ - --hash=sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7 \ - --hash=sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b \ - --hash=sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc \ - --hash=sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543 \ - --hash=sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591 \ - --hash=sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede \ - --hash=sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb \ - --hash=sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f \ - --hash=sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123 \ - --hash=sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c \ - --hash=sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285 \ - --hash=sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd \ - --hash=sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092 \ - --hash=sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289 \ - --hash=sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02 \ - --hash=sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64 \ - --hash=sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053 \ - --hash=sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417 \ - --hash=sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e \ - --hash=sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e \ - --hash=sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7 -cymem==2.0.11 \ - --hash=sha256:02ed92bead896cca36abad00502b14fa651bdf5d8319461126a2d5ac8c9674c5 \ - --hash=sha256:04ee6b4041ddec24512d6e969ed6445e57917f01e73b9dabbe17b7e6b27fef05 \ - --hash=sha256:0c269c7a867d74adeb9db65fa1d226342aacf44d64b7931282f0b0eb22eb6275 \ - --hash=sha256:25da111adf425c29af0cfd9fecfec1c71c8d82e2244a85166830a0817a66ada7 \ - --hash=sha256:44ddd3588379f8f376116384af99e3fb5f90091d90f520c341942618bf22f05e \ - --hash=sha256:5461e65340d6572eb64deadce79242a446a1d39cb7bf70fe7b7e007eb0d799b0 \ - --hash=sha256:5b02f2b17d760dc3fe5812737b1ce4f684641cdd751d67761d333a3b5ea97b83 \ - --hash=sha256:87ec985623624bbd298762d8163fc194a096cb13282731a017e09ff8a60bb8b1 \ - --hash=sha256:a0fbe19ce653cd688842d81e5819dc63f911a26e192ef30b0b89f0ab2b192ff2 \ - --hash=sha256:bee4395917f6588b8ac1699499128842768b391fe8896e8626950b4da5f9a406 \ - --hash=sha256:de72101dc0e6326f6a2f73e05a438d1f3c6110d41044236d0fbe62925091267d \ - --hash=sha256:e1048dae7e627ee25f22c87bb670b13e06bc0aecc114b89b959a798d487d1bf4 \ - --hash=sha256:e3385a47285435848e0ed66cfd29b35f3ed8703218e2b17bd7a0c053822f26bf \ - --hash=sha256:efe49a349d4a518be6b6c6b255d4a80f740a341544bde1a807707c058b88d0bd \ - --hash=sha256:f4a311c82f743275c84f708df89ac5bf60ddefe4713d532000c887931e22941f -debugpy==1.8.12 \ - --hash=sha256:086b32e233e89a2740c1615c2f775c34ae951508b28b308681dbbb87bba97d06 \ - --hash=sha256:22a11c493c70413a01ed03f01c3c3a2fc4478fc6ee186e340487b2edcd6f4180 \ - --hash=sha256:274b6a2040349b5c9864e475284bce5bb062e63dce368a394b8cc865ae3b00c6 \ - --hash=sha256:2ae5df899732a6051b49ea2632a9ea67f929604fd2b036613a9f12bc3163b92d \ - --hash=sha256:39dfbb6fa09f12fae32639e3286112fc35ae976114f1f3d37375f3130a820969 \ - --hash=sha256:646530b04f45c830ceae8e491ca1c9320a2d2f0efea3141487c82130aba70dce \ - --hash=sha256:696d8ae4dff4cbd06bf6b10d671e088b66669f110c7c4e18a44c43cf75ce966f \ - --hash=sha256:7e94b643b19e8feb5215fa508aee531387494bf668b2eca27fa769ea11d9f498 \ - --hash=sha256:898fba72b81a654e74412a67c7e0a81e89723cfe2a3ea6fcd3feaa3395138ca9 \ - --hash=sha256:fdb3c6d342825ea10b90e43d7f20f01535a72b3a1997850c0c3cefa5c27a4a2c -decorator==5.1.1 \ - --hash=sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330 \ - --hash=sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186 -defusedxml==0.7.1 \ - --hash=sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69 \ - --hash=sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61 -distlib==0.3.9 \ - --hash=sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87 \ - --hash=sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403 -distro==1.9.0 \ - --hash=sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed \ - --hash=sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2 -en-core-web-md @ https://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.7.1/en_core_web_md-3.7.1.tar.gz \ - --hash=sha256:3273a1335fcb688be09949c5cdb73e85eb584ec3dfc50d4338c17daf6ccd4628 -et-xmlfile==2.0.0 \ - --hash=sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa \ - --hash=sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54 -executing==2.2.0 \ - --hash=sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa \ - --hash=sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755 -fastjsonschema==2.21.1 \ - --hash=sha256:794d4f0a58f848961ba16af7b9c85a3e88cd360df008c59aac6fc5ae9323b5d4 \ - --hash=sha256:c9e5b7e908310918cf494a434eeb31384dd84a98b57a30bcb1f535015b554667 -filelock==3.17.0 \ - --hash=sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338 \ - --hash=sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e -fqdn==1.5.1 \ - --hash=sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f \ - --hash=sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014 -frozenlist==1.5.0 \ - --hash=sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e \ - --hash=sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28 \ - --hash=sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b \ - --hash=sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9 \ - --hash=sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2 \ - --hash=sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8 \ - --hash=sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6 \ - --hash=sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21 \ - --hash=sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c \ - --hash=sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608 \ - --hash=sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de \ - --hash=sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f \ - --hash=sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641 \ - --hash=sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9 \ - --hash=sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f \ - --hash=sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a \ - --hash=sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784 \ - --hash=sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d \ - --hash=sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03 \ - --hash=sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e \ - --hash=sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953 \ - --hash=sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee \ - --hash=sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817 \ - --hash=sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039 \ - --hash=sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f \ - --hash=sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439 \ - --hash=sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631 \ - --hash=sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840 \ - --hash=sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3 \ - --hash=sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0 \ - --hash=sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e \ - --hash=sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a -fsspec==2024.12.0 \ - --hash=sha256:670700c977ed2fb51e0d9f9253177ed20cbde4a3e5c0283cc5385b5870c8533f \ - --hash=sha256:b520aed47ad9804237ff878b504267a3b0b441e97508bd6d2d8774e3db85cee2 -h11==0.14.0 \ - --hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \ - --hash=sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761 -httpcore==1.0.7 \ - --hash=sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c \ - --hash=sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd -httpx==0.28.1 \ - --hash=sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc \ - --hash=sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad -huggingface-hub==0.27.1 \ - --hash=sha256:1c5155ca7d60b60c2e2fc38cbb3ffb7f7c3adf48f824015b219af9061771daec \ - --hash=sha256:c004463ca870283909d715d20f066ebd6968c2207dae9393fdffb3c1d4d8f98b -identify==2.6.6 \ - --hash=sha256:7bec12768ed44ea4761efb47806f0a41f86e7c0a5fdf5950d4648c90eca7e251 \ - --hash=sha256:cbd1810bce79f8b671ecb20f53ee0ae8e86ae84b557de31d89709dc2a48ba881 -idna==3.10 \ - --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \ - --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3 -ipykernel==6.29.5 \ - --hash=sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5 \ - --hash=sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215 -ipython==8.31.0 \ - --hash=sha256:46ec58f8d3d076a61d128fe517a51eb730e3aaf0c184ea8c17d16e366660c6a6 \ - --hash=sha256:b6a2274606bec6166405ff05e54932ed6e5cfecaca1fc05f2cacde7bb074d70b -ipywidgets==8.1.5 \ - --hash=sha256:3290f526f87ae6e77655555baba4f36681c555b8bdbbff430b70e52c34c86245 \ - --hash=sha256:870e43b1a35656a80c18c9503bbf2d16802db1cb487eec6fab27d683381dde17 -isodate==0.7.2 \ - --hash=sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15 \ - --hash=sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6 -isoduration==20.11.0 \ - --hash=sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9 \ - --hash=sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042 -jedi==0.19.2 \ - --hash=sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0 \ - --hash=sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9 -jinja2==3.1.5 \ - --hash=sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb \ - --hash=sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb -jiter==0.8.2 \ - --hash=sha256:025337859077b41548bdcbabe38698bcd93cfe10b06ff66617a48ff92c9aec60 \ - --hash=sha256:14601dcac4889e0a1c75ccf6a0e4baf70dbc75041e51bcf8d0e9274519df6887 \ - --hash=sha256:180a8aea058f7535d1c84183c0362c710f4750bef66630c05f40c93c2b152a0f \ - --hash=sha256:37b2998606d6dadbb5ccda959a33d6a5e853252d921fec1792fc902351bb4e2c \ - --hash=sha256:3ac9f578c46f22405ff7f8b1f5848fb753cc4b8377fbec8470a7dc3997ca7566 \ - --hash=sha256:4ab9a87f3784eb0e098f84a32670cfe4a79cb6512fd8f42ae3d0709f06405d18 \ - --hash=sha256:5672a86d55416ccd214c778efccf3266b84f87b89063b582167d803246354be4 \ - --hash=sha256:58dc9bc9767a1101f4e5e22db1b652161a225874d66f0e5cb8e2c7d1c438b587 \ - --hash=sha256:653cf462db4e8c41995e33d865965e79641ef45369d8a11f54cd30888b7e6ff1 \ - --hash=sha256:711e408732d4e9a0208008e5892c2966b485c783cd2d9a681f3eb147cf36c7ef \ - --hash=sha256:76e324da7b5da060287c54f2fabd3db5f76468006c811831f051942bf68c9d44 \ - --hash=sha256:789361ed945d8d42850f919342a8665d2dc79e7e44ca1c97cc786966a21f627a \ - --hash=sha256:79aec8172b9e3c6d05fd4b219d5de1ac616bd8da934107325a6c0d0e866a21b6 \ - --hash=sha256:7efe4853ecd3d6110301665a5178b9856be7e2a9485f49d91aa4d737ad2ae49e \ - --hash=sha256:83c0efd80b29695058d0fd2fa8a556490dbce9804eac3e281f373bbc99045f6c \ - --hash=sha256:92249669925bc1c54fcd2ec73f70f2c1d6a817928480ee1c65af5f6b81cdf12d \ - --hash=sha256:9c63eaef32b7bebac8ebebf4dabebdbc6769a09c127294db6babee38e9f405b9 \ - --hash=sha256:ab7f43235d71e03b941c1630f4b6e3055d46b6cb8728a17663eaac9d8e83a865 \ - --hash=sha256:b2dd880785088ff2ad21ffee205e58a8c1ddabc63612444ae41e5e4b321b39c0 \ - --hash=sha256:b426f72cd77da3fec300ed3bc990895e2dd6b49e3bfe6c438592a3ba660e41ca \ - --hash=sha256:bf55846c7b7a680eebaf9c3c48d630e1bf51bdf76c68a5f654b8524335b0ad29 \ - --hash=sha256:ca1f08b8e43dc3bd0594c992fb1fd2f7ce87f7bf0d44358198d6da8034afdf84 \ - --hash=sha256:cd73d3e740666d0e639f678adb176fad25c1bcbdae88d8d7b857e1783bb4212d \ - --hash=sha256:e6ec2be506e7d6f9527dae9ff4b7f54e68ea44a0ef6b098256ddf895218a2f8f \ - --hash=sha256:e725edd0929fa79f8349ab4ec7f81c714df51dc4e991539a578e5018fa4a7152 \ - --hash=sha256:eb21aaa9a200d0a80dacc7a81038d2e476ffe473ffdd9c91eb745d623561de05 \ - --hash=sha256:ecff0dc14f409599bbcafa7e470c00b80f17abc14d1405d38ab02e4b42e55b57 \ - --hash=sha256:ffd9fee7d0775ebaba131f7ca2e2d83839a62ad65e8e02fe2bd8fc975cedeb9e -joblib==1.4.2 \ - --hash=sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6 \ - --hash=sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e -json5==0.10.0 \ - --hash=sha256:19b23410220a7271e8377f81ba8aacba2fdd56947fbb137ee5977cbe1f5e8dfa \ - --hash=sha256:e66941c8f0a02026943c52c2eb34ebeb2a6f819a0be05920a6f5243cd30fd559 -jsonpointer==3.0.0 \ - --hash=sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942 \ - --hash=sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef -jsonschema==4.23.0 \ - --hash=sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4 \ - --hash=sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566 -jsonschema-specifications==2024.10.1 \ - --hash=sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272 \ - --hash=sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf -jupyter==1.1.1 \ - --hash=sha256:7a59533c22af65439b24bbe60373a4e95af8f16ac65a6c00820ad378e3f7cc83 \ - --hash=sha256:d55467bceabdea49d7e3624af7e33d59c37fff53ed3a350e1ac957bed731de7a -jupyter-client==8.6.3 \ - --hash=sha256:35b3a0947c4a6e9d589eb97d7d4cd5e90f910ee73101611f01283732bd6d9419 \ - --hash=sha256:e8a19cc986cc45905ac3362915f410f3af85424b4c0905e94fa5f2cb08e8f23f -jupyter-console==6.6.3 \ - --hash=sha256:309d33409fcc92ffdad25f0bcdf9a4a9daa61b6f341177570fdac03de5352485 \ - --hash=sha256:566a4bf31c87adbfadf22cdf846e3069b59a71ed5da71d6ba4d8aaad14a53539 -jupyter-core==5.7.2 \ - --hash=sha256:4f7315d2f6b4bcf2e3e7cb6e46772eba760ae459cd1f59d29eb57b0a01bd7409 \ - --hash=sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9 -jupyter-events==0.11.0 \ - --hash=sha256:36399b41ce1ca45fe8b8271067d6a140ffa54cec4028e95491c93b78a855cacf \ - --hash=sha256:c0bc56a37aac29c1fbc3bcfbddb8c8c49533f9cf11f1c4e6adadba936574ab90 -jupyter-lsp==2.2.5 \ - --hash=sha256:45fbddbd505f3fbfb0b6cb2f1bc5e15e83ab7c79cd6e89416b248cb3c00c11da \ - --hash=sha256:793147a05ad446f809fd53ef1cd19a9f5256fd0a2d6b7ce943a982cb4f545001 -jupyter-server==2.15.0 \ - --hash=sha256:872d989becf83517012ee669f09604aa4a28097c0bd90b2f424310156c2cdae3 \ - --hash=sha256:9d446b8697b4f7337a1b7cdcac40778babdd93ba614b6d68ab1c0c918f1c4084 -jupyter-server-terminals==0.5.3 \ - --hash=sha256:41ee0d7dc0ebf2809c668e0fc726dfaf258fcd3e769568996ca731b6194ae9aa \ - --hash=sha256:5ae0295167220e9ace0edcfdb212afd2b01ee8d179fe6f23c899590e9b8a5269 -jupyterlab==4.3.4 \ - --hash=sha256:b754c2601c5be6adf87cb5a1d8495d653ffb945f021939f77776acaa94dae952 \ - --hash=sha256:f0bb9b09a04766e3423cccc2fc23169aa2ffedcdf8713e9e0fb33cac0b6859d0 -jupyterlab-pygments==0.3.0 \ - --hash=sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d \ - --hash=sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780 -jupyterlab-server==2.27.3 \ - --hash=sha256:e697488f66c3db49df675158a77b3b017520d772c6e1548c7d9bcc5df7944ee4 \ - --hash=sha256:eb36caca59e74471988f0ae25c77945610b887f777255aa21f8065def9e51ed4 -jupyterlab-widgets==3.0.13 \ - --hash=sha256:a2966d385328c1942b683a8cd96b89b8dd82c8b8f81dda902bb2bc06d46f5bed \ - --hash=sha256:e3cda2c233ce144192f1e29914ad522b2f4c40e77214b0cc97377ca3d323db54 -langcodes==3.5.0 \ - --hash=sha256:1eef8168d07e51e131a2497ffecad4b663f6208e7c3ae3b8dc15c51734a6f801 \ - --hash=sha256:853c69d1a35e0e13da2f427bb68fb2fa4a8f4fb899e0c62ad8df8d073dcfed33 -language-data==1.3.0 \ - --hash=sha256:7600ef8aa39555145d06c89f0c324bf7dab834ea0b0a439d8243762e3ebad7ec \ - --hash=sha256:e2ee943551b5ae5f89cd0e801d1fc3835bb0ef5b7e9c3a4e8e17b2b214548fbf -marisa-trie==1.2.1 \ - --hash=sha256:20948e40ab2038e62b7000ca6b4a913bc16c91a2c2e6da501bd1f917eeb28d51 \ - --hash=sha256:2428b495003c189695fb91ceeb499f9fcced3a2dce853e17fa475519433c67ff \ - --hash=sha256:36aa4401a1180615f74d575571a6550081d84fc6461e9aefc0bb7b2427af098e \ - --hash=sha256:3a27c408e2aefc03e0f1d25b2ff2afb85aac3568f6fa2ae2a53b57a2e87ce29d \ - --hash=sha256:3ad356442c2fea4c2a6f514738ddf213d23930f942299a2b2c05df464a00848a \ - --hash=sha256:46e528ee71808c961baf8c3ce1c46a8337ec7a96cc55389d11baafe5b632f8e9 \ - --hash=sha256:5e649f3dc8ab5476732094f2828cc90cac3be7c79bc0c8318b6fda0c1d248db4 \ - --hash=sha256:638506eacf20ca503fff72221a7e66a6eadbf28d6a4a6f949fcf5b1701bb05ec \ - --hash=sha256:6532615111eec2c79e711965ece0bc95adac1ff547a7fff5ffca525463116deb \ - --hash=sha256:66b23e5b35dd547f85bf98db7c749bc0ffc57916ade2534a6bbc32db9a4abc44 \ - --hash=sha256:6704adf0247d2dda42e876b793be40775dff46624309ad99bc7537098bee106d \ - --hash=sha256:735c363d9aaac82eaf516a28f7c6b95084c2e176d8231c87328dc80e112a9afa \ - --hash=sha256:98042040d1d6085792e8d0f74004fc0f5f9ca6091c298f593dd81a22a4643854 \ - --hash=sha256:9f627f4e41be710b6cb6ed54b0128b229ac9d50e2054d9cde3af0fef277c23cf \ - --hash=sha256:aa7cd17e1c690ce96c538b2f4aae003d9a498e65067dd433c52dd069009951d4 \ - --hash=sha256:b2a7d00f53f4945320b551bccb826b3fb26948bde1a10d50bb9802fabb611b10 \ - --hash=sha256:b5ea16e69bfda0ac028c921b58de1a4aaf83d43934892977368579cd3c0a2554 \ - --hash=sha256:ce59bcd2cda9bb52b0e90cc7f36413cd86c3d0ce7224143447424aafb9f4aa48 \ - --hash=sha256:de1665eaafefa48a308e4753786519888021740501a15461c77bdfd57638e6b4 \ - --hash=sha256:eba6ca45500ca1a042466a0684aacc9838e7f20fe2605521ee19f2853062798f \ - --hash=sha256:f2806f75817392cedcacb24ac5d80b0350dde8d3861d67d045c1d9b109764114 \ - --hash=sha256:f4cd800704a5fc57e53c39c3a6b0c9b1519ebdbcb644ede3ee67a06eb542697d \ - --hash=sha256:f713af9b8aa66a34cd3a78c7d150a560a75734713abe818a69021fd269e927fa -markdown-it-py==3.0.0 \ - --hash=sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1 \ - --hash=sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb -markupsafe==3.0.2 \ - --hash=sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30 \ - --hash=sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9 \ - --hash=sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396 \ - --hash=sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028 \ - --hash=sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557 \ - --hash=sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a \ - --hash=sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c \ - --hash=sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c \ - --hash=sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22 \ - --hash=sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094 \ - --hash=sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5 \ - --hash=sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225 \ - --hash=sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c \ - --hash=sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87 \ - --hash=sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf \ - --hash=sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb \ - --hash=sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48 \ - --hash=sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c \ - --hash=sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6 \ - --hash=sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd \ - --hash=sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1 \ - --hash=sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d \ - --hash=sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca \ - --hash=sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a \ - --hash=sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe \ - --hash=sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8 \ - --hash=sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f \ - --hash=sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f \ - --hash=sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0 \ - --hash=sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79 \ - --hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430 -matplotlib-inline==0.1.7 \ - --hash=sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90 \ - --hash=sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca -mdurl==0.1.2 \ - --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ - --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba -mistune==3.1.0 \ - --hash=sha256:b05198cf6d671b3deba6c87ec6cf0d4eb7b72c524636eddb6dbf13823b52cee1 \ - --hash=sha256:dbcac2f78292b9dc066cd03b7a3a26b62d85f8159f2ea5fd28e55df79908d667 -model2vec==0.3.7 \ - --hash=sha256:1f13532fcbad57da524fd3ae1580597cdd2bc5d76077dd4f87dfd2b5a411540e \ - --hash=sha256:5000a19d86e76f20afa4b403946f512a4c17496e35295b8855e728f4ba04ec89 -msal==1.31.1 \ - --hash=sha256:11b5e6a3f802ffd3a72107203e20c4eac6ef53401961b880af2835b723d80578 \ - --hash=sha256:29d9882de247e96db01386496d59f29035e5e841bcac892e6d7bf4390bf6bd17 -msal-extensions==1.2.0 \ - --hash=sha256:6f41b320bfd2933d631a215c91ca0dd3e67d84bd1a2f50ce917d5874ec646bef \ - --hash=sha256:cf5ba83a2113fa6dc011a254a72f1c223c88d7dfad74cc30617c4679a417704d -msrest==0.7.1 \ - --hash=sha256:21120a810e1233e5e6cc7fe40b474eeb4ec6f757a15d7cf86702c369f9567c32 \ - --hash=sha256:6e7661f46f3afd88b75667b7187a92829924446c7ea1d169be8c4bb7eeb788b9 -multidict==6.1.0 \ - --hash=sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f \ - --hash=sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761 \ - --hash=sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3 \ - --hash=sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6 \ - --hash=sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966 \ - --hash=sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1 \ - --hash=sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305 \ - --hash=sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a \ - --hash=sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c \ - --hash=sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4 \ - --hash=sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81 \ - --hash=sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3 \ - --hash=sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506 \ - --hash=sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925 \ - --hash=sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6 \ - --hash=sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e \ - --hash=sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95 \ - --hash=sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2 \ - --hash=sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133 \ - --hash=sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa \ - --hash=sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3 \ - --hash=sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436 \ - --hash=sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2 \ - --hash=sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2 \ - --hash=sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa \ - --hash=sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b \ - --hash=sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa \ - --hash=sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef \ - --hash=sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44 \ - --hash=sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008 \ - --hash=sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774 \ - --hash=sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28 -murmurhash==1.0.12 \ - --hash=sha256:19de30edaaa2217cd0c41b6cf6bbfa418be5d7fdf267ca92e5e3710d4daac593 \ - --hash=sha256:1a4c97c8ffbedb62b760c3c2f77b5b8cb0e0ac0ec83a74d2f289e113e3e92ed5 \ - --hash=sha256:467b7ee31c1f79f46d00436a1957fc52a0e5801369dd2f30eb7655f380735b5f \ - --hash=sha256:63f10c6d6ef9ee85073dd896d2c4e0ab161bc6b8e7e9201c69f8061f9f1b6468 \ - --hash=sha256:66356f6308fd2a44a8ab056f020acd5bc22302f23ef5cce3705f2493e0fe9c3c \ - --hash=sha256:701cc0ce91809b4d7c2e0518be759635205e1e181325792044f5a8118019f716 \ - --hash=sha256:7a7ef5fb37e72536458ac4a6f486fb374c60ac4c4862d9195d3d4b58239a91de \ - --hash=sha256:7dc4ebdfed7ef8ed70519962ac9b704e91978ee14e049f1ff37bca2f579ce84d \ - --hash=sha256:7e1c9de2167a9d408d121ebc918bcb20b2718ec956f3aae0ded53d9bb224bb8e \ - --hash=sha256:8bd5524de195991ce3551b14286ec0b730cc9dd2e10565dad2ae470eec082028 \ - --hash=sha256:8c5b8804c07a76f779e67f83aad37bc2189a0e65ebdd3f2b305242d489d31e03 \ - --hash=sha256:94a52972835bdae8af18147c67c398ff3ea1d875f5b8dca1e1aa0fadb892f546 \ - --hash=sha256:9574f0b634f059158bb89734a811e435ac9ad2335c02a7abb59f1875dcce244c \ - --hash=sha256:bdb2104aa3471324724abf5a3a76fc94bcbeaf023bb6a6dd94da567b8633d8a6 \ - --hash=sha256:cc88004c8615dcabe31d21142689f719fdf549ba782850bef389cf227a1df575 -mypy-extensions==1.0.0 \ - --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \ - --hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782 -nbclient==0.10.2 \ - --hash=sha256:4ffee11e788b4a27fabeb7955547e4318a5298f34342a4bfd01f2e1faaeadc3d \ - --hash=sha256:90b7fc6b810630db87a6d0c2250b1f0ab4cf4d3c27a299b0cde78a4ed3fd9193 -nbconvert==7.16.5 \ - --hash=sha256:c83467bb5777fdfaac5ebbb8e864f300b277f68692ecc04d6dab72f2d8442344 \ - --hash=sha256:e12eac052d6fd03040af4166c563d76e7aeead2e9aadf5356db552a1784bd547 -nbformat==5.10.4 \ - --hash=sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a \ - --hash=sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b -nest-asyncio==1.6.0 \ - --hash=sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe \ - --hash=sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c -nodeenv==1.9.1 \ - --hash=sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f \ - --hash=sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9 -notebook==7.3.2 \ - --hash=sha256:705e83a1785f45b383bf3ee13cb76680b92d24f56fb0c7d2136fe1d850cd3ca8 \ - --hash=sha256:e5f85fc59b69d3618d73cf27544418193ff8e8058d5bf61d315ce4f473556288 -notebook-shim==0.2.4 \ - --hash=sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef \ - --hash=sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb -numpy==1.26.4 \ - --hash=sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b \ - --hash=sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818 \ - --hash=sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0 \ - --hash=sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010 \ - --hash=sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110 \ - --hash=sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed \ - --hash=sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b \ - --hash=sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a \ - --hash=sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218 -oauthlib==3.2.2 \ - --hash=sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca \ - --hash=sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918 -openai==1.60.0 \ - --hash=sha256:7fa536cd4b644718645b874d2706e36dbbef38b327e42ca0623275da347ee1a9 \ - --hash=sha256:df06c43be8018274980ac363da07d4b417bd835ead1c66e14396f6f15a0d5dda -openpyxl==3.1.5 \ - --hash=sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2 \ - --hash=sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050 -overrides==7.7.0 \ - --hash=sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a \ - --hash=sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49 -packaging==24.2 \ - --hash=sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759 \ - --hash=sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f -pandas==2.2.3 \ - --hash=sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a \ - --hash=sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d \ - --hash=sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4 \ - --hash=sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0 \ - --hash=sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28 \ - --hash=sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18 \ - --hash=sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468 \ - --hash=sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667 \ - --hash=sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13 \ - --hash=sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3 \ - --hash=sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d \ - --hash=sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb \ - --hash=sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8 \ - --hash=sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659 \ - --hash=sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4 \ - --hash=sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a \ - --hash=sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9 \ - --hash=sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2 \ - --hash=sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015 \ - --hash=sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24 \ - --hash=sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319 -pandocfilters==1.5.1 \ - --hash=sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e \ - --hash=sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc -parso==0.8.4 \ - --hash=sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18 \ - --hash=sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d -pathspec==0.12.1 \ - --hash=sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08 \ - --hash=sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712 -pexpect==4.9.0 ; sys_platform != 'emscripten' and sys_platform != 'win32' \ - --hash=sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523 \ - --hash=sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f -pillow==11.1.0 \ - --hash=sha256:11633d58b6ee5733bde153a8dafd25e505ea3d32e261accd388827ee987baf65 \ - --hash=sha256:2062ffb1d36544d42fcaa277b069c88b01bb7298f4efa06731a7fd6cc290b81a \ - --hash=sha256:31eba6bbdd27dde97b0174ddf0297d7a9c3a507a8a1480e1e60ef914fe23d352 \ - --hash=sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20 \ - --hash=sha256:36ba10b9cb413e7c7dfa3e189aba252deee0602c86c309799da5a74009ac7a1c \ - --hash=sha256:3764d53e09cdedd91bee65c2527815d315c6b90d7b8b79759cc48d7bf5d4f114 \ - --hash=sha256:3cdcdb0b896e981678eee140d882b70092dac83ac1cdf6b3a60e2216a73f2b91 \ - --hash=sha256:4dd43a78897793f60766563969442020e90eb7847463eca901e41ba186a7d4a5 \ - --hash=sha256:593c5fd6be85da83656b93ffcccc2312d2d149d251e98588b14fbc288fd8909c \ - --hash=sha256:67cd427c68926108778a9005f2a04adbd5e67c442ed21d95389fe1d595458756 \ - --hash=sha256:70ca5ef3b3b1c4a0812b5c63c57c23b63e53bc38e758b37a951e5bc466449861 \ - --hash=sha256:758e9d4ef15d3560214cddbc97b8ef3ef86ce04d62ddac17ad39ba87e89bd3b1 \ - --hash=sha256:7fdadc077553621911f27ce206ffcbec7d3f8d7b50e0da39f10997e8e2bb7f6a \ - --hash=sha256:8000376f139d4d38d6851eb149b321a52bb8893a88dae8ee7d95840431977081 \ - --hash=sha256:9044b5e4f7083f209c4e35aa5dd54b1dd5b112b108648f5c902ad586d4f945c5 \ - --hash=sha256:93a18841d09bcdd774dcdc308e4537e1f867b3dec059c131fde0327899734aa1 \ - --hash=sha256:9409c080586d1f683df3f184f20e36fb647f2e0bc3988094d4fd8c9f4eb1b3b3 \ - --hash=sha256:9aa9aeddeed452b2f616ff5507459e7bab436916ccb10961c4a382cd3e03f47f \ - --hash=sha256:9ee85f0696a17dd28fbcfceb59f9510aa71934b483d1f5601d1030c3c8304f3c \ - --hash=sha256:a697cd8ba0383bba3d2d3ada02b34ed268cb548b369943cd349007730c92bddf \ - --hash=sha256:a85b653980faad27e88b141348707ceeef8a1186f75ecc600c395dcac19f385b \ - --hash=sha256:ad5db5781c774ab9a9b2c4302bbf0c1014960a0a7be63278d13ae6fdf88126fe \ - --hash=sha256:ae98e14432d458fc3de11a77ccb3ae65ddce70f730e7c76140653048c71bfcbc \ - --hash=sha256:b523466b1a31d0dcef7c5be1f20b942919b62fd6e9a9be199d035509cbefc0ec \ - --hash=sha256:b5d658fbd9f0d6eea113aea286b21d3cd4d3fd978157cbf2447a6035916506d3 \ - --hash=sha256:cc1331b6d5a6e144aeb5e626f4375f5b7ae9934ba620c0ac6b3e43d5e683a0f0 \ - --hash=sha256:cfd5cd998c2e36a862d0e27b2df63237e67273f2fc78f47445b14e73a810e7e6 \ - --hash=sha256:dd0e081319328928531df7a0e63621caf67652c8464303fd102141b785ef9547 \ - --hash=sha256:dda60aa465b861324e65a78c9f5cf0f4bc713e4309f83bc387be158b077963d9 \ - --hash=sha256:e63e4e5081de46517099dc30abe418122f54531a6ae2ebc8680bcd7096860eab \ - --hash=sha256:f86d3a7a9af5d826744fabf4afd15b9dfef44fe69a98541f666f66fbb8d3fef9 -platformdirs==4.3.6 \ - --hash=sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907 \ - --hash=sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb -portalocker==2.10.1 \ - --hash=sha256:53a5984ebc86a025552264b459b46a2086e269b21823cb572f8f28ee759e45bf \ - --hash=sha256:ef1bf844e878ab08aee7e40184156e1151f228f103aa5c6bd0724cc330960f8f -pre-commit==4.1.0 \ - --hash=sha256:ae3f018575a588e30dfddfab9a05448bfbd6b73d78709617b5a2b853549716d4 \ - --hash=sha256:d29e7cb346295bcc1cc75fc3e92e343495e3ea0196c9ec6ba53f49f10ab6ae7b -preshed==3.0.9 \ - --hash=sha256:24229c77364628743bc29c5620c5d6607ed104f0e02ae31f8a030f99a78a5ceb \ - --hash=sha256:4a55091d0e395f1fdb62ab43401bb9f8b46c7d7794d5b071813c29dc1ab22fd0 \ - --hash=sha256:721863c5244ffcd2651ad0928951a2c7c77b102f4e11a251ad85d37ee7621660 \ - --hash=sha256:7de8f5138bcac7870424e09684dc3dd33c8e30e81b269f6c9ede3d8c7bb8e257 \ - --hash=sha256:b4fe6720012c62e6d550d6a5c1c7ad88cacef8388d186dad4bafea4140d9d198 \ - --hash=sha256:e04f05758875be9751e483bd3c519c22b00d3b07f5a64441ec328bb9e3c03700 -prometheus-client==0.21.1 \ - --hash=sha256:252505a722ac04b0456be05c05f75f45d760c2911ffc45f2a06bcaed9f3ae3fb \ - --hash=sha256:594b45c410d6f4f8888940fe80b5cc2521b305a1fafe1c58609ef715a001f301 -prompt-toolkit==3.0.50 \ - --hash=sha256:544748f3860a2623ca5cd6d2795e7a14f3d0e1c3c9728359013f79877fc89bab \ - --hash=sha256:9b6427eb19e479d98acff65196a307c555eb567989e6d88ebbb1b509d9779198 -propcache==0.2.1 \ - --hash=sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4 \ - --hash=sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a \ - --hash=sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f \ - --hash=sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9 \ - --hash=sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d \ - --hash=sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6 \ - --hash=sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d \ - --hash=sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30 \ - --hash=sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95 \ - --hash=sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348 \ - --hash=sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64 \ - --hash=sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce \ - --hash=sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629 \ - --hash=sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54 \ - --hash=sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1 \ - --hash=sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf \ - --hash=sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b \ - --hash=sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24 \ - --hash=sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5 \ - --hash=sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc \ - --hash=sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce \ - --hash=sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518 \ - --hash=sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536 \ - --hash=sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052 \ - --hash=sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff \ - --hash=sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1 \ - --hash=sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246 \ - --hash=sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0 \ - --hash=sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f \ - --hash=sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439 \ - --hash=sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6 \ - --hash=sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec \ - --hash=sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d \ - --hash=sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6 -psutil==6.1.1 \ - --hash=sha256:0bdd4eab935276290ad3cb718e9809412895ca6b5b334f5a9111ee6d9aff9377 \ - --hash=sha256:33431e84fee02bc84ea36d9e2c4a6d395d479c9dd9bba2376c1f6ee8f3a4e0b3 \ - --hash=sha256:97f7cb9921fbec4904f522d972f0c0e1f4fabbdd4e0287813b21215074a0f160 \ - --hash=sha256:b6e06c20c05fe95a3d7302d74e7097756d4ba1247975ad6905441ae1b5b66003 \ - --hash=sha256:cf8496728c18f2d0b45198f06895be52f36611711746b7f30c464b422b50e2f5 \ - --hash=sha256:eaa912e0b11848c4d9279a93d7e2783df352b082f40111e078388701fd479e53 \ - --hash=sha256:f35cfccb065fff93529d2afb4a2e89e363fe63ca1e4a5da22b603a85833c2649 \ - --hash=sha256:fc0ed7fe2231a444fc219b9c42d0376e0a9a1a72f16c5cfa0f68d19f1a0663e8 -ptyprocess==0.7.0 ; os_name != 'nt' or (sys_platform != 'emscripten' and sys_platform != 'win32') \ - --hash=sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35 \ - --hash=sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220 -pure-eval==0.2.3 \ - --hash=sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0 \ - --hash=sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42 -pycparser==2.22 \ - --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ - --hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc -pydantic==2.10.5 \ - --hash=sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff \ - --hash=sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53 -pydantic-core==2.27.2 \ - --hash=sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6 \ - --hash=sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7 \ - --hash=sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee \ - --hash=sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc \ - --hash=sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130 \ - --hash=sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4 \ - --hash=sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4 \ - --hash=sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b \ - --hash=sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934 \ - --hash=sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2 \ - --hash=sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9 \ - --hash=sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27 \ - --hash=sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b \ - --hash=sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154 \ - --hash=sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef \ - --hash=sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4 \ - --hash=sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee \ - --hash=sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c \ - --hash=sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0 \ - --hash=sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57 \ - --hash=sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b \ - --hash=sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1 \ - --hash=sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e \ - --hash=sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9 \ - --hash=sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1 \ - --hash=sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3 \ - --hash=sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39 \ - --hash=sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a \ - --hash=sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9 -pygments==2.19.1 \ - --hash=sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f \ - --hash=sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c -pyjwt==2.10.1 \ - --hash=sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953 \ - --hash=sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb -pymupdf==1.25.2 \ - --hash=sha256:1b4ca6f5780d319a08dff885a5a0e3585c5d7af04dcfa063c535b88371fd91c1 \ - --hash=sha256:295505fe1ecb7c7b57d4124d373e207ea311d8e40bc7ac3016d8ec2d60b091e9 \ - --hash=sha256:59dea22b633cc4fc13670b4c5db50d71f8cd4f420814420f33ce47ddcb61e1f6 \ - --hash=sha256:9ea88ff1b3ccb359620f106a6fd5ba6877d959d21d78272052c3496ceede6eec \ - --hash=sha256:ae8cfa7a97d78f813d286ecba32369059d88073edd1e5cf105f4cd0811f71925 \ - --hash=sha256:b9488c8b82bb9be36fb13ee0c8d43b0ddcc50af83b61da01e6040413d9e67da6 \ - --hash=sha256:e8b8a874497cd0deee89a6a4fb76a3a08173c8d39e88fc7cf715764ec5a243e9 \ - --hash=sha256:f61e5cdb25b86eb28d34aa3557b49ecf9e361d5f5cd3b1660406f8f0bf813af7 -python-dateutil==2.9.0.post0 \ - --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ - --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 -python-dotenv==1.0.1 \ - --hash=sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca \ - --hash=sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a -python-json-logger==3.2.1 \ - --hash=sha256:8eb0554ea17cb75b05d2848bc14fb02fbdbd9d6972120781b974380bfa162008 \ - --hash=sha256:cdc17047eb5374bd311e748b42f99d71223f3b0e186f4206cc5d52aefe85b090 -pytz==2024.2 \ - --hash=sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a \ - --hash=sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725 -pywin32==308 ; (platform_python_implementation != 'PyPy' and sys_platform == 'win32') or platform_system == 'Windows' \ - --hash=sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47 \ - --hash=sha256:1c44539a37a5b7b21d02ab34e6a4d314e0788f1690d65b48e9b0b89f31abbbed \ - --hash=sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897 \ - --hash=sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091 \ - --hash=sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd \ - --hash=sha256:fd380990e792eaf6827fcb7e187b2b4b1cede0585e3d0c9e84201ec27b9905e4 -pywinpty==2.0.14 ; os_name == 'nt' \ - --hash=sha256:074fb988a56ec79ca90ed03a896d40707131897cefb8f76f926e3834227f2819 \ - --hash=sha256:18bd9529e4a5daf2d9719aa17788ba6013e594ae94c5a0c27e83df3278b0660e \ - --hash=sha256:55dad362ef3e9408ade68fd173e4f9032b3ce08f68cfe7eacb2c263ea1179737 -pyyaml==6.0.2 \ - --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \ - --hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \ - --hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \ - --hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \ - --hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \ - --hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \ - --hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \ - --hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \ - --hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \ - --hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \ - --hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \ - --hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \ - --hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \ - --hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \ - --hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \ - --hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \ - --hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \ - --hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \ - --hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba -pyzmq==26.2.0 \ - --hash=sha256:007137c9ac9ad5ea21e6ad97d3489af654381324d5d3ba614c323f60dab8fae6 \ - --hash=sha256:034da5fc55d9f8da09015d368f519478a52675e558c989bfcb5cf6d4e16a7d2a \ - --hash=sha256:070672c258581c8e4f640b5159297580a9974b026043bd4ab0470be9ed324f1f \ - --hash=sha256:17bf5a931c7f6618023cdacc7081f3f266aecb68ca692adac015c383a134ca52 \ - --hash=sha256:23f4aad749d13698f3f7b64aad34f5fc02d6f20f05999eebc96b89b01262fb18 \ - --hash=sha256:25bf2374a2a8433633c65ccb9553350d5e17e60c8eb4de4d92cc6bd60f01d306 \ - --hash=sha256:28c812d9757fe8acecc910c9ac9dafd2ce968c00f9e619db09e9f8f54c3a68a3 \ - --hash=sha256:29c6a4635eef69d68a00321e12a7d2559fe2dfccfa8efae3ffb8e91cd0b36a8b \ - --hash=sha256:2a50625acdc7801bc6f74698c5c583a491c61d73c6b7ea4dee3901bb99adb27a \ - --hash=sha256:2ae90ff9dad33a1cfe947d2c40cb9cb5e600d759ac4f0fd22616ce6540f72797 \ - --hash=sha256:31507f7b47cc1ead1f6e86927f8ebb196a0bab043f6345ce070f412a59bf87b5 \ - --hash=sha256:43a47408ac52647dfabbc66a25b05b6a61700b5165807e3fbd40063fcaf46386 \ - --hash=sha256:4661c88db4a9e0f958c8abc2b97472e23061f0bc737f6f6179d7a27024e1faa5 \ - --hash=sha256:470d4a4f6d48fb34e92d768b4e8a5cc3780db0d69107abf1cd7ff734b9766eb0 \ - --hash=sha256:4d29ab8592b6ad12ebbf92ac2ed2bedcfd1cec192d8e559e2e099f648570e19b \ - --hash=sha256:4d80b1dd99c1942f74ed608ddb38b181b87476c6a966a88a950c7dee118fdf50 \ - --hash=sha256:55cf66647e49d4621a7e20c8d13511ef1fe1efbbccf670811864452487007e08 \ - --hash=sha256:6b274e0762c33c7471f1a7471d1a2085b1a35eba5cdc48d2ae319f28b6fc4de3 \ - --hash=sha256:70fc7fcf0410d16ebdda9b26cbd8bf8d803d220a7f3522e060a69a9c87bf7bad \ - --hash=sha256:794a4562dcb374f7dbbfb3f51d28fb40123b5a2abadee7b4091f93054909add5 \ - --hash=sha256:7ad1bc8d1b7a18497dda9600b12dc193c577beb391beae5cd2349184db40f187 \ - --hash=sha256:7f98f6dfa8b8ccaf39163ce872bddacca38f6a67289116c8937a02e30bbe9711 \ - --hash=sha256:8c997098cc65e3208eca09303630e84d42718620e83b733d0fd69543a9cab9cb \ - --hash=sha256:989d842dc06dc59feea09e58c74ca3e1678c812a4a8a2a419046d711031f69c7 \ - --hash=sha256:9dd8cd1aeb00775f527ec60022004d030ddc51d783d056e3e23e74e623e33726 \ - --hash=sha256:a4f96f0d88accc3dbe4a9025f785ba830f968e21e3e2c6321ccdfc9aef755115 \ - --hash=sha256:aee22939bb6075e7afededabad1a56a905da0b3c4e3e0c45e75810ebe3a52672 \ - --hash=sha256:bea2acdd8ea4275e1278350ced63da0b166421928276c7c8e3f9729d7402a57b \ - --hash=sha256:c3789bd5768ab5618ebf09cef6ec2b35fed88709b104351748a63045f0ff9797 \ - --hash=sha256:c92d73464b886931308ccc45b2744e5968cbaade0b1d6aeb40d8ab537765f5bc \ - --hash=sha256:ced65e5a985398827cc9276b93ef6dfabe0273c23de8c7931339d7e141c2818e \ - --hash=sha256:ded0fc7d90fe93ae0b18059930086c51e640cdd3baebdc783a695c77f123dcd9 \ - --hash=sha256:e3e0210287329272539eea617830a6a28161fbbd8a3271bf4150ae3e58c5d0e6 \ - --hash=sha256:ea7f69de383cb47522c9c208aec6dd17697db7875a4674c4af3f8cfdac0bdeae -referencing==0.36.1 \ - --hash=sha256:363d9c65f080d0d70bc41c721dce3c7f3e77fc09f269cd5c8813da18069a6794 \ - --hash=sha256:ca2e6492769e3602957e9b831b94211599d2aade9477f5d44110d2530cf9aade -regex==2024.11.6 \ - --hash=sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0 \ - --hash=sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad \ - --hash=sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe \ - --hash=sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3 \ - --hash=sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4 \ - --hash=sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39 \ - --hash=sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7 \ - --hash=sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a \ - --hash=sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54 \ - --hash=sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c \ - --hash=sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d \ - --hash=sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4 \ - --hash=sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a \ - --hash=sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07 \ - --hash=sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff \ - --hash=sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e \ - --hash=sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519 \ - --hash=sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2 \ - --hash=sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e \ - --hash=sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84 \ - --hash=sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29 \ - --hash=sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b \ - --hash=sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3 \ - --hash=sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7 \ - --hash=sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4 \ - --hash=sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e \ - --hash=sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577 \ - --hash=sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0 \ - --hash=sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51 \ - --hash=sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6 \ - --hash=sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9 -requests==2.32.3 \ - --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \ - --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6 -requests-oauthlib==2.0.0 \ - --hash=sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36 \ - --hash=sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9 -rfc3339-validator==0.1.4 \ - --hash=sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b \ - --hash=sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa -rfc3986-validator==0.1.1 \ - --hash=sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9 \ - --hash=sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055 -rich==13.9.4 \ - --hash=sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098 \ - --hash=sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90 -rpds-py==0.22.3 \ - --hash=sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518 \ - --hash=sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059 \ - --hash=sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61 \ - --hash=sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5 \ - --hash=sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56 \ - --hash=sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd \ - --hash=sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b \ - --hash=sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4 \ - --hash=sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d \ - --hash=sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1 \ - --hash=sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e \ - --hash=sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc \ - --hash=sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38 \ - --hash=sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b \ - --hash=sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c \ - --hash=sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83 \ - --hash=sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1 \ - --hash=sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627 \ - --hash=sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16 \ - --hash=sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45 \ - --hash=sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730 \ - --hash=sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25 \ - --hash=sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7 \ - --hash=sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f \ - --hash=sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd \ - --hash=sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333 \ - --hash=sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9 \ - --hash=sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4 \ - --hash=sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d \ - --hash=sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15 \ - --hash=sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84 \ - --hash=sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e \ - --hash=sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf \ - --hash=sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b \ - --hash=sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2 \ - --hash=sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3 \ - --hash=sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130 \ - --hash=sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b \ - --hash=sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de \ - --hash=sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e -ruff==0.9.2 \ - --hash=sha256:1a605fdcf6e8b2d39f9436d343d1f0ff70c365a1e681546de0104bef81ce88df \ - --hash=sha256:3292c5a22ea9a5f9a185e2d131dc7f98f8534a32fb6d2ee7b9944569239c648d \ - --hash=sha256:492a5e44ad9b22a0ea98cf72e40305cbdaf27fac0d927f8bc9e1df316dcc96eb \ - --hash=sha256:71cbe22e178c5da20e1514e1e01029c73dc09288a8028a5d3446e6bba87a5145 \ - --hash=sha256:80605a039ba1454d002b32139e4970becf84b5fee3a3c3bf1c2af6f61a784347 \ - --hash=sha256:82b35259b0cbf8daa22a498018e300b9bb0174c2bbb7bcba593935158a78054d \ - --hash=sha256:8b6a9701d1e371bf41dca22015c3f89769da7576884d2add7317ec1ec8cb9c3c \ - --hash=sha256:8efd9da7a1ee314b910da155ca7e8953094a7c10d0c0a39bfde3fcfd2a015684 \ - --hash=sha256:9cc53e68b3c5ae41e8faf83a3b89f4a5d7b2cb666dff4b366bb86ed2a85b481f \ - --hash=sha256:a1b63fa24149918f8b37cef2ee6fff81f24f0d74b6f0bdc37bc3e1f2143e41c6 \ - --hash=sha256:af1e9e9fe7b1f767264d26b1075ac4ad831c7db976911fa362d09b2d0356426a \ - --hash=sha256:b338edc4610142355ccf6b87bd356729b62bf1bc152a2fad5b0c7dc04af77bfe \ - --hash=sha256:b5eceb334d55fae5f316f783437392642ae18e16dcf4f1858d55d3c2a0f8f5d0 \ - --hash=sha256:b9aab82bb20afd5f596527045c01e6ae25a718ff1784cb92947bff1f83068b00 \ - --hash=sha256:c547f7f256aa366834829a08375c297fa63386cbe5f1459efaf174086b564247 \ - --hash=sha256:c5e1d6abc798419cf46eed03f54f2e0c3adb1ad4b801119dedf23fcaf69b55b5 \ - --hash=sha256:d18bba3d3353ed916e882521bc3e0af403949dbada344c20c16ea78f47af965e \ - --hash=sha256:fbd337bac1cfa96be615f6efcd4bc4d077edbc127ef30e2b8ba2a27e18c054d4 -safetensors==0.5.2 \ - --hash=sha256:03c937100f38c9ff4c1507abea9928a6a9b02c9c1c9c3609ed4fb2bf413d4975 \ - --hash=sha256:1506e4c2eda1431099cebe9abf6c76853e95d0b7a95addceaa74c6019c65d8cf \ - --hash=sha256:3ab696dfdc060caffb61dbe4066b86419107a24c804a4e373ba59be699ebd8d5 \ - --hash=sha256:3dfa7c2f3fe55db34eba90c29df94bcdac4821043fc391cb5d082d9922013869 \ - --hash=sha256:45b6092997ceb8aa3801693781a71a99909ab9cc776fbc3fa9322d29b1d3bef2 \ - --hash=sha256:46ff2116150ae70a4e9c490d2ab6b6e1b1b93f25e520e540abe1b81b48560c3a \ - --hash=sha256:5c5b5d9da594f638a259fca766046f44c97244cc7ab8bef161b3e80d04becc76 \ - --hash=sha256:6d0d6a8ee2215a440e1296b843edf44fd377b055ba350eaba74655a2fe2c4bae \ - --hash=sha256:78abdddd03a406646107f973c7843276e7b64e5e32623529dc17f3d94a20f589 \ - --hash=sha256:86016d40bcaa3bcc9a56cd74d97e654b5f4f4abe42b038c71e4f00a089c4526c \ - --hash=sha256:990833f70a5f9c7d3fc82c94507f03179930ff7d00941c287f73b6fcbf67f19e \ - --hash=sha256:a00e737948791b94dad83cf0eafc09a02c4d8c2171a239e8c8572fe04e25960e \ - --hash=sha256:cb4a8d98ba12fa016f4241932b1fc5e702e5143f5374bba0bbcf7ddc1c4cf2b8 \ - --hash=sha256:d3a06fae62418ec8e5c635b61a8086032c9e281f16c63c3af46a6efbab33156f \ - --hash=sha256:fe55c039d97090d1f85277d402954dd6ad27f63034fa81985a9cc59655ac3ee2 -send2trash==1.8.3 \ - --hash=sha256:0c31227e0bd08961c7665474a3d1ef7193929fedda4233843689baa056be46c9 \ - --hash=sha256:b18e7a3966d99871aefeb00cfbcfdced55ce4871194810fc71f4aa484b953abf -setuptools==75.8.0 \ - --hash=sha256:c5afc8f407c626b8313a86e10311dd3f661c6cd9c09d4bf8c15c0e11f9f2b0e6 \ - --hash=sha256:e3982f444617239225d675215d51f6ba05f845d4eec313da4418fdbb56fb27e3 -shellingham==1.5.4 \ - --hash=sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686 \ - --hash=sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de -six==1.17.0 \ - --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ - --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81 -smart-open==7.1.0 \ - --hash=sha256:4b8489bb6058196258bafe901730c7db0dcf4f083f316e97269c66f45502055b \ - --hash=sha256:a4f09f84f0f6d3637c6543aca7b5487438877a21360e7368ccf1f704789752ba -sniffio==1.3.1 \ - --hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \ - --hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc -soupsieve==2.6 \ - --hash=sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb \ - --hash=sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9 -spacy==3.7.5 \ - --hash=sha256:07677e270a6d729453cc04b5e2247a96a86320b8845e6428d9f90f217eff0f56 \ - --hash=sha256:262f8ebb71f7ed5ffe8e4f384b2594b7a296be50241ce9fbd9277b5da2f46f38 \ - --hash=sha256:4145cea7f9814fa7d86b2028c2dd83e02f13f80d5ac604a400b2f7d7b26a0e8c \ - --hash=sha256:a648c6cbf2acc7a55a69ee9e7fa4f22bdf69aa828a587a1bc5cfff08cf3c2dd3 \ - --hash=sha256:bf54c3c2425428b328b53a65913d47eb4cb27a1429aa4e8ed979ffc97d4663e0 \ - --hash=sha256:faa1e2b6234ae33c0b1f8dfa5a8dcb66fb891f19231725dfcff4b2666125c250 -spacy-legacy==3.0.12 \ - --hash=sha256:476e3bd0d05f8c339ed60f40986c07387c0a71479245d6d0f4298dbd52cda55f \ - --hash=sha256:b37d6e0c9b6e1d7ca1cf5bc7152ab64a4c4671f59c85adaf7a3fcb870357a774 -spacy-loggers==1.0.5 \ - --hash=sha256:196284c9c446cc0cdb944005384270d775fdeaf4f494d8e269466cfa497ef645 \ - --hash=sha256:d60b0bdbf915a60e516cc2e653baeff946f0cfc461b452d11a4d5458c6fe5f24 -srsly==2.5.1 \ - --hash=sha256:00c2a3e4856e63b7efd47591d049aaee8e5a250e098917f50d93ea68853fab78 \ - --hash=sha256:184e3c98389aab68ff04aab9095bd5f1a8e5a72cc5edcba9d733bac928f5cf9f \ - --hash=sha256:366b4708933cd8d6025c13c2cea3331f079c7bb5c25ec76fca392b6fc09818a0 \ - --hash=sha256:459d987130e57e83ce9e160899afbeb871d975f811e6958158763dd9a8a20f23 \ - --hash=sha256:6118f9c4b221cde0a990d06a42c8a4845218d55b425d8550746fe790acf267e9 \ - --hash=sha256:683b54ed63d7dfee03bc2abc4b4a5f2152f81ec217bbadbac01ef1aaf2a75790 \ - --hash=sha256:6ac3944c112acb3347a39bfdc2ebfc9e2d4bace20fe1c0b764374ac5b83519f2 \ - --hash=sha256:6e57b8138082f09e35db60f99757e16652489e9e3692471d8e0c39aa95180688 \ - --hash=sha256:7481460110d9986781d9e4ac0f5f991f1d6839284a80ad268625f9a23f686950 \ - --hash=sha256:7952538f6bba91b9d8bf31a642ac9e8b9ccc0ccbb309feb88518bfb84bb0dc0d \ - --hash=sha256:84b372f7ef1604b4a5b3cee1571993931f845a5b58652ac01bcb32c52586d2a8 \ - --hash=sha256:ab1b4bf6cf3e29da23dae0493dd1517fb787075206512351421b89b4fc27c77e \ - --hash=sha256:bab90b85a63a1fe0bbc74d373c8bb9bb0499ddfa89075e0ebe8d670f12d04691 \ - --hash=sha256:c8a0b03c64eb6e150d772c5149befbadd981cc734ab13184b0561c17c8cef9b1 \ - --hash=sha256:e73712be1634b5e1de6f81c273a7d47fe091ad3c79dc779c03d3416a5c117cee -stack-data==0.6.3 \ - --hash=sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9 \ - --hash=sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695 -tenacity==9.0.0 \ - --hash=sha256:807f37ca97d62aa361264d497b0e31e92b8027044942bfa756160d908320d73b \ - --hash=sha256:93de0c98785b27fcf659856aa9f54bfbd399e29969b0621bc7f762bd441b4539 -terminado==0.18.1 \ - --hash=sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0 \ - --hash=sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e -thinc==8.2.5 \ - --hash=sha256:87e729f33c76ec6df9b375989743252ab880d79f3a2b4175169b21dece90f102 \ - --hash=sha256:8e299d4dc41107385d6d14d8604a060825798a031cabe2b894b22f9d75d9eaad \ - --hash=sha256:9fc26697e2358c71a5fe243d52e98ae67ee1a3b314eead5031845b6d1c0d121c \ - --hash=sha256:c2963791c934cc7fbd8f9b942d571cac79892ad11630bfca690a868c32752b75 \ - --hash=sha256:c5f750ea2dd32ca6d46947025dacfc0f6037340c4e5f7adb9af84c75f65aa7d8 \ - --hash=sha256:e8a8f2f249f2be9a5ce2a81a6efe7503b68be7b57e47ad54ab28204e1f0c723b -tiktoken==0.8.0 \ - --hash=sha256:02be1666096aff7da6cbd7cdaa8e7917bfed3467cd64b38b1f112e96d3b06a24 \ - --hash=sha256:18228d624807d66c87acd8f25fc135665617cab220671eb65b50f5d70fa51f69 \ - --hash=sha256:294440d21a2a51e12d4238e68a5972095534fe9878be57d905c476017bff99fc \ - --hash=sha256:4177faa809bd55f699e88c96d9bb4635d22e3f59d635ba6fd9ffedf7150b9953 \ - --hash=sha256:5376b6f8dc4753cd81ead935c5f518fa0fbe7e133d9e25f648d8c4dabdd4bad7 \ - --hash=sha256:6b231f5e8982c245ee3065cd84a4712d64692348bc609d84467c57b4b72dcbc5 \ - --hash=sha256:881839cfeae051b3628d9823b2e56b5cc93a9e2efb435f4cf15f17dc45f21586 \ - --hash=sha256:9a58deb7075d5b69237a3ff4bb51a726670419db6ea62bdcd8bd80c78497d7ab \ - --hash=sha256:9ccbb2740f24542534369c5635cfd9b2b3c2490754a78ac8831d99f89f94eeb2 \ - --hash=sha256:c94ff53c5c74b535b2cbf431d907fc13c678bbd009ee633a2aca269a04389f9a \ - --hash=sha256:d2908c0d043a7d03ebd80347266b0e58440bdef5564f84f4d29fb235b5df3b04 \ - --hash=sha256:d8f3192733ac4d77977432947d563d7e1b310b96497acd3c196c9bddb36ed9db \ - --hash=sha256:fe9399bdc3f29d428f16a2f86c3c8ec20be3eac5f53693ce4980371c3245729b -tinycss2==1.4.0 \ - --hash=sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7 \ - --hash=sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289 -tokenizers==0.21.0 \ - --hash=sha256:089d56db6782a73a27fd8abf3ba21779f5b85d4a9f35e3b493c7bbcbbf0d539b \ - --hash=sha256:3c4c93eae637e7d2aaae3d376f06085164e1660f89304c0ab2b1d08a406636b2 \ - --hash=sha256:400832c0904f77ce87c40f1a8a27493071282f785724ae62144324f171377273 \ - --hash=sha256:4145505a973116f91bc3ac45988a92e618a6f83eb458f49ea0790df94ee243ff \ - --hash=sha256:6b177fb54c4702ef611de0c069d9169f0004233890e0c4c5bd5508ae05abf193 \ - --hash=sha256:6b43779a269f4629bebb114e19c3fca0223296ae9fea8bb9a7a6c6fb0657ff8e \ - --hash=sha256:87841da5a25a3a5f70c102de371db120f41873b854ba65e52bccd57df5a3780c \ - --hash=sha256:9aeb255802be90acfd363626753fda0064a8df06031012fe7d52fd9a905eb00e \ - --hash=sha256:c87ca3dc48b9b1222d984b6b7490355a6fdb411a2d810f6f05977258400ddb74 \ - --hash=sha256:d8b09dbeb7a8d73ee204a70f94fc06ea0f17dcf0844f16102b9f414f0b7463ba \ - --hash=sha256:e84ca973b3a96894d1707e189c14a774b701596d579ffc7e69debfc036a61a04 \ - --hash=sha256:eb1702c2f27d25d9dd5b389cc1f2f51813e99f8ca30d9e25348db6585a97e24a \ - --hash=sha256:eb7202d231b273c34ec67767378cd04c767e967fda12d4a9e36208a34e2f137e \ - --hash=sha256:ee0894bf311b75b0c03079f33859ae4b2334d675d4e93f5a4132e1eae2834fe4 \ - --hash=sha256:f53ea537c925422a2e0e92a24cce96f6bc5046bbef24a1652a5edc8ba975f62e -tornado==6.4.2 \ - --hash=sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803 \ - --hash=sha256:1a017d239bd1bb0919f72af256a970624241f070496635784d9bf0db640d3fec \ - --hash=sha256:2876cef82e6c5978fde1e0d5b1f919d756968d5b4282418f3146b79b58556482 \ - --hash=sha256:304463bd0772442ff4d0f5149c6f1c2135a1fae045adf070821c6cdc76980634 \ - --hash=sha256:908b71bf3ff37d81073356a5fadcc660eb10c1476ee6e2725588626ce7e5ca38 \ - --hash=sha256:92bad5b4746e9879fd7bf1eb21dce4e3fc5128d71601f80005afa39237ad620b \ - --hash=sha256:932d195ca9015956fa502c6b56af9eb06106140d844a335590c1ec7f5277d10c \ - --hash=sha256:bca9eb02196e789c9cb5c3c7c0f04fb447dc2adffd95265b2c7223a8a615ccbf \ - --hash=sha256:c36e62ce8f63409301537222faffcef7dfc5284f27eec227389f2ad11b09d946 \ - --hash=sha256:c82c46813ba483a385ab2a99caeaedf92585a1f90defb5693351fa7e4ea0bf73 \ - --hash=sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1 -tqdm==4.67.1 \ - --hash=sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2 \ - --hash=sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2 -traitlets==5.14.3 \ - --hash=sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7 \ - --hash=sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f -typer==0.15.1 \ - --hash=sha256:7994fb7b8155b64d3402518560648446072864beefd44aa2dc36972a5972e847 \ - --hash=sha256:a0588c0a7fa68a1978a069818657778f86abe6ff5ea6abf472f940a08bfe4f0a -types-python-dateutil==2.9.0.20241206 \ - --hash=sha256:18f493414c26ffba692a72369fea7a154c502646301ebfe3d56a04b3767284cb \ - --hash=sha256:e248a4bc70a486d3e3ec84d0dc30eec3a5f979d6e7ee4123ae043eedbb987f53 -typing-extensions==4.12.2 \ - --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ - --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 -tzdata==2025.1 \ - --hash=sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694 \ - --hash=sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639 -uri-template==1.3.0 \ - --hash=sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7 \ - --hash=sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363 -urllib3==2.3.0 \ - --hash=sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df \ - --hash=sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d -virtualenv==20.29.1 \ - --hash=sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779 \ - --hash=sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35 -wasabi==1.1.3 \ - --hash=sha256:4bb3008f003809db0c3e28b4daf20906ea871a2bb43f9914197d540f4f2e0878 \ - --hash=sha256:f76e16e8f7e79f8c4c8be49b4024ac725713ab10cd7f19350ad18a8e3f71728c -wcwidth==0.2.13 \ - --hash=sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859 \ - --hash=sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5 -weasel==0.4.1 \ - --hash=sha256:24140a090ea1ac512a2b2f479cc64192fd1d527a7f3627671268d08ed5ac418c \ - --hash=sha256:aabc210f072e13f6744e5c3a28037f93702433405cd35673f7c6279147085aa9 -webcolors==24.11.1 \ - --hash=sha256:515291393b4cdf0eb19c155749a096f779f7d909f7cceea072791cb9095b92e9 \ - --hash=sha256:ecb3d768f32202af770477b8b65f318fa4f566c22948673a977b00d589dd80f6 -webencodings==0.5.1 \ - --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ - --hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923 -websocket-client==1.8.0 \ - --hash=sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526 \ - --hash=sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da -widgetsnbextension==4.0.13 \ - --hash=sha256:74b2692e8500525cc38c2b877236ba51d34541e6385eeed5aec15a70f88a6c71 \ - --hash=sha256:ffcb67bc9febd10234a362795f643927f4e0c05d9342c727b65d2384f8feacb6 -wrapt==1.17.2 \ - --hash=sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555 \ - --hash=sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b \ - --hash=sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998 \ - --hash=sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392 \ - --hash=sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306 \ - --hash=sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3 \ - --hash=sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9 \ - --hash=sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6 \ - --hash=sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192 \ - --hash=sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f \ - --hash=sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d \ - --hash=sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8 \ - --hash=sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845 \ - --hash=sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82 \ - --hash=sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125 \ - --hash=sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504 \ - --hash=sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b \ - --hash=sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc \ - --hash=sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6 \ - --hash=sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40 \ - --hash=sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681 \ - --hash=sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae \ - --hash=sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2 \ - --hash=sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb \ - --hash=sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5 \ - --hash=sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a \ - --hash=sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8 \ - --hash=sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98 \ - --hash=sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b \ - --hash=sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925 \ - --hash=sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6 \ - --hash=sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0 \ - --hash=sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9 \ - --hash=sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c \ - --hash=sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991 -yarl==1.18.3 \ - --hash=sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba \ - --hash=sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186 \ - --hash=sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50 \ - --hash=sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640 \ - --hash=sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8 \ - --hash=sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58 \ - --hash=sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2 \ - --hash=sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393 \ - --hash=sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c \ - --hash=sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272 \ - --hash=sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d \ - --hash=sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576 \ - --hash=sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477 \ - --hash=sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2 \ - --hash=sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512 \ - --hash=sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a \ - --hash=sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0 \ - --hash=sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8 \ - --hash=sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb \ - --hash=sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa \ - --hash=sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1 \ - --hash=sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10 \ - --hash=sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b \ - --hash=sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e \ - --hash=sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb \ - --hash=sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6 \ - --hash=sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285 \ - --hash=sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb \ - --hash=sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482 \ - --hash=sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75 \ - --hash=sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782 \ - --hash=sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53 \ - --hash=sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2 \ - --hash=sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1 +# uv export --all-extras --frozen --no-hashes +aiohappyeyeballs==2.4.4 +aiohttp==3.11.11 +aiosignal==1.3.2 +annotated-types==0.7.0 +anyio==4.8.0 +appnope==0.1.4 ; platform_system == 'Darwin' +argon2-cffi==23.1.0 +argon2-cffi-bindings==21.2.0 +arrow==1.3.0 +asttokens==3.0.0 +async-lru==2.0.4 +attrs==24.3.0 +azure-ai-documentintelligence==1.0.0 +azure-ai-textanalytics==5.3.0 +azure-ai-vision-imageanalysis==1.0.0 +azure-common==1.1.28 +azure-core==1.32.0 +azure-functions==1.21.3 +azure-identity==1.19.0 +azure-search==1.0.0b2 +azure-search-documents==11.6.0b8 +azure-storage-blob==12.24.0 +babel==2.16.0 +beautifulsoup4==4.12.3 +black==24.10.0 +bleach==6.2.0 +blis==0.7.11 +bs4==0.0.2 +catalogue==2.0.10 +certifi==2024.12.14 +cffi==1.17.1 +cfgv==3.4.0 +charset-normalizer==3.4.1 +click==8.1.8 +cloudpathlib==0.20.0 +colorama==0.4.6 ; sys_platform == 'win32' or platform_system == 'Windows' +comm==0.2.2 +confection==0.1.5 +cryptography==44.0.0 +cymem==2.0.11 +debugpy==1.8.12 +decorator==5.1.1 +defusedxml==0.7.1 +distlib==0.3.9 +distro==1.9.0 +en-core-web-md @ https://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.7.1/en_core_web_md-3.7.1.tar.gz +et-xmlfile==2.0.0 +executing==2.2.0 +fastjsonschema==2.21.1 +filelock==3.17.0 +fqdn==1.5.1 +frozenlist==1.5.0 +fsspec==2024.12.0 +h11==0.14.0 +httpcore==1.0.7 +httpx==0.28.1 +huggingface-hub==0.27.1 +identify==2.6.6 +idna==3.10 +ipykernel==6.29.5 +ipython==8.31.0 +ipywidgets==8.1.5 +isodate==0.7.2 +isoduration==20.11.0 +jedi==0.19.2 +jinja2==3.1.5 +jiter==0.8.2 +joblib==1.4.2 +json5==0.10.0 +jsonpointer==3.0.0 +jsonschema==4.23.0 +jsonschema-specifications==2024.10.1 +jupyter==1.1.1 +jupyter-client==8.6.3 +jupyter-console==6.6.3 +jupyter-core==5.7.2 +jupyter-events==0.11.0 +jupyter-lsp==2.2.5 +jupyter-server==2.15.0 +jupyter-server-terminals==0.5.3 +jupyterlab==4.3.4 +jupyterlab-pygments==0.3.0 +jupyterlab-server==2.27.3 +jupyterlab-widgets==3.0.13 +langcodes==3.5.0 +language-data==1.3.0 +marisa-trie==1.2.1 +markdown-it-py==3.0.0 +markupsafe==3.0.2 +matplotlib-inline==0.1.7 +mdurl==0.1.2 +mistune==3.1.0 +model2vec==0.3.7 +msal==1.31.1 +msal-extensions==1.2.0 +msrest==0.7.1 +multidict==6.1.0 +murmurhash==1.0.12 +mypy-extensions==1.0.0 +nbclient==0.10.2 +nbconvert==7.16.5 +nbformat==5.10.4 +nest-asyncio==1.6.0 +nodeenv==1.9.1 +notebook==7.3.2 +notebook-shim==0.2.4 +numpy==1.26.4 +oauthlib==3.2.2 +openai==1.60.0 +openpyxl==3.1.5 +overrides==7.7.0 +packaging==24.2 +pandas==2.2.3 +pandocfilters==1.5.1 +parso==0.8.4 +pathspec==0.12.1 +pexpect==4.9.0 ; sys_platform != 'emscripten' and sys_platform != 'win32' +pillow==11.1.0 +platformdirs==4.3.6 +portalocker==2.10.1 +pre-commit==4.1.0 +preshed==3.0.9 +prometheus-client==0.21.1 +prompt-toolkit==3.0.50 +propcache==0.2.1 +psutil==6.1.1 +ptyprocess==0.7.0 ; os_name != 'nt' or (sys_platform != 'emscripten' and sys_platform != 'win32') +pure-eval==0.2.3 +pycparser==2.22 +pydantic==2.10.5 +pydantic-core==2.27.2 +pygments==2.19.1 +pyjwt==2.10.1 +pymupdf==1.25.2 +python-dateutil==2.9.0.post0 +python-dotenv==1.0.1 +python-json-logger==3.2.1 +pytz==2024.2 +pywin32==308 ; (platform_python_implementation != 'PyPy' and sys_platform == 'win32') or platform_system == 'Windows' +pywinpty==2.0.14 ; os_name == 'nt' +pyyaml==6.0.2 +pyzmq==26.2.0 +referencing==0.36.1 +regex==2024.11.6 +requests==2.32.3 +requests-oauthlib==2.0.0 +rfc3339-validator==0.1.4 +rfc3986-validator==0.1.1 +rich==13.9.4 +rpds-py==0.22.3 +ruff==0.9.2 +safetensors==0.5.2 +send2trash==1.8.3 +setuptools==75.8.0 +shellingham==1.5.4 +six==1.17.0 +smart-open==7.1.0 +sniffio==1.3.1 +soupsieve==2.6 +spacy==3.7.5 +spacy-legacy==3.0.12 +spacy-loggers==1.0.5 +srsly==2.5.1 +stack-data==0.6.3 +tenacity==9.0.0 +terminado==0.18.1 +thinc==8.2.5 +tiktoken==0.8.0 +tinycss2==1.4.0 +tokenizers==0.21.0 +tornado==6.4.2 +tqdm==4.67.1 +traitlets==5.14.3 +typer==0.15.1 +types-python-dateutil==2.9.0.20241206 +typing-extensions==4.12.2 +tzdata==2025.1 +uri-template==1.3.0 +urllib3==2.3.0 +virtualenv==20.29.1 +wasabi==1.1.3 +wcwidth==0.2.13 +weasel==0.4.1 +webcolors==24.11.1 +webencodings==0.5.1 +websocket-client==1.8.0 +widgetsnbextension==4.0.13 +wrapt==1.17.2 +yarl==1.18.3 From f99c883521a0c2ad99146051f8cb5eae3b0cdcdc Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 20:02:35 +0000 Subject: [PATCH 42/64] udpate --- .pre-commit-config.yaml | 2 +- image_processing/src/image_processing/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7c94bb18..1e09eb9c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -57,5 +57,5 @@ repos: - id: compile-image-processing-requirements name: compile-image-processing-requirements language: system - entry: bash -c 'cd image_processing && exec uv export --all-extras --frozen --no-hashes > src/image_processing/requirements.txt' + entry: bash -c 'cd image_processing && exec uv export --all-extras --frozen --no-hashes --no-editable --no-sources --verbose > src/image_processing/requirements.txt' pass_filenames: false diff --git a/image_processing/src/image_processing/requirements.txt b/image_processing/src/image_processing/requirements.txt index 33079beb..2a3330fd 100644 --- a/image_processing/src/image_processing/requirements.txt +++ b/image_processing/src/image_processing/requirements.txt @@ -1,5 +1,5 @@ # This file was autogenerated by uv via the following command: -# uv export --all-extras --frozen --no-hashes +# uv export --all-extras --frozen --no-hashes --no-editable --no-sources aiohappyeyeballs==2.4.4 aiohttp==3.11.11 aiosignal==1.3.2 From a6f5a940e829ed8adf365e64e6b09685d455b858 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 20:06:19 +0000 Subject: [PATCH 43/64] Remove extra --- .pre-commit-config.yaml | 2 +- .../src/image_processing/requirements.txt | 92 +------------------ 2 files changed, 5 insertions(+), 89 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1e09eb9c..afc3dc14 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -57,5 +57,5 @@ repos: - id: compile-image-processing-requirements name: compile-image-processing-requirements language: system - entry: bash -c 'cd image_processing && exec uv export --all-extras --frozen --no-hashes --no-editable --no-sources --verbose > src/image_processing/requirements.txt' + entry: bash -c 'cd image_processing && exec uv export --frozen --no-hashes --no-editable --no-sources --verbose --no-group dev > src/image_processing/requirements.txt' pass_filenames: false diff --git a/image_processing/src/image_processing/requirements.txt b/image_processing/src/image_processing/requirements.txt index 2a3330fd..c3bca5fc 100644 --- a/image_processing/src/image_processing/requirements.txt +++ b/image_processing/src/image_processing/requirements.txt @@ -1,16 +1,10 @@ # This file was autogenerated by uv via the following command: -# uv export --all-extras --frozen --no-hashes --no-editable --no-sources +# uv export --frozen --no-hashes --no-editable --no-sources --no-group dev aiohappyeyeballs==2.4.4 aiohttp==3.11.11 aiosignal==1.3.2 annotated-types==0.7.0 anyio==4.8.0 -appnope==0.1.4 ; platform_system == 'Darwin' -argon2-cffi==23.1.0 -argon2-cffi-bindings==21.2.0 -arrow==1.3.0 -asttokens==3.0.0 -async-lru==2.0.4 attrs==24.3.0 azure-ai-documentintelligence==1.0.0 azure-ai-textanalytics==5.3.0 @@ -22,113 +16,57 @@ azure-identity==1.19.0 azure-search==1.0.0b2 azure-search-documents==11.6.0b8 azure-storage-blob==12.24.0 -babel==2.16.0 beautifulsoup4==4.12.3 -black==24.10.0 -bleach==6.2.0 blis==0.7.11 bs4==0.0.2 catalogue==2.0.10 certifi==2024.12.14 -cffi==1.17.1 -cfgv==3.4.0 +cffi==1.17.1 ; platform_python_implementation != 'PyPy' charset-normalizer==3.4.1 click==8.1.8 cloudpathlib==0.20.0 colorama==0.4.6 ; sys_platform == 'win32' or platform_system == 'Windows' -comm==0.2.2 confection==0.1.5 cryptography==44.0.0 cymem==2.0.11 -debugpy==1.8.12 -decorator==5.1.1 -defusedxml==0.7.1 -distlib==0.3.9 distro==1.9.0 en-core-web-md @ https://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.7.1/en_core_web_md-3.7.1.tar.gz et-xmlfile==2.0.0 -executing==2.2.0 -fastjsonschema==2.21.1 filelock==3.17.0 -fqdn==1.5.1 frozenlist==1.5.0 fsspec==2024.12.0 h11==0.14.0 httpcore==1.0.7 httpx==0.28.1 huggingface-hub==0.27.1 -identify==2.6.6 idna==3.10 -ipykernel==6.29.5 -ipython==8.31.0 -ipywidgets==8.1.5 isodate==0.7.2 -isoduration==20.11.0 -jedi==0.19.2 jinja2==3.1.5 jiter==0.8.2 joblib==1.4.2 -json5==0.10.0 -jsonpointer==3.0.0 -jsonschema==4.23.0 -jsonschema-specifications==2024.10.1 -jupyter==1.1.1 -jupyter-client==8.6.3 -jupyter-console==6.6.3 -jupyter-core==5.7.2 -jupyter-events==0.11.0 -jupyter-lsp==2.2.5 -jupyter-server==2.15.0 -jupyter-server-terminals==0.5.3 -jupyterlab==4.3.4 -jupyterlab-pygments==0.3.0 -jupyterlab-server==2.27.3 -jupyterlab-widgets==3.0.13 langcodes==3.5.0 language-data==1.3.0 marisa-trie==1.2.1 markdown-it-py==3.0.0 markupsafe==3.0.2 -matplotlib-inline==0.1.7 mdurl==0.1.2 -mistune==3.1.0 model2vec==0.3.7 msal==1.31.1 msal-extensions==1.2.0 msrest==0.7.1 multidict==6.1.0 murmurhash==1.0.12 -mypy-extensions==1.0.0 -nbclient==0.10.2 -nbconvert==7.16.5 -nbformat==5.10.4 -nest-asyncio==1.6.0 -nodeenv==1.9.1 -notebook==7.3.2 -notebook-shim==0.2.4 numpy==1.26.4 oauthlib==3.2.2 openai==1.60.0 openpyxl==3.1.5 -overrides==7.7.0 packaging==24.2 pandas==2.2.3 -pandocfilters==1.5.1 -parso==0.8.4 -pathspec==0.12.1 -pexpect==4.9.0 ; sys_platform != 'emscripten' and sys_platform != 'win32' pillow==11.1.0 -platformdirs==4.3.6 portalocker==2.10.1 -pre-commit==4.1.0 preshed==3.0.9 -prometheus-client==0.21.1 -prompt-toolkit==3.0.50 propcache==0.2.1 -psutil==6.1.1 -ptyprocess==0.7.0 ; os_name != 'nt' or (sys_platform != 'emscripten' and sys_platform != 'win32') -pure-eval==0.2.3 -pycparser==2.22 +pycparser==2.22 ; platform_python_implementation != 'PyPy' pydantic==2.10.5 pydantic-core==2.27.2 pygments==2.19.1 @@ -136,23 +74,14 @@ pyjwt==2.10.1 pymupdf==1.25.2 python-dateutil==2.9.0.post0 python-dotenv==1.0.1 -python-json-logger==3.2.1 pytz==2024.2 -pywin32==308 ; (platform_python_implementation != 'PyPy' and sys_platform == 'win32') or platform_system == 'Windows' -pywinpty==2.0.14 ; os_name == 'nt' +pywin32==308 ; platform_system == 'Windows' pyyaml==6.0.2 -pyzmq==26.2.0 -referencing==0.36.1 regex==2024.11.6 requests==2.32.3 requests-oauthlib==2.0.0 -rfc3339-validator==0.1.4 -rfc3986-validator==0.1.1 rich==13.9.4 -rpds-py==0.22.3 -ruff==0.9.2 safetensors==0.5.2 -send2trash==1.8.3 setuptools==75.8.0 shellingham==1.5.4 six==1.17.0 @@ -163,29 +92,16 @@ spacy==3.7.5 spacy-legacy==3.0.12 spacy-loggers==1.0.5 srsly==2.5.1 -stack-data==0.6.3 tenacity==9.0.0 -terminado==0.18.1 thinc==8.2.5 tiktoken==0.8.0 -tinycss2==1.4.0 tokenizers==0.21.0 -tornado==6.4.2 tqdm==4.67.1 -traitlets==5.14.3 typer==0.15.1 -types-python-dateutil==2.9.0.20241206 typing-extensions==4.12.2 tzdata==2025.1 -uri-template==1.3.0 urllib3==2.3.0 -virtualenv==20.29.1 wasabi==1.1.3 -wcwidth==0.2.13 weasel==0.4.1 -webcolors==24.11.1 -webencodings==0.5.1 -websocket-client==1.8.0 -widgetsnbextension==4.0.13 wrapt==1.17.2 yarl==1.18.3 From aab7b413eeb244ac9c7d4ad2d0f8525f20c94ee0 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 20:09:24 +0000 Subject: [PATCH 44/64] new pre commit --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index afc3dc14..dd5675ee 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -57,5 +57,5 @@ repos: - id: compile-image-processing-requirements name: compile-image-processing-requirements language: system - entry: bash -c 'cd image_processing && exec uv export --frozen --no-hashes --no-editable --no-sources --verbose --no-group dev > src/image_processing/requirements.txt' + entry: bash -c 'cd image_processing && exec uv export --frozen --no-hashes --no-editable --no-sources --verbose --no-group dev > src/image_processing/requirements.txt && cat src/image_processing/requirements.txt' pass_filenames: false From 5b965f633b5b6e3cfebe987128fee3e5843cc031 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 20:12:56 +0000 Subject: [PATCH 45/64] Update --- deploy_ai_search_indexes/pyproject.toml | 2 +- image_processing/pyproject.toml | 2 +- pyproject.toml | 2 +- text_2_sql/autogen/pyproject.toml | 2 +- text_2_sql/text_2_sql_core/pyproject.toml | 2 +- uv.lock | 345 +++++++++++++++++++++- 6 files changed, 349 insertions(+), 6 deletions(-) diff --git a/deploy_ai_search_indexes/pyproject.toml b/deploy_ai_search_indexes/pyproject.toml index 5ce4fe43..b0b555b9 100644 --- a/deploy_ai_search_indexes/pyproject.toml +++ b/deploy_ai_search_indexes/pyproject.toml @@ -6,7 +6,7 @@ readme = "README.md" authors = [ { name = "Ben Constable", email = "benconstable@microsoft.com" } ] -requires-python = ">=3.12" +requires-python = ">=3.11" dependencies = [ "azure-identity>=1.19.0", "azure-mgmt-web>=7.3.1", diff --git a/image_processing/pyproject.toml b/image_processing/pyproject.toml index cf376f18..c7b082e2 100644 --- a/image_processing/pyproject.toml +++ b/image_processing/pyproject.toml @@ -6,7 +6,7 @@ readme = "README.md" authors = [ { name = "Ben Constable", email = "benconstable@microsoft.com" } ] -requires-python = ">=3.12" +requires-python = ">=3.11" dependencies = [ "azure-functions>=1.21.3", "azure-identity>=1.19.0", diff --git a/pyproject.toml b/pyproject.toml index 5bd2d5ce..1a8292b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "dstoolkit-text2sql-and-imageprocessing" version = "0.1.0" description = "This repo accelerates development of RAG applications with rich data sources including SQL Warehouses and documents analysed with Azure Document Intelligence." readme = "README.md" -requires-python = ">=3.12" +requires-python = ">=3.11" dependencies = [ "deploy_ai_search_indexes", "image_processing", diff --git a/text_2_sql/autogen/pyproject.toml b/text_2_sql/autogen/pyproject.toml index 4d4273b1..174aa9af 100644 --- a/text_2_sql/autogen/pyproject.toml +++ b/text_2_sql/autogen/pyproject.toml @@ -6,7 +6,7 @@ readme = "README.md" authors = [ { name = "Ben Constable", email = "benconstable@microsoft.com" } ] -requires-python = ">=3.12" +requires-python = ">=3.11" dependencies = [ "aiostream>=0.6.4", "autogen-agentchat==0.4.2", diff --git a/text_2_sql/text_2_sql_core/pyproject.toml b/text_2_sql/text_2_sql_core/pyproject.toml index 852de481..b6e7fd04 100644 --- a/text_2_sql/text_2_sql_core/pyproject.toml +++ b/text_2_sql/text_2_sql_core/pyproject.toml @@ -6,7 +6,7 @@ readme = "README.md" authors = [ { name = "Ben Constable", email = "benconstable@microsoft.com" } ] -requires-python = ">=3.12" +requires-python = ">=3.11" dependencies = [ "aiohttp>=3.11.11", "aioodbc>=0.5.0", diff --git a/uv.lock b/uv.lock index d25e1ea5..01b1b134 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,9 @@ version = 1 -requires-python = ">=3.12" +requires-python = ">=3.11" +resolution-markers = [ + "python_full_version < '3.12'", + "python_full_version >= '3.12'", +] [manifest] members = [ @@ -43,6 +47,21 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/fe/ed/f26db39d29cd3cb2f5a3374304c713fe5ab5a0e4c8ee25a0c45cc6adf844/aiohttp-3.11.11.tar.gz", hash = "sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e", size = 7669618 } wheels = [ + { url = "https://files.pythonhosted.org/packages/34/ae/e8806a9f054e15f1d18b04db75c23ec38ec954a10c0a68d3bd275d7e8be3/aiohttp-3.11.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ba74ec819177af1ef7f59063c6d35a214a8fde6f987f7661f4f0eecc468a8f76", size = 708624 }, + { url = "https://files.pythonhosted.org/packages/c7/e0/313ef1a333fb4d58d0c55a6acb3cd772f5d7756604b455181049e222c020/aiohttp-3.11.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4af57160800b7a815f3fe0eba9b46bf28aafc195555f1824555fa2cfab6c1538", size = 468507 }, + { url = "https://files.pythonhosted.org/packages/a9/60/03455476bf1f467e5b4a32a465c450548b2ce724eec39d69f737191f936a/aiohttp-3.11.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffa336210cf9cd8ed117011085817d00abe4c08f99968deef0013ea283547204", size = 455571 }, + { url = "https://files.pythonhosted.org/packages/be/f9/469588603bd75bf02c8ffb8c8a0d4b217eed446b49d4a767684685aa33fd/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81b8fe282183e4a3c7a1b72f5ade1094ed1c6345a8f153506d114af5bf8accd9", size = 1685694 }, + { url = "https://files.pythonhosted.org/packages/88/b9/1b7fa43faf6c8616fa94c568dc1309ffee2b6b68b04ac268e5d64b738688/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af41686ccec6a0f2bdc66686dc0f403c41ac2089f80e2214a0f82d001052c03", size = 1743660 }, + { url = "https://files.pythonhosted.org/packages/2a/8b/0248d19dbb16b67222e75f6aecedd014656225733157e5afaf6a6a07e2e8/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70d1f9dde0e5dd9e292a6d4d00058737052b01f3532f69c0c65818dac26dc287", size = 1785421 }, + { url = "https://files.pythonhosted.org/packages/c4/11/f478e071815a46ca0a5ae974651ff0c7a35898c55063305a896e58aa1247/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:249cc6912405917344192b9f9ea5cd5b139d49e0d2f5c7f70bdfaf6b4dbf3a2e", size = 1675145 }, + { url = "https://files.pythonhosted.org/packages/26/5d/284d182fecbb5075ae10153ff7374f57314c93a8681666600e3a9e09c505/aiohttp-3.11.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0eb98d90b6690827dcc84c246811feeb4e1eea683c0eac6caed7549be9c84665", size = 1619804 }, + { url = "https://files.pythonhosted.org/packages/1b/78/980064c2ad685c64ce0e8aeeb7ef1e53f43c5b005edcd7d32e60809c4992/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec82bf1fda6cecce7f7b915f9196601a1bd1a3079796b76d16ae4cce6d0ef89b", size = 1654007 }, + { url = "https://files.pythonhosted.org/packages/21/8d/9e658d63b1438ad42b96f94da227f2e2c1d5c6001c9e8ffcc0bfb22e9105/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9fd46ce0845cfe28f108888b3ab17abff84ff695e01e73657eec3f96d72eef34", size = 1650022 }, + { url = "https://files.pythonhosted.org/packages/85/fd/a032bf7f2755c2df4f87f9effa34ccc1ef5cea465377dbaeef93bb56bbd6/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:bd176afcf8f5d2aed50c3647d4925d0db0579d96f75a31e77cbaf67d8a87742d", size = 1732899 }, + { url = "https://files.pythonhosted.org/packages/c5/0c/c2b85fde167dd440c7ba50af2aac20b5a5666392b174df54c00f888c5a75/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ec2aa89305006fba9ffb98970db6c8221541be7bee4c1d027421d6f6df7d1ce2", size = 1755142 }, + { url = "https://files.pythonhosted.org/packages/bc/78/91ae1a3b3b3bed8b893c5d69c07023e151b1c95d79544ad04cf68f596c2f/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:92cde43018a2e17d48bb09c79e4d4cb0e236de5063ce897a5e40ac7cb4878773", size = 1692736 }, + { url = "https://files.pythonhosted.org/packages/77/89/a7ef9c4b4cdb546fcc650ca7f7395aaffbd267f0e1f648a436bec33c9b95/aiohttp-3.11.11-cp311-cp311-win32.whl", hash = "sha256:aba807f9569455cba566882c8938f1a549f205ee43c27b126e5450dc9f83cc62", size = 416418 }, + { url = "https://files.pythonhosted.org/packages/fc/db/2192489a8a51b52e06627506f8ac8df69ee221de88ab9bdea77aa793aa6a/aiohttp-3.11.11-cp311-cp311-win_amd64.whl", hash = "sha256:ae545f31489548c87b0cced5755cfe5a5308d00407000e72c4fa30b19c3220ac", size = 442509 }, { url = "https://files.pythonhosted.org/packages/69/cf/4bda538c502f9738d6b95ada11603c05ec260807246e15e869fc3ec5de97/aiohttp-3.11.11-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886", size = 704666 }, { url = "https://files.pythonhosted.org/packages/46/7b/87fcef2cad2fad420ca77bef981e815df6904047d0a1bd6aeded1b0d1d66/aiohttp-3.11.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2", size = 464057 }, { url = "https://files.pythonhosted.org/packages/5a/a6/789e1f17a1b6f4a38939fbc39d29e1d960d5f89f73d0629a939410171bc0/aiohttp-3.11.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c", size = 455996 }, @@ -553,6 +572,10 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/d8/0d/cc2fb42b8c50d80143221515dd7e4766995bd07c56c9a3ed30baf080b6dc/black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875", size = 645813 } wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/cc/7496bb63a9b06a954d3d0ac9fe7a73f3bf1cd92d7a58877c27f4ad1e9d41/black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad", size = 1607468 }, + { url = "https://files.pythonhosted.org/packages/2b/e3/69a738fb5ba18b5422f50b4f143544c664d7da40f09c13969b2fd52900e0/black-24.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50", size = 1437270 }, + { url = "https://files.pythonhosted.org/packages/c9/9b/2db8045b45844665c720dcfe292fdaf2e49825810c0103e1191515fc101a/black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392", size = 1737061 }, + { url = "https://files.pythonhosted.org/packages/a3/95/17d4a09a5be5f8c65aa4a361444d95edc45def0de887810f508d3f65db7a/black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175", size = 1423293 }, { url = "https://files.pythonhosted.org/packages/90/04/bf74c71f592bcd761610bbf67e23e6a3cff824780761f536512437f1e655/black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3", size = 1644256 }, { url = "https://files.pythonhosted.org/packages/4c/ea/a77bab4cf1887f4b2e0bce5516ea0b3ff7d04ba96af21d65024629afedb6/black-24.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65", size = 1448534 }, { url = "https://files.pythonhosted.org/packages/4e/3e/443ef8bc1fbda78e61f79157f303893f3fddf19ca3c8989b163eb3469a12/black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f", size = 1761892 }, @@ -590,6 +613,11 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/51/8c/60c85350f2e1c9647df580083a0f6acc686ef32d1a91f4ab0c624b3ff867/blis-0.7.11.tar.gz", hash = "sha256:cec6d48f75f7ac328ae1b6fbb372dde8c8a57c89559172277f66e01ff08d4d42", size = 2897107 } wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/59/c8010f380a16709e6d3ef5534845d1ca1e689079914ec67ab60f57edfc37/blis-0.7.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1b68df4d01d62f9adaef3dad6f96418787265a6878891fc4e0fabafd6d02afba", size = 6123547 }, + { url = "https://files.pythonhosted.org/packages/a8/73/0a9d4e7f6e78ef270e3a4532b17e060a02087590cf615ba9943fd1a283e9/blis-0.7.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:162e60d941a8151418d558a94ee5547cb1bbeed9f26b3b6f89ec9243f111a201", size = 1106895 }, + { url = "https://files.pythonhosted.org/packages/51/f7/a5d9a0be0729f4172248dbae74d7e02b139b3a32cc29650d3ade7ab91fea/blis-0.7.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:686a7d0111d5ba727cd62f374748952fd6eb74701b18177f525b16209a253c01", size = 1707389 }, + { url = "https://files.pythonhosted.org/packages/dc/23/eb01450dc284a7ea8ebc0e5296f1f8fdbe5299169f4c318f836b4284a119/blis-0.7.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0421d6e44cda202b113a34761f9a062b53f8c2ae8e4ec8325a76e709fca93b6e", size = 10172888 }, + { url = "https://files.pythonhosted.org/packages/2f/09/da0592c74560cc33396504698122f7a56747c82a5e072ca7d2c3397898e1/blis-0.7.11-cp311-cp311-win_amd64.whl", hash = "sha256:0dc9dcb3843045b6b8b00432409fd5ee96b8344a324e031bfec7303838c41a1a", size = 6602835 }, { url = "https://files.pythonhosted.org/packages/e2/12/90897bc489626cb71e51ce8bb89e492fabe96a57811e53159c0f74ae90ec/blis-0.7.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dadf8713ea51d91444d14ad4104a5493fa7ecc401bbb5f4a203ff6448fadb113", size = 6121528 }, { url = "https://files.pythonhosted.org/packages/e2/5d/67a3f6b6108c39d3fd1cf55a7dca9267152190dad419c9de6d764b3708ca/blis-0.7.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5bcdaf370f03adaf4171d6405a89fa66cb3c09399d75fc02e1230a78cd2759e4", size = 1105039 }, { url = "https://files.pythonhosted.org/packages/03/62/0d214dde0703863ed2d3dabb3f10606f7f55ac4eb07a52c3906601331b63/blis-0.7.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7de19264b1d49a178bf8035406d0ae77831f3bfaa3ce02942964a81a202abb03", size = 1701009 }, @@ -636,6 +664,18 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 } wheels = [ + { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264 }, + { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651 }, + { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259 }, + { url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200 }, + { url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235 }, + { url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721 }, + { url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242 }, + { url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999 }, + { url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242 }, + { url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604 }, + { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727 }, + { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400 }, { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 }, { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 }, { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 }, @@ -675,6 +715,19 @@ version = "3.4.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/16/b0/572805e227f01586461c80e0fd25d65a2115599cc9dad142fee4b747c357/charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", size = 123188 } wheels = [ + { url = "https://files.pythonhosted.org/packages/72/80/41ef5d5a7935d2d3a773e3eaebf0a9350542f2cab4eac59a7a4741fbbbbe/charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125", size = 194995 }, + { url = "https://files.pythonhosted.org/packages/7a/28/0b9fefa7b8b080ec492110af6d88aa3dea91c464b17d53474b6e9ba5d2c5/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1", size = 139471 }, + { url = "https://files.pythonhosted.org/packages/71/64/d24ab1a997efb06402e3fc07317e94da358e2585165930d9d59ad45fcae2/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3", size = 149831 }, + { url = "https://files.pythonhosted.org/packages/37/ed/be39e5258e198655240db5e19e0b11379163ad7070962d6b0c87ed2c4d39/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd", size = 142335 }, + { url = "https://files.pythonhosted.org/packages/88/83/489e9504711fa05d8dde1574996408026bdbdbd938f23be67deebb5eca92/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00", size = 143862 }, + { url = "https://files.pythonhosted.org/packages/c6/c7/32da20821cf387b759ad24627a9aca289d2822de929b8a41b6241767b461/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12", size = 145673 }, + { url = "https://files.pythonhosted.org/packages/68/85/f4288e96039abdd5aeb5c546fa20a37b50da71b5cf01e75e87f16cd43304/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77", size = 140211 }, + { url = "https://files.pythonhosted.org/packages/28/a3/a42e70d03cbdabc18997baf4f0227c73591a08041c149e710045c281f97b/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146", size = 148039 }, + { url = "https://files.pythonhosted.org/packages/85/e4/65699e8ab3014ecbe6f5c71d1a55d810fb716bbfd74f6283d5c2aa87febf/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd", size = 151939 }, + { url = "https://files.pythonhosted.org/packages/b1/82/8e9fe624cc5374193de6860aba3ea8070f584c8565ee77c168ec13274bd2/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6", size = 149075 }, + { url = "https://files.pythonhosted.org/packages/3d/7b/82865ba54c765560c8433f65e8acb9217cb839a9e32b42af4aa8e945870f/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8", size = 144340 }, + { url = "https://files.pythonhosted.org/packages/b5/b6/9674a4b7d4d99a0d2df9b215da766ee682718f88055751e1e5e753c82db0/charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b", size = 95205 }, + { url = "https://files.pythonhosted.org/packages/1e/ab/45b180e175de4402dcf7547e4fb617283bae54ce35c27930a6f35b6bef15/charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76", size = 102441 }, { url = "https://files.pythonhosted.org/packages/0a/9a/dd1e1cdceb841925b7798369a09279bd1cf183cef0f9ddf15a3a6502ee45/charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545", size = 196105 }, { url = "https://files.pythonhosted.org/packages/d3/8c/90bfabf8c4809ecb648f39794cf2a84ff2e7d2a6cf159fe68d9a26160467/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7", size = 140404 }, { url = "https://files.pythonhosted.org/packages/ad/8f/e410d57c721945ea3b4f1a04b74f70ce8fa800d393d72899f0a40526401f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757", size = 150423 }, @@ -796,6 +849,13 @@ version = "2.0.11" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f2/4a/1acd761fb6ac4c560e823ce40536a62f886f2d59b2763b5c3fc7e9d92101/cymem-2.0.11.tar.gz", hash = "sha256:efe49a349d4a518be6b6c6b255d4a80f740a341544bde1a807707c058b88d0bd", size = 10346 } wheels = [ + { url = "https://files.pythonhosted.org/packages/03/e3/d98e3976f4ffa99cddebc1ce379d4d62e3eb1da22285267f902c99cc3395/cymem-2.0.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3ee54039aad3ef65de82d66c40516bf54586287b46d32c91ea0530c34e8a2745", size = 42005 }, + { url = "https://files.pythonhosted.org/packages/41/b4/7546faf2ab63e59befc95972316d62276cec153f7d4d60e7b0d5e08f0602/cymem-2.0.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c05ef75b5db217be820604e43a47ccbbafea98ab6659d07cea92fa3c864ea58", size = 41747 }, + { url = "https://files.pythonhosted.org/packages/7d/4e/042f372e5b3eb7f5f3dd7677161771d301de2b6fa3f7c74e1cebcd502552/cymem-2.0.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8d5381e5793ce531bac0dbc00829c8381f18605bb67e4b61d34f8850463da40", size = 217647 }, + { url = "https://files.pythonhosted.org/packages/48/cb/2207679e4b92701f78cf141e1ab4f81f55247dbe154eb426b842a0a993de/cymem-2.0.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2b9d3f42d7249ac81802135cad51d707def058001a32f73fc7fbf3de7045ac7", size = 218857 }, + { url = "https://files.pythonhosted.org/packages/31/7a/76ae3b7a39ab2531029d281e43fcfcaad728c2341b150a81a3a1f5587cf3/cymem-2.0.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:39b78f2195d20b75c2d465732f6b8e8721c5d4eb012777c2cb89bdb45a043185", size = 206148 }, + { url = "https://files.pythonhosted.org/packages/25/f9/d0fc0191ac79f15638ddb59237aa76f234691374d7d7950e10f384bd8a25/cymem-2.0.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2203bd6525a80d8fd0c94654a263af21c0387ae1d5062cceaebb652bf9bad7bc", size = 207112 }, + { url = "https://files.pythonhosted.org/packages/56/c8/75f75889401b20f4c3a7c5965dda09df42913e904ddc2ffe7ef3bdf25061/cymem-2.0.11-cp311-cp311-win_amd64.whl", hash = "sha256:aa54af7314de400634448da1f935b61323da80a49484074688d344fb2036681b", size = 39360 }, { url = "https://files.pythonhosted.org/packages/71/67/0d74f7e9d79f934368a78fb1d1466b94bebdbff14f8ae94dd3e4ea8738bb/cymem-2.0.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a0fbe19ce653cd688842d81e5819dc63f911a26e192ef30b0b89f0ab2b192ff2", size = 42621 }, { url = "https://files.pythonhosted.org/packages/4a/d6/f7a19c63b48efc3f00a3ee8d69070ac90202e1e378f6cf81b8671f0cf762/cymem-2.0.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de72101dc0e6326f6a2f73e05a438d1f3c6110d41044236d0fbe62925091267d", size = 42249 }, { url = "https://files.pythonhosted.org/packages/d7/60/cdc434239813eef547fb99b6d0bafe31178501702df9b77c4108c9a216f6/cymem-2.0.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee4395917f6588b8ac1699499128842768b391fe8896e8626950b4da5f9a406", size = 224758 }, @@ -837,6 +897,10 @@ version = "1.8.12" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/68/25/c74e337134edf55c4dfc9af579eccb45af2393c40960e2795a94351e8140/debugpy-1.8.12.tar.gz", hash = "sha256:646530b04f45c830ceae8e491ca1c9320a2d2f0efea3141487c82130aba70dce", size = 1641122 } wheels = [ + { url = "https://files.pythonhosted.org/packages/af/9f/5b8af282253615296264d4ef62d14a8686f0dcdebb31a669374e22fff0a4/debugpy-1.8.12-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:36f4829839ef0afdfdd208bb54f4c3d0eea86106d719811681a8627ae2e53dd5", size = 2174643 }, + { url = "https://files.pythonhosted.org/packages/ef/31/f9274dcd3b0f9f7d1e60373c3fa4696a585c55acb30729d313bb9d3bcbd1/debugpy-1.8.12-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a28ed481d530e3138553be60991d2d61103ce6da254e51547b79549675f539b7", size = 3133457 }, + { url = "https://files.pythonhosted.org/packages/ab/ca/6ee59e9892e424477e0c76e3798046f1fd1288040b927319c7a7b0baa484/debugpy-1.8.12-cp311-cp311-win32.whl", hash = "sha256:4ad9a94d8f5c9b954e0e3b137cc64ef3f579d0df3c3698fe9c3734ee397e4abb", size = 5106220 }, + { url = "https://files.pythonhosted.org/packages/d5/1a/8ab508ab05ede8a4eae3b139bbc06ea3ca6234f9e8c02713a044f253be5e/debugpy-1.8.12-cp311-cp311-win_amd64.whl", hash = "sha256:4703575b78dd697b294f8c65588dc86874ed787b7348c65da70cfc885efdf1e1", size = 5130481 }, { url = "https://files.pythonhosted.org/packages/ba/e6/0f876ecfe5831ebe4762b19214364753c8bc2b357d28c5d739a1e88325c7/debugpy-1.8.12-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:7e94b643b19e8feb5215fa508aee531387494bf668b2eca27fa769ea11d9f498", size = 2500846 }, { url = "https://files.pythonhosted.org/packages/19/64/33f41653a701f3cd2cbff8b41ebaad59885b3428b5afd0d93d16012ecf17/debugpy-1.8.12-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:086b32e233e89a2740c1615c2f775c34ae951508b28b308681dbbb87bba97d06", size = 4222181 }, { url = "https://files.pythonhosted.org/packages/32/a6/02646cfe50bfacc9b71321c47dc19a46e35f4e0aceea227b6d205e900e34/debugpy-1.8.12-cp312-cp312-win32.whl", hash = "sha256:2ae5df899732a6051b49ea2632a9ea67f929604fd2b036613a9f12bc3163b92d", size = 5227017 }, @@ -1063,6 +1127,21 @@ version = "1.5.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/8f/ed/0f4cec13a93c02c47ec32d81d11c0c1efbadf4a471e3f3ce7cad366cbbd3/frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817", size = 39930 } wheels = [ + { url = "https://files.pythonhosted.org/packages/79/43/0bed28bf5eb1c9e4301003b74453b8e7aa85fb293b31dde352aac528dafc/frozenlist-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30", size = 94987 }, + { url = "https://files.pythonhosted.org/packages/bb/bf/b74e38f09a246e8abbe1e90eb65787ed745ccab6eaa58b9c9308e052323d/frozenlist-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5", size = 54584 }, + { url = "https://files.pythonhosted.org/packages/2c/31/ab01375682f14f7613a1ade30149f684c84f9b8823a4391ed950c8285656/frozenlist-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778", size = 52499 }, + { url = "https://files.pythonhosted.org/packages/98/a8/d0ac0b9276e1404f58fec3ab6e90a4f76b778a49373ccaf6a563f100dfbc/frozenlist-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a", size = 276357 }, + { url = "https://files.pythonhosted.org/packages/ad/c9/c7761084fa822f07dac38ac29f841d4587570dd211e2262544aa0b791d21/frozenlist-1.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869", size = 287516 }, + { url = "https://files.pythonhosted.org/packages/a1/ff/cd7479e703c39df7bdab431798cef89dc75010d8aa0ca2514c5b9321db27/frozenlist-1.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d", size = 283131 }, + { url = "https://files.pythonhosted.org/packages/59/a0/370941beb47d237eca4fbf27e4e91389fd68699e6f4b0ebcc95da463835b/frozenlist-1.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45", size = 261320 }, + { url = "https://files.pythonhosted.org/packages/b8/5f/c10123e8d64867bc9b4f2f510a32042a306ff5fcd7e2e09e5ae5100ee333/frozenlist-1.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d", size = 274877 }, + { url = "https://files.pythonhosted.org/packages/fa/79/38c505601ae29d4348f21706c5d89755ceded02a745016ba2f58bd5f1ea6/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3", size = 269592 }, + { url = "https://files.pythonhosted.org/packages/19/e2/39f3a53191b8204ba9f0bb574b926b73dd2efba2a2b9d2d730517e8f7622/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a", size = 265934 }, + { url = "https://files.pythonhosted.org/packages/d5/c9/3075eb7f7f3a91f1a6b00284af4de0a65a9ae47084930916f5528144c9dd/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9", size = 283859 }, + { url = "https://files.pythonhosted.org/packages/05/f5/549f44d314c29408b962fa2b0e69a1a67c59379fb143b92a0a065ffd1f0f/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2", size = 287560 }, + { url = "https://files.pythonhosted.org/packages/9d/f8/cb09b3c24a3eac02c4c07a9558e11e9e244fb02bf62c85ac2106d1eb0c0b/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf", size = 277150 }, + { url = "https://files.pythonhosted.org/packages/37/48/38c2db3f54d1501e692d6fe058f45b6ad1b358d82cd19436efab80cfc965/frozenlist-1.5.0-cp311-cp311-win32.whl", hash = "sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942", size = 45244 }, + { url = "https://files.pythonhosted.org/packages/ca/8c/2ddffeb8b60a4bce3b196c32fcc30d8830d4615e7b492ec2071da801b8ad/frozenlist-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d", size = 51634 }, { url = "https://files.pythonhosted.org/packages/79/73/fa6d1a96ab7fd6e6d1c3500700963eab46813847f01ef0ccbaa726181dd5/frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21", size = 94026 }, { url = "https://files.pythonhosted.org/packages/ab/04/ea8bf62c8868b8eada363f20ff1b647cf2e93377a7b284d36062d21d81d1/frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d", size = 54150 }, { url = "https://files.pythonhosted.org/packages/d0/9a/8e479b482a6f2070b26bda572c5e6889bb3ba48977e81beea35b5ae13ece/frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e", size = 51927 }, @@ -1111,6 +1190,15 @@ version = "1.69.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e4/87/06a145284cbe86c91ca517fe6b57be5efbb733c0d6374b407f0992054d18/grpcio-1.69.0.tar.gz", hash = "sha256:936fa44241b5379c5afc344e1260d467bee495747eaf478de825bab2791da6f5", size = 12738244 } wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/cd/ca256aeef64047881586331347cd5a68a4574ba1a236e293cd8eba34e355/grpcio-1.69.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:8de1b192c29b8ce45ee26a700044717bcbbd21c697fa1124d440548964328561", size = 5198734 }, + { url = "https://files.pythonhosted.org/packages/37/3f/10c1e5e0150bf59aa08ea6aebf38f87622f95f7f33f98954b43d1b2a3200/grpcio-1.69.0-cp311-cp311-macosx_10_14_universal2.whl", hash = "sha256:7e76accf38808f5c5c752b0ab3fd919eb14ff8fafb8db520ad1cc12afff74de6", size = 11135285 }, + { url = "https://files.pythonhosted.org/packages/08/61/61cd116a572203a740684fcba3fef37a3524f1cf032b6568e1e639e59db0/grpcio-1.69.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:d5658c3c2660417d82db51e168b277e0ff036d0b0f859fa7576c0ffd2aec1442", size = 5699468 }, + { url = "https://files.pythonhosted.org/packages/01/f1/a841662e8e2465ba171c973b77d18fa7438ced535519b3c53617b7e6e25c/grpcio-1.69.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5494d0e52bf77a2f7eb17c6da662886ca0a731e56c1c85b93505bece8dc6cf4c", size = 6332337 }, + { url = "https://files.pythonhosted.org/packages/62/b1/c30e932e02c2e0bfdb8df46fe3b0c47f518fb04158ebdc0eb96cc97d642f/grpcio-1.69.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ed866f9edb574fd9be71bf64c954ce1b88fc93b2a4cbf94af221e9426eb14d6", size = 5949844 }, + { url = "https://files.pythonhosted.org/packages/5e/cb/55327d43b6286100ffae7d1791be6178d13c917382f3e9f43f82e8b393cf/grpcio-1.69.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c5ba38aeac7a2fe353615c6b4213d1fbb3a3c34f86b4aaa8be08baaaee8cc56d", size = 6661828 }, + { url = "https://files.pythonhosted.org/packages/6f/e4/120d72ae982d51cb9cabcd9672f8a1c6d62011b493a4d049d2abdf564db0/grpcio-1.69.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f79e05f5bbf551c4057c227d1b041ace0e78462ac8128e2ad39ec58a382536d2", size = 6226026 }, + { url = "https://files.pythonhosted.org/packages/96/e8/2cc15f11db506d7b1778f0587fa7bdd781602b05b3c4d75b7ca13de33d62/grpcio-1.69.0-cp311-cp311-win32.whl", hash = "sha256:bf1f8be0da3fcdb2c1e9f374f3c2d043d606d69f425cd685110dd6d0d2d61258", size = 3662653 }, + { url = "https://files.pythonhosted.org/packages/42/78/3c5216829a48237fcb71a077f891328a435e980d9757a9ebc49114d88768/grpcio-1.69.0-cp311-cp311-win_amd64.whl", hash = "sha256:fb9302afc3a0e4ba0b225cd651ef8e478bf0070cf11a529175caecd5ea2474e7", size = 4412824 }, { url = "https://files.pythonhosted.org/packages/61/1d/8f28f147d7f3f5d6b6082f14e1e0f40d58e50bc2bd30d2377c730c57a286/grpcio-1.69.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:fc18a4de8c33491ad6f70022af5c460b39611e39578a4d84de0fe92f12d5d47b", size = 5161414 }, { url = "https://files.pythonhosted.org/packages/35/4b/9ab8ea65e515e1844feced1ef9e7a5d8359c48d986c93f3d2a2006fbdb63/grpcio-1.69.0-cp312-cp312-macosx_10_14_universal2.whl", hash = "sha256:0f0270bd9ffbff6961fe1da487bdcd594407ad390cc7960e738725d4807b18c4", size = 11108909 }, { url = "https://files.pythonhosted.org/packages/99/68/1856fde2b3c3162bdfb9845978608deef3606e6907fdc2c87443fce6ecd0/grpcio-1.69.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:dc48f99cc05e0698e689b51a05933253c69a8c8559a47f605cff83801b03af0e", size = 5658302 }, @@ -1335,6 +1423,7 @@ dependencies = [ { name = "pygments" }, { name = "stack-data" }, { name = "traitlets" }, + { name = "typing-extensions", marker = "python_full_version < '3.12'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/01/35/6f90fdddff7a08b7b715fccbd2427b5212c9525cd043d26fdc45bee0708d/ipython-8.31.0.tar.gz", hash = "sha256:b6a2274606bec6166405ff05e54932ed6e5cfecaca1fc05f2cacde7bb074d70b", size = 5501011 } wheels = [ @@ -1408,6 +1497,18 @@ version = "0.8.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f8/70/90bc7bd3932e651486861df5c8ffea4ca7c77d28e8532ddefe2abc561a53/jiter-0.8.2.tar.gz", hash = "sha256:cd73d3e740666d0e639f678adb176fad25c1bcbdae88d8d7b857e1783bb4212d", size = 163007 } wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b0/c1a7caa7f9dc5f1f6cfa08722867790fe2d3645d6e7170ca280e6e52d163/jiter-0.8.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:2dd61c5afc88a4fda7d8b2cf03ae5947c6ac7516d32b7a15bf4b49569a5c076b", size = 303666 }, + { url = "https://files.pythonhosted.org/packages/f5/97/0468bc9eeae43079aaa5feb9267964e496bf13133d469cfdc135498f8dd0/jiter-0.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a6c710d657c8d1d2adbbb5c0b0c6bfcec28fd35bd6b5f016395f9ac43e878a15", size = 311934 }, + { url = "https://files.pythonhosted.org/packages/e5/69/64058e18263d9a5f1e10f90c436853616d5f047d997c37c7b2df11b085ec/jiter-0.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9584de0cd306072635fe4b89742bf26feae858a0683b399ad0c2509011b9dc0", size = 335506 }, + { url = "https://files.pythonhosted.org/packages/9d/14/b747f9a77b8c0542141d77ca1e2a7523e854754af2c339ac89a8b66527d6/jiter-0.8.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a90a923338531b7970abb063cfc087eebae6ef8ec8139762007188f6bc69a9f", size = 355849 }, + { url = "https://files.pythonhosted.org/packages/53/e2/98a08161db7cc9d0e39bc385415890928ff09709034982f48eccfca40733/jiter-0.8.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21974d246ed0181558087cd9f76e84e8321091ebfb3a93d4c341479a736f099", size = 381700 }, + { url = "https://files.pythonhosted.org/packages/7a/38/1674672954d35bce3b1c9af99d5849f9256ac8f5b672e020ac7821581206/jiter-0.8.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:32475a42b2ea7b344069dc1e81445cfc00b9d0e3ca837f0523072432332e9f74", size = 389710 }, + { url = "https://files.pythonhosted.org/packages/f8/9b/92f9da9a9e107d019bcf883cd9125fa1690079f323f5a9d5c6986eeec3c0/jiter-0.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b9931fd36ee513c26b5bf08c940b0ac875de175341cbdd4fa3be109f0492586", size = 345553 }, + { url = "https://files.pythonhosted.org/packages/44/a6/6d030003394e9659cd0d7136bbeabd82e869849ceccddc34d40abbbbb269/jiter-0.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ce0820f4a3a59ddced7fce696d86a096d5cc48d32a4183483a17671a61edfddc", size = 376388 }, + { url = "https://files.pythonhosted.org/packages/ad/8d/87b09e648e4aca5f9af89e3ab3cfb93db2d1e633b2f2931ede8dabd9b19a/jiter-0.8.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8ffc86ae5e3e6a93765d49d1ab47b6075a9c978a2b3b80f0f32628f39caa0c88", size = 511226 }, + { url = "https://files.pythonhosted.org/packages/77/95/8008ebe4cdc82eac1c97864a8042ca7e383ed67e0ec17bfd03797045c727/jiter-0.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5127dc1abd809431172bc3fbe8168d6b90556a30bb10acd5ded41c3cfd6f43b6", size = 504134 }, + { url = "https://files.pythonhosted.org/packages/26/0d/3056a74de13e8b2562e4d526de6dac2f65d91ace63a8234deb9284a1d24d/jiter-0.8.2-cp311-cp311-win32.whl", hash = "sha256:66227a2c7b575720c1871c8800d3a0122bb8ee94edb43a5685aa9aceb2782d44", size = 203103 }, + { url = "https://files.pythonhosted.org/packages/4e/1e/7f96b798f356e531ffc0f53dd2f37185fac60fae4d6c612bbbd4639b90aa/jiter-0.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:cde031d8413842a1e7501e9129b8e676e62a657f8ec8166e18a70d94d4682855", size = 206717 }, { url = "https://files.pythonhosted.org/packages/a1/17/c8747af8ea4e045f57d6cfd6fc180752cab9bc3de0e8a0c9ca4e8af333b1/jiter-0.8.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:e6ec2be506e7d6f9527dae9ff4b7f54e68ea44a0ef6b098256ddf895218a2f8f", size = 302027 }, { url = "https://files.pythonhosted.org/packages/3c/c1/6da849640cd35a41e91085723b76acc818d4b7d92b0b6e5111736ce1dd10/jiter-0.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76e324da7b5da060287c54f2fabd3db5f76468006c811831f051942bf68c9d44", size = 310326 }, { url = "https://files.pythonhosted.org/packages/06/99/a2bf660d8ccffee9ad7ed46b4f860d2108a148d0ea36043fd16f4dc37e94/jiter-0.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:180a8aea058f7535d1c84183c0362c710f4750bef66630c05f40c93c2b152a0f", size = 334242 }, @@ -1741,6 +1842,13 @@ version = "4.3.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/a4/31/ec1259ca8ad11568abaf090a7da719616ca96b60d097ccc5799cd0ff599c/lz4-4.3.3.tar.gz", hash = "sha256:01fe674ef2889dbb9899d8a67361e0c4a2c833af5aeb37dd505727cf5d2a131e", size = 171509 } wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/f7/cfb942edd53c8a6aba168720ccf3d6a0cac3e891a7feba97d5823b5dd047/lz4-4.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:30e8c20b8857adef7be045c65f47ab1e2c4fabba86a9fa9a997d7674a31ea6b6", size = 254267 }, + { url = "https://files.pythonhosted.org/packages/71/ca/046bd7e7e1ed4639eb398192374bc3fbf5010d3c168361fec161b63e8bfa/lz4-4.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2f7b1839f795315e480fb87d9bc60b186a98e3e5d17203c6e757611ef7dcef61", size = 212353 }, + { url = "https://files.pythonhosted.org/packages/0c/c2/5beb6a7bb7fd27cd5fe5bb93c15636d30987794b161e4609fbf20dc3b5c7/lz4-4.3.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edfd858985c23523f4e5a7526ca6ee65ff930207a7ec8a8f57a01eae506aaee7", size = 1239095 }, + { url = "https://files.pythonhosted.org/packages/cf/d4/12915eb3083dfd1746d50b71b73334030b129cd25abbed9133dd2d413c21/lz4-4.3.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e9c410b11a31dbdc94c05ac3c480cb4b222460faf9231f12538d0074e56c563", size = 1265760 }, + { url = "https://files.pythonhosted.org/packages/94/7b/5e72b7504d7675b484812bfc65fe958f7649a64e0d6fe35c11812511f0b5/lz4-4.3.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d2507ee9c99dbddd191c86f0e0c8b724c76d26b0602db9ea23232304382e1f21", size = 1185451 }, + { url = "https://files.pythonhosted.org/packages/2f/b5/3726a678b3a0c64d24e71179e35e7ff8e3553da9d32c2fddce879d042b63/lz4-4.3.3-cp311-cp311-win32.whl", hash = "sha256:f180904f33bdd1e92967923a43c22899e303906d19b2cf8bb547db6653ea6e7d", size = 87232 }, + { url = "https://files.pythonhosted.org/packages/55/f9/69ed96043dae4d982286a4dda2feb473f49e95e4c90a928ec583d93769a2/lz4-4.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:b14d948e6dce389f9a7afc666d60dd1e35fa2138a8ec5306d30cd2e30d36b40c", size = 99794 }, { url = "https://files.pythonhosted.org/packages/4d/6f/081811b17ccaec5f06b3030756af2737841447849118a6e1078481a78c6c/lz4-4.3.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e36cd7b9d4d920d3bfc2369840da506fa68258f7bb176b8743189793c055e43d", size = 254213 }, { url = "https://files.pythonhosted.org/packages/53/4d/8e04ef75feff8848ba3c624ce81c7732bdcea5f8f994758afa88cd3d7764/lz4-4.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:31ea4be9d0059c00b2572d700bf2c1bc82f241f2c3282034a759c9a4d6ca4dc2", size = 212354 }, { url = "https://files.pythonhosted.org/packages/a3/04/257a72d6a879dbc8c669018989f776fcdd5b4bf3c2c51c09a54f1ca31721/lz4-4.3.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33c9a6fd20767ccaf70649982f8f3eeb0884035c150c0b818ea660152cf3c809", size = 1238643 }, @@ -1759,6 +1867,17 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/31/15/9d9743897e4450b2de199ee673b50cb018980c4ced477d41cf91304a85e3/marisa_trie-1.2.1.tar.gz", hash = "sha256:3a27c408e2aefc03e0f1d25b2ff2afb85aac3568f6fa2ae2a53b57a2e87ce29d", size = 416124 } wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/93/ffb01dfa22b6eee918e798e0bc3487427036c608aa4c065725f31aaf4104/marisa_trie-1.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ed3fb4ed7f2084597e862bcd56c56c5529e773729a426c083238682dba540e98", size = 362823 }, + { url = "https://files.pythonhosted.org/packages/6d/1d/5c36500ac350c278c9bdfd88e17fa846fa4136d75597c167141ed973cdf2/marisa_trie-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0fe69fb9ffb2767746181f7b3b29bbd3454d1d24717b5958e030494f3d3cddf3", size = 192741 }, + { url = "https://files.pythonhosted.org/packages/e8/04/87dd0840f3f720e511eba56193c02bf64d7d96df1ca9f6d19994f55154be/marisa_trie-1.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4728ed3ae372d1ea2cdbd5eaa27b8f20a10e415d1f9d153314831e67d963f281", size = 174995 }, + { url = "https://files.pythonhosted.org/packages/c9/51/9e903a7e13b7593e2e675d0ec4c390ca076dc5df1c1a0d5e85a513b886a3/marisa_trie-1.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8cf4f25cf895692b232f49aa5397af6aba78bb679fb917a05fce8d3cb1ee446d", size = 1384728 }, + { url = "https://files.pythonhosted.org/packages/e8/3f/7362a5ac60c2b0aad0f52cd57e7bd0c708f20d2660d8df85360f3d8f1c4b/marisa_trie-1.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cca7f96236ffdbf49be4b2e42c132e3df05968ac424544034767650913524de", size = 1412620 }, + { url = "https://files.pythonhosted.org/packages/1f/bc/aaa3eaf6875f78a204a8da9692d56e3a36f89997dad2c388628385614576/marisa_trie-1.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d7eb20bf0e8b55a58d2a9b518aabc4c18278787bdba476c551dd1c1ed109e509", size = 1361555 }, + { url = "https://files.pythonhosted.org/packages/18/98/e11b5a6206c5d110f32adab37fa84a85410d684e9c731acdd5c9250e2ce4/marisa_trie-1.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b1ec93f0d1ee6d7ab680a6d8ea1a08bf264636358e92692072170032dda652ba", size = 2257717 }, + { url = "https://files.pythonhosted.org/packages/d2/9d/6b4a40867875e738a67c5b29f83e2e490a66bd9067ace3dd9a5c497e2b7f/marisa_trie-1.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e2699255d7ac610dee26d4ae7bda5951d05c7d9123a22e1f7c6a6f1964e0a4e4", size = 2417044 }, + { url = "https://files.pythonhosted.org/packages/fe/61/e25613c72f2931757334b8bcf6b501569ef713f5ee9c6c7688ec460bd720/marisa_trie-1.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c484410911182457a8a1a0249d0c09c01e2071b78a0a8538cd5f7fa45589b13a", size = 2351960 }, + { url = "https://files.pythonhosted.org/packages/19/0a/a90ccaf3eb476d13ec261f80c6c52defaf10ebc7f35eb2bcd7dfb533aef7/marisa_trie-1.2.1-cp311-cp311-win32.whl", hash = "sha256:ad548117744b2bcf0e3d97374608be0a92d18c2af13d98b728d37cd06248e571", size = 130446 }, + { url = "https://files.pythonhosted.org/packages/fc/98/574b4e143e0a2f5f71af8716b6c4a8a46220f75a6e0847ce7d11ee0ba4aa/marisa_trie-1.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:436f62d27714970b9cdd3b3c41bdad046f260e62ebb0daa38125ef70536fc73b", size = 152037 }, { url = "https://files.pythonhosted.org/packages/4e/bf/8bd4ac8436b33fd46c9e1ffe3c2a131cd9744cc1649dbbe13308f744ef2b/marisa_trie-1.2.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:638506eacf20ca503fff72221a7e66a6eadbf28d6a4a6f949fcf5b1701bb05ec", size = 360041 }, { url = "https://files.pythonhosted.org/packages/ab/dd/4d3151e302e66ae387885f6ec265bd189e096b0c43c1379bfd9a3b9d2543/marisa_trie-1.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de1665eaafefa48a308e4753786519888021740501a15461c77bdfd57638e6b4", size = 190520 }, { url = "https://files.pythonhosted.org/packages/00/28/ae5991c74fb90b173167a366a634c83445f948ad044d37287b478d6b457e/marisa_trie-1.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f713af9b8aa66a34cd3a78c7d150a560a75734713abe818a69021fd269e927fa", size = 174175 }, @@ -1801,6 +1920,16 @@ version = "3.0.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537 } wheels = [ + { url = "https://files.pythonhosted.org/packages/6b/28/bbf83e3f76936960b850435576dd5e67034e200469571be53f69174a2dfd/MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", size = 14353 }, + { url = "https://files.pythonhosted.org/packages/6c/30/316d194b093cde57d448a4c3209f22e3046c5bb2fb0820b118292b334be7/MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", size = 12392 }, + { url = "https://files.pythonhosted.org/packages/f2/96/9cdafba8445d3a53cae530aaf83c38ec64c4d5427d975c974084af5bc5d2/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", size = 23984 }, + { url = "https://files.pythonhosted.org/packages/f1/a4/aefb044a2cd8d7334c8a47d3fb2c9f328ac48cb349468cc31c20b539305f/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", size = 23120 }, + { url = "https://files.pythonhosted.org/packages/8d/21/5e4851379f88f3fad1de30361db501300d4f07bcad047d3cb0449fc51f8c/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", size = 23032 }, + { url = "https://files.pythonhosted.org/packages/00/7b/e92c64e079b2d0d7ddf69899c98842f3f9a60a1ae72657c89ce2655c999d/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", size = 24057 }, + { url = "https://files.pythonhosted.org/packages/f9/ac/46f960ca323037caa0a10662ef97d0a4728e890334fc156b9f9e52bcc4ca/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", size = 23359 }, + { url = "https://files.pythonhosted.org/packages/69/84/83439e16197337b8b14b6a5b9c2105fff81d42c2a7c5b58ac7b62ee2c3b1/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", size = 23306 }, + { url = "https://files.pythonhosted.org/packages/9a/34/a15aa69f01e2181ed8d2b685c0d2f6655d5cca2c4db0ddea775e631918cd/MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", size = 15094 }, + { url = "https://files.pythonhosted.org/packages/da/b8/3a3bd761922d416f3dc5d00bfbed11f66b1ab89a0c2b6e887240a30b0f6b/MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", size = 15521 }, { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274 }, { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348 }, { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149 }, @@ -1931,6 +2060,21 @@ version = "6.1.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d6/be/504b89a5e9ca731cd47487e91c469064f8ae5af93b7259758dcfc2b9c848/multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a", size = 64002 } wheels = [ + { url = "https://files.pythonhosted.org/packages/93/13/df3505a46d0cd08428e4c8169a196131d1b0c4b515c3649829258843dde6/multidict-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6", size = 48570 }, + { url = "https://files.pythonhosted.org/packages/f0/e1/a215908bfae1343cdb72f805366592bdd60487b4232d039c437fe8f5013d/multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156", size = 29316 }, + { url = "https://files.pythonhosted.org/packages/70/0f/6dc70ddf5d442702ed74f298d69977f904960b82368532c88e854b79f72b/multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb", size = 29640 }, + { url = "https://files.pythonhosted.org/packages/d8/6d/9c87b73a13d1cdea30b321ef4b3824449866bd7f7127eceed066ccb9b9ff/multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b", size = 131067 }, + { url = "https://files.pythonhosted.org/packages/cc/1e/1b34154fef373371fd6c65125b3d42ff5f56c7ccc6bfff91b9b3c60ae9e0/multidict-6.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72", size = 138507 }, + { url = "https://files.pythonhosted.org/packages/fb/e0/0bc6b2bac6e461822b5f575eae85da6aae76d0e2a79b6665d6206b8e2e48/multidict-6.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304", size = 133905 }, + { url = "https://files.pythonhosted.org/packages/ba/af/73d13b918071ff9b2205fcf773d316e0f8fefb4ec65354bbcf0b10908cc6/multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351", size = 129004 }, + { url = "https://files.pythonhosted.org/packages/74/21/23960627b00ed39643302d81bcda44c9444ebcdc04ee5bedd0757513f259/multidict-6.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb", size = 121308 }, + { url = "https://files.pythonhosted.org/packages/8b/5c/cf282263ffce4a596ed0bb2aa1a1dddfe1996d6a62d08842a8d4b33dca13/multidict-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3", size = 132608 }, + { url = "https://files.pythonhosted.org/packages/d7/3e/97e778c041c72063f42b290888daff008d3ab1427f5b09b714f5a8eff294/multidict-6.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399", size = 127029 }, + { url = "https://files.pythonhosted.org/packages/47/ac/3efb7bfe2f3aefcf8d103e9a7162572f01936155ab2f7ebcc7c255a23212/multidict-6.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423", size = 137594 }, + { url = "https://files.pythonhosted.org/packages/42/9b/6c6e9e8dc4f915fc90a9b7798c44a30773dea2995fdcb619870e705afe2b/multidict-6.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3", size = 134556 }, + { url = "https://files.pythonhosted.org/packages/1d/10/8e881743b26aaf718379a14ac58572a240e8293a1c9d68e1418fb11c0f90/multidict-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753", size = 130993 }, + { url = "https://files.pythonhosted.org/packages/45/84/3eb91b4b557442802d058a7579e864b329968c8d0ea57d907e7023c677f2/multidict-6.1.0-cp311-cp311-win32.whl", hash = "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80", size = 26405 }, + { url = "https://files.pythonhosted.org/packages/9f/0b/ad879847ecbf6d27e90a6eabb7eff6b62c129eefe617ea45eae7c1f0aead/multidict-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926", size = 28795 }, { url = "https://files.pythonhosted.org/packages/fd/16/92057c74ba3b96d5e211b553895cd6dc7cc4d1e43d9ab8fafc727681ef71/multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa", size = 48713 }, { url = "https://files.pythonhosted.org/packages/94/3d/37d1b8893ae79716179540b89fc6a0ee56b4a65fcc0d63535c6f5d96f217/multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436", size = 29516 }, { url = "https://files.pythonhosted.org/packages/a2/12/adb6b3200c363062f805275b4c1e656be2b3681aada66c80129932ff0bae/multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761", size = 29557 }, @@ -1970,6 +2114,13 @@ version = "1.0.12" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/64/d9/e7c6a7d4e9b5320c17e54af6f9edd2f521c6f86bbbb72aba571f641a9793/murmurhash-1.0.12.tar.gz", hash = "sha256:467b7ee31c1f79f46d00436a1957fc52a0e5801369dd2f30eb7655f380735b5f", size = 13233 } wheels = [ + { url = "https://files.pythonhosted.org/packages/d3/f4/0208624de330224f3a8981c030007fc4a3583ca6b4d4dd3275364c1d06e6/murmurhash-1.0.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8b236b76a256690e745b63b679892878ec4f01deeeda8d311482a9b183d2d452", size = 26793 }, + { url = "https://files.pythonhosted.org/packages/2f/a4/a387486e79bcc04f3d3b123195fd4cca74a7ba439d6c45b35c5366c66586/murmurhash-1.0.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8bc3756dd657ed90c1354705e66513c11516929fe726e7bc91c79734d190f394", size = 26884 }, + { url = "https://files.pythonhosted.org/packages/9f/38/ec45a33c519feb802cdf0fe9dd1b1e6c15897c43d29c738eaae61da8ae5d/murmurhash-1.0.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd41e4c3d7936b69010d76e5edff363bf40fd918d86287a14e924363d7828522", size = 136101 }, + { url = "https://files.pythonhosted.org/packages/0b/d5/6f1b561d8b14ef01d28d9cec278870bec01d8a569cfbc694e68ac05a5615/murmurhash-1.0.12-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36be2831df750163495e471d24aeef6aca1b2a3c4dfb05f40114859db47ff3f2", size = 134309 }, + { url = "https://files.pythonhosted.org/packages/e8/78/2df6cdce439f6b8509d7947b8c47e7fe2589671899eb6399f4e2f602fe1f/murmurhash-1.0.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b078c10f9c82cbd144b1200061fbfa7f99af9d5d8d7f7d8a324370169e3da7c2", size = 131134 }, + { url = "https://files.pythonhosted.org/packages/43/0b/f0a5a622c505786d3d1dc1ad3e7f6b6fbfcae2665b205e07b3882185c39f/murmurhash-1.0.12-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:307ca8da5f038635ded9de722fe11f07f06a2b76442ae272dcccbff6086de487", size = 128630 }, + { url = "https://files.pythonhosted.org/packages/de/30/ceb9217cdba72bc0bf8466e373e12e5a42945cc85eda0a7c479e319e07ae/murmurhash-1.0.12-cp311-cp311-win_amd64.whl", hash = "sha256:1b4ab5ba5ba909959659989f3bf57903f31f49906fe40f00aec81e32eea69a88", size = 25417 }, { url = "https://files.pythonhosted.org/packages/38/c7/0dc2914c24adb9466b69606dfdee7bbfed13476f4dda3753e0185cfbbe1f/murmurhash-1.0.12-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1a4c97c8ffbedb62b760c3c2f77b5b8cb0e0ac0ec83a74d2f289e113e3e92ed5", size = 27120 }, { url = "https://files.pythonhosted.org/packages/ae/d7/aea56101f225eb021cfd47245d55680605665b556aba95eecee937b4d4d6/murmurhash-1.0.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9574f0b634f059158bb89734a811e435ac9ad2335c02a7abb59f1875dcce244c", size = 27081 }, { url = "https://files.pythonhosted.org/packages/f4/68/4b723e0f318e92b0b4779f41ff5d9446e1dc0e68aca2f0043e1fab3fc1be/murmurhash-1.0.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:701cc0ce91809b4d7c2e0518be759635205e1e181325792044f5a8118019f716", size = 138552 }, @@ -2126,6 +2277,14 @@ version = "1.26.4" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/65/6e/09db70a523a96d25e115e71cc56a6f9031e7b8cd166c1ac8438307c14058/numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010", size = 15786129 } wheels = [ + { url = "https://files.pythonhosted.org/packages/11/57/baae43d14fe163fa0e4c47f307b6b2511ab8d7d30177c491960504252053/numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71", size = 20630554 }, + { url = "https://files.pythonhosted.org/packages/1a/2e/151484f49fd03944c4a3ad9c418ed193cfd02724e138ac8a9505d056c582/numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef", size = 13997127 }, + { url = "https://files.pythonhosted.org/packages/79/ae/7e5b85136806f9dadf4878bf73cf223fe5c2636818ba3ab1c585d0403164/numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e", size = 14222994 }, + { url = "https://files.pythonhosted.org/packages/3a/d0/edc009c27b406c4f9cbc79274d6e46d634d139075492ad055e3d68445925/numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5", size = 18252005 }, + { url = "https://files.pythonhosted.org/packages/09/bf/2b1aaf8f525f2923ff6cfcf134ae5e750e279ac65ebf386c75a0cf6da06a/numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a", size = 13885297 }, + { url = "https://files.pythonhosted.org/packages/df/a0/4e0f14d847cfc2a633a1c8621d00724f3206cfeddeb66d35698c4e2cf3d2/numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a", size = 18093567 }, + { url = "https://files.pythonhosted.org/packages/d2/b7/a734c733286e10a7f1a8ad1ae8c90f2d33bf604a96548e0a4a3a6739b468/numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20", size = 5968812 }, + { url = "https://files.pythonhosted.org/packages/3f/6b/5610004206cf7f8e7ad91c5a85a8c71b2f2f8051a0c0c4d5916b76d6cbb2/numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2", size = 15811913 }, { url = "https://files.pythonhosted.org/packages/95/12/8f2020a8e8b8383ac0177dc9570aad031a3beb12e38847f7129bacd96228/numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218", size = 20335901 }, { url = "https://files.pythonhosted.org/packages/75/5b/ca6c8bd14007e5ca171c7c03102d17b4f4e0ceb53957e8c44343a9546dcc/numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b", size = 13685868 }, { url = "https://files.pythonhosted.org/packages/79/f8/97f10e6755e2a7d027ca783f63044d5b1bc1ae7acb12afe6a9b4286eac17/numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b", size = 13925109 }, @@ -2219,6 +2378,13 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/9c/d6/9f8431bacc2e19dca897724cd097b1bb224a6ad5433784a44b587c7c13af/pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667", size = 4399213 } wheels = [ + { url = "https://files.pythonhosted.org/packages/a8/44/d9502bf0ed197ba9bf1103c9867d5904ddcaf869e52329787fc54ed70cc8/pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039", size = 12602222 }, + { url = "https://files.pythonhosted.org/packages/52/11/9eac327a38834f162b8250aab32a6781339c69afe7574368fffe46387edf/pandas-2.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd", size = 11321274 }, + { url = "https://files.pythonhosted.org/packages/45/fb/c4beeb084718598ba19aa9f5abbc8aed8b42f90930da861fcb1acdb54c3a/pandas-2.2.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698", size = 15579836 }, + { url = "https://files.pythonhosted.org/packages/cd/5f/4dba1d39bb9c38d574a9a22548c540177f78ea47b32f99c0ff2ec499fac5/pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc", size = 13058505 }, + { url = "https://files.pythonhosted.org/packages/b9/57/708135b90391995361636634df1f1130d03ba456e95bcf576fada459115a/pandas-2.2.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3", size = 16744420 }, + { url = "https://files.pythonhosted.org/packages/86/4a/03ed6b7ee323cf30404265c284cee9c65c56a212e0a08d9ee06984ba2240/pandas-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32", size = 14440457 }, + { url = "https://files.pythonhosted.org/packages/ed/8c/87ddf1fcb55d11f9f847e3c69bb1c6f8e46e2f40ab1a2d2abadb2401b007/pandas-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5", size = 11617166 }, { url = "https://files.pythonhosted.org/packages/17/a3/fb2734118db0af37ea7433f57f722c0a56687e14b14690edff0cdb4b7e58/pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9", size = 12529893 }, { url = "https://files.pythonhosted.org/packages/e1/0c/ad295fd74bfac85358fd579e271cded3ac969de81f62dd0142c426b9da91/pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4", size = 11363475 }, { url = "https://files.pythonhosted.org/packages/c6/2a/4bba3f03f7d07207481fed47f5b35f556c7441acddc368ec43d6643c5777/pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3", size = 15188645 }, @@ -2286,6 +2452,17 @@ version = "11.1.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f3/af/c097e544e7bd278333db77933e535098c259609c4eb3b85381109602fb5b/pillow-11.1.0.tar.gz", hash = "sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20", size = 46742715 } wheels = [ + { url = "https://files.pythonhosted.org/packages/dd/d6/2000bfd8d5414fb70cbbe52c8332f2283ff30ed66a9cde42716c8ecbe22c/pillow-11.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:e06695e0326d05b06833b40b7ef477e475d0b1ba3a6d27da1bb48c23209bf457", size = 3229968 }, + { url = "https://files.pythonhosted.org/packages/d9/45/3fe487010dd9ce0a06adf9b8ff4f273cc0a44536e234b0fad3532a42c15b/pillow-11.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96f82000e12f23e4f29346e42702b6ed9a2f2fea34a740dd5ffffcc8c539eb35", size = 3101806 }, + { url = "https://files.pythonhosted.org/packages/e3/72/776b3629c47d9d5f1c160113158a7a7ad177688d3a1159cd3b62ded5a33a/pillow-11.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3cd561ded2cf2bbae44d4605837221b987c216cff94f49dfeed63488bb228d2", size = 4322283 }, + { url = "https://files.pythonhosted.org/packages/e4/c2/e25199e7e4e71d64eeb869f5b72c7ddec70e0a87926398785ab944d92375/pillow-11.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f189805c8be5ca5add39e6f899e6ce2ed824e65fb45f3c28cb2841911da19070", size = 4402945 }, + { url = "https://files.pythonhosted.org/packages/c1/ed/51d6136c9d5911f78632b1b86c45241c712c5a80ed7fa7f9120a5dff1eba/pillow-11.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:dd0052e9db3474df30433f83a71b9b23bd9e4ef1de13d92df21a52c0303b8ab6", size = 4361228 }, + { url = "https://files.pythonhosted.org/packages/48/a4/fbfe9d5581d7b111b28f1d8c2762dee92e9821bb209af9fa83c940e507a0/pillow-11.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:837060a8599b8f5d402e97197d4924f05a2e0d68756998345c829c33186217b1", size = 4484021 }, + { url = "https://files.pythonhosted.org/packages/39/db/0b3c1a5018117f3c1d4df671fb8e47d08937f27519e8614bbe86153b65a5/pillow-11.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:aa8dd43daa836b9a8128dbe7d923423e5ad86f50a7a14dc688194b7be5c0dea2", size = 4287449 }, + { url = "https://files.pythonhosted.org/packages/d9/58/bc128da7fea8c89fc85e09f773c4901e95b5936000e6f303222490c052f3/pillow-11.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0a2f91f8a8b367e7a57c6e91cd25af510168091fb89ec5146003e424e1558a96", size = 4419972 }, + { url = "https://files.pythonhosted.org/packages/5f/bb/58f34379bde9fe197f51841c5bbe8830c28bbb6d3801f16a83b8f2ad37df/pillow-11.1.0-cp311-cp311-win32.whl", hash = "sha256:c12fc111ef090845de2bb15009372175d76ac99969bdf31e2ce9b42e4b8cd88f", size = 2291201 }, + { url = "https://files.pythonhosted.org/packages/3a/c6/fce9255272bcf0c39e15abd2f8fd8429a954cf344469eaceb9d0d1366913/pillow-11.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbd43429d0d7ed6533b25fc993861b8fd512c42d04514a0dd6337fb3ccf22761", size = 2625686 }, + { url = "https://files.pythonhosted.org/packages/c8/52/8ba066d569d932365509054859f74f2a9abee273edcef5cd75e4bc3e831e/pillow-11.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:f7955ecf5609dee9442cbface754f2c6e541d9e6eda87fad7f7a989b0bdb9d71", size = 2375194 }, { url = "https://files.pythonhosted.org/packages/95/20/9ce6ed62c91c073fcaa23d216e68289e19d95fb8188b9fb7a63d36771db8/pillow-11.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2062ffb1d36544d42fcaa277b069c88b01bb7298f4efa06731a7fd6cc290b81a", size = 3226818 }, { url = "https://files.pythonhosted.org/packages/b9/d8/f6004d98579a2596c098d1e30d10b248798cceff82d2b77aa914875bfea1/pillow-11.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a85b653980faad27e88b141348707ceeef8a1186f75ecc600c395dcac19f385b", size = 3101662 }, { url = "https://files.pythonhosted.org/packages/08/d9/892e705f90051c7a2574d9f24579c9e100c828700d78a63239676f960b74/pillow-11.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9409c080586d1f683df3f184f20e36fb647f2e0bc3988094d4fd8c9f4eb1b3b3", size = 4329317 }, @@ -2365,6 +2542,11 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/f2/4e/76dbf784e7d4ed069f91a4c249b1d6ec6856ef0c0b2fd96992895d458b15/preshed-3.0.9.tar.gz", hash = "sha256:721863c5244ffcd2651ad0928951a2c7c77b102f4e11a251ad85d37ee7621660", size = 14478 } wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/1e/05fa559f53b635d96b233b63e93accb75215025b997486f7290991bec6c3/preshed-3.0.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7c2364da27f2875524ce1ca754dc071515a9ad26eb5def4c7e69129a13c9a59", size = 132972 }, + { url = "https://files.pythonhosted.org/packages/a8/b3/1a73ba16bab53043fd19dd0a7838ae05c705dccb329404dd4ad5925767f1/preshed-3.0.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:182138033c0730c683a6d97e567ceb8a3e83f3bff5704f300d582238dbd384b3", size = 128751 }, + { url = "https://files.pythonhosted.org/packages/2c/9a/919d3708f6fa98d9eab1a186e6b30ab25a4595907bbc1fea5c1e8faa9b9d/preshed-3.0.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:345a10be3b86bcc6c0591d343a6dc2bfd86aa6838c30ced4256dfcfa836c3a64", size = 150050 }, + { url = "https://files.pythonhosted.org/packages/db/69/d9ab108dc670b5be9e292bbd555f39e6eb0a4baab25cd28f792850d5e65b/preshed-3.0.9-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51d0192274aa061699b284f9fd08416065348edbafd64840c3889617ee1609de", size = 157159 }, + { url = "https://files.pythonhosted.org/packages/e4/fc/78cdbdb79f5d6d45949e72c32445d6c060977ad50a1dcfc0392622165f7c/preshed-3.0.9-cp311-cp311-win_amd64.whl", hash = "sha256:96b857d7a62cbccc3845ac8c41fd23addf052821be4eb987f2eb0da3d8745aa1", size = 122323 }, { url = "https://files.pythonhosted.org/packages/fe/7e/a41595876f644d8bd2c3d5422d7211e876b1848a8cc0c03cce33d9cd048a/preshed-3.0.9-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b4fe6720012c62e6d550d6a5c1c7ad88cacef8388d186dad4bafea4140d9d198", size = 133196 }, { url = "https://files.pythonhosted.org/packages/e7/68/1b4772ff3232e71b63a9206936eb1f75e976ebf4e4e24dc9b3ea7b68369b/preshed-3.0.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e04f05758875be9751e483bd3c519c22b00d3b07f5a64441ec328bb9e3c03700", size = 128594 }, { url = "https://files.pythonhosted.org/packages/f3/52/48eefe876a3841c5850bd955daf145d0e408567c8f46a997bce136dc259d/preshed-3.0.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a55091d0e395f1fdb62ab43401bb9f8b46c7d7794d5b071813c29dc1ab22fd0", size = 149220 }, @@ -2399,6 +2581,22 @@ version = "0.2.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/20/c8/2a13f78d82211490855b2fb303b6721348d0787fdd9a12ac46d99d3acde1/propcache-0.2.1.tar.gz", hash = "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64", size = 41735 } wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/0f/2913b6791ebefb2b25b4efd4bb2299c985e09786b9f5b19184a88e5778dd/propcache-0.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16", size = 79297 }, + { url = "https://files.pythonhosted.org/packages/cf/73/af2053aeccd40b05d6e19058419ac77674daecdd32478088b79375b9ab54/propcache-0.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717", size = 45611 }, + { url = "https://files.pythonhosted.org/packages/3c/09/8386115ba7775ea3b9537730e8cf718d83bbf95bffe30757ccf37ec4e5da/propcache-0.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3", size = 45146 }, + { url = "https://files.pythonhosted.org/packages/03/7a/793aa12f0537b2e520bf09f4c6833706b63170a211ad042ca71cbf79d9cb/propcache-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9", size = 232136 }, + { url = "https://files.pythonhosted.org/packages/f1/38/b921b3168d72111769f648314100558c2ea1d52eb3d1ba7ea5c4aa6f9848/propcache-0.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787", size = 239706 }, + { url = "https://files.pythonhosted.org/packages/14/29/4636f500c69b5edea7786db3c34eb6166f3384b905665ce312a6e42c720c/propcache-0.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465", size = 238531 }, + { url = "https://files.pythonhosted.org/packages/85/14/01fe53580a8e1734ebb704a3482b7829a0ef4ea68d356141cf0994d9659b/propcache-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af", size = 231063 }, + { url = "https://files.pythonhosted.org/packages/33/5c/1d961299f3c3b8438301ccfbff0143b69afcc30c05fa28673cface692305/propcache-0.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7", size = 220134 }, + { url = "https://files.pythonhosted.org/packages/00/d0/ed735e76db279ba67a7d3b45ba4c654e7b02bc2f8050671ec365d8665e21/propcache-0.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f", size = 220009 }, + { url = "https://files.pythonhosted.org/packages/75/90/ee8fab7304ad6533872fee982cfff5a53b63d095d78140827d93de22e2d4/propcache-0.2.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54", size = 212199 }, + { url = "https://files.pythonhosted.org/packages/eb/ec/977ffaf1664f82e90737275873461695d4c9407d52abc2f3c3e24716da13/propcache-0.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505", size = 214827 }, + { url = "https://files.pythonhosted.org/packages/57/48/031fb87ab6081764054821a71b71942161619549396224cbb242922525e8/propcache-0.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82", size = 228009 }, + { url = "https://files.pythonhosted.org/packages/1a/06/ef1390f2524850838f2390421b23a8b298f6ce3396a7cc6d39dedd4047b0/propcache-0.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca", size = 231638 }, + { url = "https://files.pythonhosted.org/packages/38/2a/101e6386d5a93358395da1d41642b79c1ee0f3b12e31727932b069282b1d/propcache-0.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e", size = 222788 }, + { url = "https://files.pythonhosted.org/packages/db/81/786f687951d0979007e05ad9346cd357e50e3d0b0f1a1d6074df334b1bbb/propcache-0.2.1-cp311-cp311-win32.whl", hash = "sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034", size = 40170 }, + { url = "https://files.pythonhosted.org/packages/cf/59/7cc7037b295d5772eceb426358bb1b86e6cab4616d971bd74275395d100d/propcache-0.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3", size = 44404 }, { url = "https://files.pythonhosted.org/packages/4c/28/1d205fe49be8b1b4df4c50024e62480a442b1a7b818e734308bb0d17e7fb/propcache-0.2.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a", size = 79588 }, { url = "https://files.pythonhosted.org/packages/21/ee/fc4d893f8d81cd4971affef2a6cb542b36617cd1d8ce56b406112cb80bf7/propcache-0.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0", size = 45825 }, { url = "https://files.pythonhosted.org/packages/4a/de/bbe712f94d088da1d237c35d735f675e494a816fd6f54e9db2f61ef4d03f/propcache-0.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d", size = 45357 }, @@ -2503,6 +2701,13 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/1a/f2/67533f116deb6dae7a0ac04681695fe06135912253a115c5ecdc714a32d4/pyarrow-16.1.0.tar.gz", hash = "sha256:15fbb22ea96d11f0b5768504a3f961edab25eaf4197c341720c4a387f6c60315", size = 1080280 } wheels = [ + { url = "https://files.pythonhosted.org/packages/28/17/a12aaddb818b7b73d17f3304afc22bce32ccb26723b507cc9c267aa809f3/pyarrow-16.1.0-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:d0ebea336b535b37eee9eee31761813086d33ed06de9ab6fc6aaa0bace7b250c", size = 28380406 }, + { url = "https://files.pythonhosted.org/packages/f3/94/4e2a579bbac1adb19e63b054b300f6f7fa04f32f212ce86c18727bdda698/pyarrow-16.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e73cfc4a99e796727919c5541c65bb88b973377501e39b9842ea71401ca6c1c", size = 26040531 }, + { url = "https://files.pythonhosted.org/packages/7e/34/d5b6eb5066553533dd6eb9782d50f353f8c6451ee2e49e0ea54d0e67bc34/pyarrow-16.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf9251264247ecfe93e5f5a0cd43b8ae834f1e61d1abca22da55b20c788417f6", size = 38666685 }, + { url = "https://files.pythonhosted.org/packages/d2/34/4e3c04e7398764e56ef00f8f267f8ebf565808478f5fee850cef4be670c3/pyarrow-16.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddf5aace92d520d3d2a20031d8b0ec27b4395cab9f74e07cc95edf42a5cc0147", size = 40949577 }, + { url = "https://files.pythonhosted.org/packages/47/62/b446ee0971b00e7437b9c54a8409ae20413235a64c0a301d7cf97070cffa/pyarrow-16.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:25233642583bf658f629eb230b9bb79d9af4d9f9229890b3c878699c82f7d11e", size = 38077480 }, + { url = "https://files.pythonhosted.org/packages/fa/15/48a68b30542a0231a75c26d8661bc5c9bbc07b42c5b219e929adba814ba7/pyarrow-16.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a33a64576fddfbec0a44112eaf844c20853647ca833e9a647bfae0582b2ff94b", size = 40821141 }, + { url = "https://files.pythonhosted.org/packages/49/4d/62a09116ec357ade462fac4086e0711457a87177bea25ae46b25897d6d7c/pyarrow-16.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:185d121b50836379fe012753cf15c4ba9638bda9645183ab36246923875f8d1b", size = 25889334 }, { url = "https://files.pythonhosted.org/packages/84/bd/d5903125e38c33b74f7b3d57ffffd4ef48145208cfd8742367f12effb59c/pyarrow-16.1.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:2e51ca1d6ed7f2e9d5c3c83decf27b0d17bb207a7dea986e8dc3e24f80ff7d6f", size = 28372822 }, { url = "https://files.pythonhosted.org/packages/9b/73/560ef6bf05f16305502b8e368c771e8f82d774898b37a3fb231f89c13342/pyarrow-16.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:06ebccb6f8cb7357de85f60d5da50e83507954af617d7b05f48af1621d331c9a", size = 26004052 }, { url = "https://files.pythonhosted.org/packages/56/5e/3cd956aceb1c960e8ac6fdc6eea69d642aa2e6ee10e2f10ce7815dbf62a9/pyarrow-16.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b04707f1979815f5e49824ce52d1dceb46e2f12909a48a6a753fe7cafbc44a0c", size = 38660648 }, @@ -2544,6 +2749,20 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 } wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/89/f3450af9d09d44eea1f2c369f49e8f181d742f28220f88cc4dfaae91ea6e/pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc", size = 1893421 }, + { url = "https://files.pythonhosted.org/packages/9e/e3/71fe85af2021f3f386da42d291412e5baf6ce7716bd7101ea49c810eda90/pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7", size = 1814998 }, + { url = "https://files.pythonhosted.org/packages/a6/3c/724039e0d848fd69dbf5806894e26479577316c6f0f112bacaf67aa889ac/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15", size = 1826167 }, + { url = "https://files.pythonhosted.org/packages/2b/5b/1b29e8c1fb5f3199a9a57c1452004ff39f494bbe9bdbe9a81e18172e40d3/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306", size = 1865071 }, + { url = "https://files.pythonhosted.org/packages/89/6c/3985203863d76bb7d7266e36970d7e3b6385148c18a68cc8915fd8c84d57/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99", size = 2036244 }, + { url = "https://files.pythonhosted.org/packages/0e/41/f15316858a246b5d723f7d7f599f79e37493b2e84bfc789e58d88c209f8a/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459", size = 2737470 }, + { url = "https://files.pythonhosted.org/packages/a8/7c/b860618c25678bbd6d1d99dbdfdf0510ccb50790099b963ff78a124b754f/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048", size = 1992291 }, + { url = "https://files.pythonhosted.org/packages/bf/73/42c3742a391eccbeab39f15213ecda3104ae8682ba3c0c28069fbcb8c10d/pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d", size = 1994613 }, + { url = "https://files.pythonhosted.org/packages/94/7a/941e89096d1175d56f59340f3a8ebaf20762fef222c298ea96d36a6328c5/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b", size = 2002355 }, + { url = "https://files.pythonhosted.org/packages/6e/95/2359937a73d49e336a5a19848713555605d4d8d6940c3ec6c6c0ca4dcf25/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474", size = 2126661 }, + { url = "https://files.pythonhosted.org/packages/2b/4c/ca02b7bdb6012a1adef21a50625b14f43ed4d11f1fc237f9d7490aa5078c/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6", size = 2153261 }, + { url = "https://files.pythonhosted.org/packages/72/9d/a241db83f973049a1092a079272ffe2e3e82e98561ef6214ab53fe53b1c7/pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c", size = 1812361 }, + { url = "https://files.pythonhosted.org/packages/e8/ef/013f07248041b74abd48a385e2110aa3a9bbfef0fbd97d4e6d07d2f5b89a/pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc", size = 1982484 }, + { url = "https://files.pythonhosted.org/packages/10/1c/16b3a3e3398fd29dca77cea0a1d998d6bde3902fa2706985191e2313cc76/pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4", size = 1867102 }, { url = "https://files.pythonhosted.org/packages/d6/74/51c8a5482ca447871c93e142d9d4a92ead74de6c8dc5e66733e22c9bba89/pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", size = 1893127 }, { url = "https://files.pythonhosted.org/packages/d3/f3/c97e80721735868313c58b89d2de85fa80fe8dfeeed84dc51598b92a135e/pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", size = 1811340 }, { url = "https://files.pythonhosted.org/packages/9e/91/840ec1375e686dbae1bd80a9e46c26a1e0083e1186abc610efa3d9a36180/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", size = 1822900 }, @@ -2618,6 +2837,12 @@ version = "5.2.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/a0/36/a1ac7d23a1611e7ccd4d27df096f3794e8d1e7faa040260d9d41b6fc3185/pyodbc-5.2.0.tar.gz", hash = "sha256:de8be39809c8ddeeee26a4b876a6463529cd487a60d1393eb2a93e9bcd44a8f5", size = 116908 } wheels = [ + { url = "https://files.pythonhosted.org/packages/8f/a2/5907ce319a571eb1e271d6a475920edfeacd92da1021bb2a15ed1b7f6ac1/pyodbc-5.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4627779f0a608b51ce2d2fe6d1d395384e65ca36248bf9dbb6d7cf2c8fda1cab", size = 72536 }, + { url = "https://files.pythonhosted.org/packages/e1/b8/bd438ab2bb9481615142784b0c9778079a87ae1bca7a0fe8aabfc088aa9f/pyodbc-5.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4d997d3b6551273647825c734158ca8a6f682df269f6b3975f2499c01577ddec", size = 71825 }, + { url = "https://files.pythonhosted.org/packages/8b/82/cf71ae99b511a7f20c380ce470de233a0291fa3798afa74e0adc8fad1675/pyodbc-5.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5102007a8c78dd2fc1c1b6f6147de8cfc020f81013e4b46c33e66aaa7d1bf7b1", size = 342304 }, + { url = "https://files.pythonhosted.org/packages/43/ea/03fe042f4a390df05e753ddd21c6cab006baae1eee71ce230f6e2a883944/pyodbc-5.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e3cbc7075a46c411b531ada557c4aef13d034060a70077717124cabc1717e2d", size = 346186 }, + { url = "https://files.pythonhosted.org/packages/f9/80/48178bb50990147adb72ec9e377e94517a0dfaf2f2a6e3fe477d9a33671f/pyodbc-5.2.0-cp311-cp311-win32.whl", hash = "sha256:de1ee7ec2eb326b7be5e2c4ce20d472c5ef1a6eb838d126d1d26779ff5486e49", size = 62418 }, + { url = "https://files.pythonhosted.org/packages/7c/6b/f0ad7d8a535d58f35f375ffbf367c68d0ec54452a431d23b0ebee4cd44c6/pyodbc-5.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:113f904b9852c12f10c7a3288f5a3563ecdbbefe3ccc829074a9eb8255edcd29", size = 68871 }, { url = "https://files.pythonhosted.org/packages/26/26/104525b728fedfababd3143426b9d0008c70f0d604a3bf5d4773977d83f4/pyodbc-5.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:be43d1ece4f2cf4d430996689d89a1a15aeb3a8da8262527e5ced5aee27e89c3", size = 73014 }, { url = "https://files.pythonhosted.org/packages/4f/7d/bb632488b603bcd2a6753b858e8bc7dd56146dd19bd72003cc09ae6e3fc0/pyodbc-5.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9f7badd0055221a744d76c11440c0856fd2846ed53b6555cf8f0a8893a3e4b03", size = 72515 }, { url = "https://files.pythonhosted.org/packages/ab/38/a1b9bfe5a7062672268553c2d6ff93676173b0fb4bd583e8c4f74a0e296f/pyodbc-5.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad633c52f4f4e7691daaa2278d6e6ebb2fe4ae7709e610e22c7dd1a1d620cf8b", size = 348561 }, @@ -2688,6 +2913,9 @@ name = "pywin32" version = "308" source = { registry = "https://pypi.org/simple" } wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/e2/02652007469263fe1466e98439831d65d4ca80ea1a2df29abecedf7e47b7/pywin32-308-cp311-cp311-win32.whl", hash = "sha256:5d8c8015b24a7d6855b1550d8e660d8daa09983c80e5daf89a273e5c6fb5095a", size = 5928156 }, + { url = "https://files.pythonhosted.org/packages/48/ef/f4fb45e2196bc7ffe09cad0542d9aff66b0e33f6c0954b43e49c33cad7bd/pywin32-308-cp311-cp311-win_amd64.whl", hash = "sha256:575621b90f0dc2695fec346b2d6302faebd4f0f45c05ea29404cefe35d89442b", size = 6559559 }, + { url = "https://files.pythonhosted.org/packages/79/ef/68bb6aa865c5c9b11a35771329e95917b5559845bd75b65549407f9fc6b4/pywin32-308-cp311-cp311-win_arm64.whl", hash = "sha256:100a5442b7332070983c4cd03f2e906a5648a5104b8a7f50175f7906efd16bb6", size = 7972495 }, { url = "https://files.pythonhosted.org/packages/00/7c/d00d6bdd96de4344e06c4afbf218bc86b54436a94c01c71a8701f613aa56/pywin32-308-cp312-cp312-win32.whl", hash = "sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897", size = 5939729 }, { url = "https://files.pythonhosted.org/packages/21/27/0c8811fbc3ca188f93b5354e7c286eb91f80a53afa4e11007ef661afa746/pywin32-308-cp312-cp312-win_amd64.whl", hash = "sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47", size = 6543015 }, { url = "https://files.pythonhosted.org/packages/9d/0f/d40f8373608caed2255781a3ad9a51d03a594a1248cd632d6a298daca693/pywin32-308-cp312-cp312-win_arm64.whl", hash = "sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091", size = 7976033 }, @@ -2702,6 +2930,7 @@ version = "2.0.14" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f1/82/90f8750423cba4b9b6c842df227609fb60704482d7abf6dd47e2babc055a/pywinpty-2.0.14.tar.gz", hash = "sha256:18bd9529e4a5daf2d9719aa17788ba6013e594ae94c5a0c27e83df3278b0660e", size = 27769 } wheels = [ + { url = "https://files.pythonhosted.org/packages/be/e2/af1a99c0432e4e58c9ac8e334ee191790ec9793d33559189b9d2069bdc1d/pywinpty-2.0.14-cp311-none-win_amd64.whl", hash = "sha256:cf2a43ac7065b3e0dc8510f8c1f13a75fb8fde805efa3b8cff7599a1ef497bc7", size = 1397223 }, { url = "https://files.pythonhosted.org/packages/ad/79/759ae767a3b78d340446efd54dd1fe4f7dafa4fc7be96ed757e44bcdba54/pywinpty-2.0.14-cp312-none-win_amd64.whl", hash = "sha256:55dad362ef3e9408ade68fd173e4f9032b3ce08f68cfe7eacb2c263ea1179737", size = 1397207 }, { url = "https://files.pythonhosted.org/packages/7d/34/b77b3c209bf2eaa6455390c8d5449241637f5957f41636a2204065d52bfa/pywinpty-2.0.14-cp313-none-win_amd64.whl", hash = "sha256:074fb988a56ec79ca90ed03a896d40707131897cefb8f76f926e3834227f2819", size = 1396698 }, ] @@ -2712,6 +2941,15 @@ version = "6.0.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612 }, + { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040 }, + { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829 }, + { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167 }, + { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952 }, + { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301 }, + { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638 }, + { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850 }, + { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980 }, { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 }, { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 }, { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 }, @@ -2741,6 +2979,18 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/fd/05/bed626b9f7bb2322cdbbf7b4bd8f54b1b617b0d2ab2d3547d6e39428a48e/pyzmq-26.2.0.tar.gz", hash = "sha256:070672c258581c8e4f640b5159297580a9974b026043bd4ab0470be9ed324f1f", size = 271975 } wheels = [ + { url = "https://files.pythonhosted.org/packages/12/20/de7442172f77f7c96299a0ac70e7d4fb78cd51eca67aa2cf552b66c14196/pyzmq-26.2.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:8f7e66c7113c684c2b3f1c83cdd3376103ee0ce4c49ff80a648643e57fb22218", size = 1340639 }, + { url = "https://files.pythonhosted.org/packages/98/4d/5000468bd64c7910190ed0a6c76a1ca59a68189ec1f007c451dc181a22f4/pyzmq-26.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3a495b30fc91db2db25120df5847d9833af237546fd59170701acd816ccc01c4", size = 1008710 }, + { url = "https://files.pythonhosted.org/packages/e1/bf/c67fd638c2f9fbbab8090a3ee779370b97c82b84cc12d0c498b285d7b2c0/pyzmq-26.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77eb0968da535cba0470a5165468b2cac7772cfb569977cff92e240f57e31bef", size = 673129 }, + { url = "https://files.pythonhosted.org/packages/86/94/99085a3f492aa538161cbf27246e8886ff850e113e0c294a5b8245f13b52/pyzmq-26.2.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ace4f71f1900a548f48407fc9be59c6ba9d9aaf658c2eea6cf2779e72f9f317", size = 910107 }, + { url = "https://files.pythonhosted.org/packages/31/1d/346809e8a9b999646d03f21096428453465b1bca5cd5c64ecd048d9ecb01/pyzmq-26.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:92a78853d7280bffb93df0a4a6a2498cba10ee793cc8076ef797ef2f74d107cf", size = 867960 }, + { url = "https://files.pythonhosted.org/packages/ab/68/6fb6ae5551846ad5beca295b7bca32bf0a7ce19f135cb30e55fa2314e6b6/pyzmq-26.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:689c5d781014956a4a6de61d74ba97b23547e431e9e7d64f27d4922ba96e9d6e", size = 869204 }, + { url = "https://files.pythonhosted.org/packages/0f/f9/18417771dee223ccf0f48e29adf8b4e25ba6d0e8285e33bcbce078070bc3/pyzmq-26.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0aca98bc423eb7d153214b2df397c6421ba6373d3397b26c057af3c904452e37", size = 1203351 }, + { url = "https://files.pythonhosted.org/packages/e0/46/f13e67fe0d4f8a2315782cbad50493de6203ea0d744610faf4d5f5b16e90/pyzmq-26.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1f3496d76b89d9429a656293744ceca4d2ac2a10ae59b84c1da9b5165f429ad3", size = 1514204 }, + { url = "https://files.pythonhosted.org/packages/50/11/ddcf7343b7b7a226e0fc7b68cbf5a5bb56291fac07f5c3023bb4c319ebb4/pyzmq-26.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5c2b3bfd4b9689919db068ac6c9911f3fcb231c39f7dd30e3138be94896d18e6", size = 1414339 }, + { url = "https://files.pythonhosted.org/packages/01/14/1c18d7d5b7be2708f513f37c61bfadfa62161c10624f8733f1c8451b3509/pyzmq-26.2.0-cp311-cp311-win32.whl", hash = "sha256:eac5174677da084abf378739dbf4ad245661635f1600edd1221f150b165343f4", size = 576928 }, + { url = "https://files.pythonhosted.org/packages/3b/1b/0a540edd75a41df14ec416a9a500b9fec66e554aac920d4c58fbd5756776/pyzmq-26.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:5a509df7d0a83a4b178d0f937ef14286659225ef4e8812e05580776c70e155d5", size = 642317 }, + { url = "https://files.pythonhosted.org/packages/98/77/1cbfec0358078a4c5add529d8a70892db1be900980cdb5dd0898b3d6ab9d/pyzmq-26.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:c0e6091b157d48cbe37bd67233318dbb53e1e6327d6fc3bb284afd585d141003", size = 543834 }, { url = "https://files.pythonhosted.org/packages/28/2f/78a766c8913ad62b28581777ac4ede50c6d9f249d39c2963e279524a1bbe/pyzmq-26.2.0-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:ded0fc7d90fe93ae0b18059930086c51e640cdd3baebdc783a695c77f123dcd9", size = 1343105 }, { url = "https://files.pythonhosted.org/packages/b7/9c/4b1e2d3d4065be715e007fe063ec7885978fad285f87eae1436e6c3201f4/pyzmq-26.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:17bf5a931c7f6618023cdacc7081f3f266aecb68ca692adac015c383a134ca52", size = 1008365 }, { url = "https://files.pythonhosted.org/packages/4f/ef/5a23ec689ff36d7625b38d121ef15abfc3631a9aecb417baf7a4245e4124/pyzmq-26.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55cf66647e49d4621a7e20c8d13511ef1fe1efbbccf670811864452487007e08", size = 665923 }, @@ -2796,6 +3046,21 @@ version = "2024.11.6" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/8e/5f/bd69653fbfb76cf8604468d3b4ec4c403197144c7bfe0e6a5fc9e02a07cb/regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519", size = 399494 } wheels = [ + { url = "https://files.pythonhosted.org/packages/58/58/7e4d9493a66c88a7da6d205768119f51af0f684fe7be7bac8328e217a52c/regex-2024.11.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638", size = 482669 }, + { url = "https://files.pythonhosted.org/packages/34/4c/8f8e631fcdc2ff978609eaeef1d6994bf2f028b59d9ac67640ed051f1218/regex-2024.11.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7", size = 287684 }, + { url = "https://files.pythonhosted.org/packages/c5/1b/f0e4d13e6adf866ce9b069e191f303a30ab1277e037037a365c3aad5cc9c/regex-2024.11.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20", size = 284589 }, + { url = "https://files.pythonhosted.org/packages/25/4d/ab21047f446693887f25510887e6820b93f791992994f6498b0318904d4a/regex-2024.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114", size = 792121 }, + { url = "https://files.pythonhosted.org/packages/45/ee/c867e15cd894985cb32b731d89576c41a4642a57850c162490ea34b78c3b/regex-2024.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3", size = 831275 }, + { url = "https://files.pythonhosted.org/packages/b3/12/b0f480726cf1c60f6536fa5e1c95275a77624f3ac8fdccf79e6727499e28/regex-2024.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f", size = 818257 }, + { url = "https://files.pythonhosted.org/packages/bf/ce/0d0e61429f603bac433910d99ef1a02ce45a8967ffbe3cbee48599e62d88/regex-2024.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0", size = 792727 }, + { url = "https://files.pythonhosted.org/packages/e4/c1/243c83c53d4a419c1556f43777ccb552bccdf79d08fda3980e4e77dd9137/regex-2024.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55", size = 780667 }, + { url = "https://files.pythonhosted.org/packages/c5/f4/75eb0dd4ce4b37f04928987f1d22547ddaf6c4bae697623c1b05da67a8aa/regex-2024.11.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89", size = 776963 }, + { url = "https://files.pythonhosted.org/packages/16/5d/95c568574e630e141a69ff8a254c2f188b4398e813c40d49228c9bbd9875/regex-2024.11.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d", size = 784700 }, + { url = "https://files.pythonhosted.org/packages/8e/b5/f8495c7917f15cc6fee1e7f395e324ec3e00ab3c665a7dc9d27562fd5290/regex-2024.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34", size = 848592 }, + { url = "https://files.pythonhosted.org/packages/1c/80/6dd7118e8cb212c3c60b191b932dc57db93fb2e36fb9e0e92f72a5909af9/regex-2024.11.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d", size = 852929 }, + { url = "https://files.pythonhosted.org/packages/11/9b/5a05d2040297d2d254baf95eeeb6df83554e5e1df03bc1a6687fc4ba1f66/regex-2024.11.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45", size = 781213 }, + { url = "https://files.pythonhosted.org/packages/26/b7/b14e2440156ab39e0177506c08c18accaf2b8932e39fb092074de733d868/regex-2024.11.6-cp311-cp311-win32.whl", hash = "sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9", size = 261734 }, + { url = "https://files.pythonhosted.org/packages/80/32/763a6cc01d21fb3819227a1cc3f60fd251c13c37c27a73b8ff4315433a8e/regex-2024.11.6-cp311-cp311-win_amd64.whl", hash = "sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60", size = 274052 }, { url = "https://files.pythonhosted.org/packages/ba/30/9a87ce8336b172cc232a0db89a3af97929d06c11ceaa19d97d84fa90a8f8/regex-2024.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a", size = 483781 }, { url = "https://files.pythonhosted.org/packages/01/e8/00008ad4ff4be8b1844786ba6636035f7ef926db5686e4c0f98093612add/regex-2024.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9", size = 288455 }, { url = "https://files.pythonhosted.org/packages/60/85/cebcc0aff603ea0a201667b203f13ba75d9fc8668fab917ac5b2de3967bc/regex-2024.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2", size = 284759 }, @@ -2896,6 +3161,19 @@ version = "0.22.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/01/80/cce854d0921ff2f0a9fa831ba3ad3c65cee3a46711addf39a2af52df2cfd/rpds_py-0.22.3.tar.gz", hash = "sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d", size = 26771 } wheels = [ + { url = "https://files.pythonhosted.org/packages/15/ad/8d1ddf78f2805a71253fcd388017e7b4a0615c22c762b6d35301fef20106/rpds_py-0.22.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d20cfb4e099748ea39e6f7b16c91ab057989712d31761d3300d43134e26e165f", size = 359773 }, + { url = "https://files.pythonhosted.org/packages/c8/75/68c15732293a8485d79fe4ebe9045525502a067865fa4278f178851b2d87/rpds_py-0.22.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:68049202f67380ff9aa52f12e92b1c30115f32e6895cd7198fa2a7961621fc5a", size = 349214 }, + { url = "https://files.pythonhosted.org/packages/3c/4c/7ce50f3070083c2e1b2bbd0fb7046f3da55f510d19e283222f8f33d7d5f4/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb4f868f712b2dd4bcc538b0a0c1f63a2b1d584c925e69a224d759e7070a12d5", size = 380477 }, + { url = "https://files.pythonhosted.org/packages/9a/e9/835196a69cb229d5c31c13b8ae603bd2da9a6695f35fe4270d398e1db44c/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc51abd01f08117283c5ebf64844a35144a0843ff7b2983e0648e4d3d9f10dbb", size = 386171 }, + { url = "https://files.pythonhosted.org/packages/f9/8e/33fc4eba6683db71e91e6d594a2cf3a8fbceb5316629f0477f7ece5e3f75/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3cec041684de9a4684b1572fe28c7267410e02450f4561700ca5a3bc6695a2", size = 422676 }, + { url = "https://files.pythonhosted.org/packages/37/47/2e82d58f8046a98bb9497a8319604c92b827b94d558df30877c4b3c6ccb3/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ef9d9da710be50ff6809fed8f1963fecdfecc8b86656cadfca3bc24289414b0", size = 446152 }, + { url = "https://files.pythonhosted.org/packages/e1/78/79c128c3e71abbc8e9739ac27af11dc0f91840a86fce67ff83c65d1ba195/rpds_py-0.22.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59f4a79c19232a5774aee369a0c296712ad0e77f24e62cad53160312b1c1eaa1", size = 381300 }, + { url = "https://files.pythonhosted.org/packages/c9/5b/2e193be0e8b228c1207f31fa3ea79de64dadb4f6a4833111af8145a6bc33/rpds_py-0.22.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a60bce91f81ddaac922a40bbb571a12c1070cb20ebd6d49c48e0b101d87300d", size = 409636 }, + { url = "https://files.pythonhosted.org/packages/c2/3f/687c7100b762d62186a1c1100ffdf99825f6fa5ea94556844bbbd2d0f3a9/rpds_py-0.22.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e89391e6d60251560f0a8f4bd32137b077a80d9b7dbe6d5cab1cd80d2746f648", size = 556708 }, + { url = "https://files.pythonhosted.org/packages/8c/a2/c00cbc4b857e8b3d5e7f7fc4c81e23afd8c138b930f4f3ccf9a41a23e9e4/rpds_py-0.22.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e3fb866d9932a3d7d0c82da76d816996d1667c44891bd861a0f97ba27e84fc74", size = 583554 }, + { url = "https://files.pythonhosted.org/packages/d0/08/696c9872cf56effdad9ed617ac072f6774a898d46b8b8964eab39ec562d2/rpds_py-0.22.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1352ae4f7c717ae8cba93421a63373e582d19d55d2ee2cbb184344c82d2ae55a", size = 552105 }, + { url = "https://files.pythonhosted.org/packages/18/1f/4df560be1e994f5adf56cabd6c117e02de7c88ee238bb4ce03ed50da9d56/rpds_py-0.22.3-cp311-cp311-win32.whl", hash = "sha256:b0b4136a252cadfa1adb705bb81524eee47d9f6aab4f2ee4fa1e9d3cd4581f64", size = 220199 }, + { url = "https://files.pythonhosted.org/packages/b8/1b/c29b570bc5db8237553002788dc734d6bd71443a2ceac2a58202ec06ef12/rpds_py-0.22.3-cp311-cp311-win_amd64.whl", hash = "sha256:8bd7c8cfc0b8247c8799080fbff54e0b9619e17cdfeb0478ba7295d43f635d7c", size = 231775 }, { url = "https://files.pythonhosted.org/packages/75/47/3383ee3bd787a2a5e65a9b9edc37ccf8505c0a00170e3a5e6ea5fbcd97f7/rpds_py-0.22.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e", size = 352334 }, { url = "https://files.pythonhosted.org/packages/40/14/aa6400fa8158b90a5a250a77f2077c0d0cd8a76fce31d9f2b289f04c6dec/rpds_py-0.22.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56", size = 342111 }, { url = "https://files.pythonhosted.org/packages/7d/06/395a13bfaa8a28b302fb433fb285a67ce0ea2004959a027aea8f9c52bad4/rpds_py-0.22.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45", size = 384286 }, @@ -3065,6 +3343,11 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/6b/de/f43d9c827ccc1974696ffd3c0495e2d4e98b0414b2353b7de932621f23dd/snowflake_connector_python-3.12.4.tar.gz", hash = "sha256:289e0691dfbf8ec8b7a8f58bcbb95a819890fe5e5b278fdbfc885059a63a946f", size = 743445 } wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/95/e8aac28d6913e4b59f96e6d361f31b9576b5f0abe4d2c4f7decf9f075932/snowflake_connector_python-3.12.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ec5cfaa1526084cf4d0e7849d5ace601245cb4ad9675ab3cd7d799b3abea481", size = 958125 }, + { url = "https://files.pythonhosted.org/packages/67/b6/a847a94e03bdf39010048feacd57f250a91a655eed333d7d32b165f65201/snowflake_connector_python-3.12.4-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:ff225824b3a0fa5e822442de72172f97028f04ae183877f1305d538d8d6c5d11", size = 970770 }, + { url = "https://files.pythonhosted.org/packages/0e/91/f97812ae9946944bcd9bfe1965af1cb9b1844919da879d90b90dfd3e5086/snowflake_connector_python-3.12.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9beced2789dc75e8f1e749aa637e7ec9b03302b4ed4b793ae0f1ff32823370e", size = 2519875 }, + { url = "https://files.pythonhosted.org/packages/37/52/500d72079bfb322ebdf3892180ecf3dc73c117b3a966ee8d4bb1378882b2/snowflake_connector_python-3.12.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ea47450a04ff713f3adf28053e34103bd990291e62daee9721c76597af4b2b5", size = 2542320 }, + { url = "https://files.pythonhosted.org/packages/59/92/74ead6bee8dd29fe372002ce59477221e04b9da96ad7aafe584afce02937/snowflake_connector_python-3.12.4-cp311-cp311-win_amd64.whl", hash = "sha256:748f9125854dca07ea471bb2bb3c5bb932a53f9b8a77ba348b50b738c77203ce", size = 918363 }, { url = "https://files.pythonhosted.org/packages/a5/a3/1cbe0b52b810f069bdc96c372b2d91ac51aeac32986c2832aa3fe0b0b0e5/snowflake_connector_python-3.12.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4bcd0371b20d199f15e6a3c0b489bf18e27f2a88c84cf3194b2569ca039fa7d1", size = 957561 }, { url = "https://files.pythonhosted.org/packages/f4/05/8a5e16bd908a89f36d59686d356890c4bd6a976a487f86274181010f4b49/snowflake_connector_python-3.12.4-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:7900d82a450b206fa2ed6c42cd65d9b3b9fd4547eca1696937175fac2a03ba37", size = 969045 }, { url = "https://files.pythonhosted.org/packages/79/1b/8f5ab15d224d7bf76533c55cfd8ce73b185ce94d84241f0e900739ce3f37/snowflake_connector_python-3.12.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:300f0562aeea55e40ee03b45205dbef7b78f5ba2f1787a278c7b807e7d8db22c", size = 2533969 }, @@ -3117,6 +3400,11 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/21/1e/94e3981516db6fcd6685f058c43c3fa81805c120b04829596367dad1aa4e/spacy-3.7.5.tar.gz", hash = "sha256:a648c6cbf2acc7a55a69ee9e7fa4f22bdf69aa828a587a1bc5cfff08cf3c2dd3", size = 1274806 } wheels = [ + { url = "https://files.pythonhosted.org/packages/80/36/53a831d2e82a432d785823cdff56f84737aed26e8f7667d423ee32c3983d/spacy-3.7.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cd93c34bf2a02bbed7df73d42aed8df5e3eb9688c4ea84ec576f740ba939cce5", size = 6750524 }, + { url = "https://files.pythonhosted.org/packages/72/49/bd65abe76607c86dc1f104ad545eeb3e771f474b7e259e64e5a16614615b/spacy-3.7.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:190ba0032a5efdb138487c587c0ebb7a98f86adb917f464b252ee8766b8eec4a", size = 6517941 }, + { url = "https://files.pythonhosted.org/packages/51/83/ec38e9bddb17b8f07539a49a19f2b30ce8e7d7a3d4f94dda31ea9bd043f7/spacy-3.7.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38de1c9bbb73b8cdfea2dd6e57450f093c1a1af47515870c1c8640b85b35ab16", size = 6236788 }, + { url = "https://files.pythonhosted.org/packages/e0/ce/b5e6b02165881547ad251b0b172ebf496b9181a95833f94012af82d044df/spacy-3.7.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3dad4853950a2fe6c7a0bdfd791a762d1f8cedd2915c4ae41b2e0ca3a850eefc", size = 6585757 }, + { url = "https://files.pythonhosted.org/packages/39/e1/08681583569f435347ced0535b27c073fcc9a927d9b4293c963092f2d01c/spacy-3.7.5-cp311-cp311-win_amd64.whl", hash = "sha256:4e00d076871af784c2e43185a71ee676b58893853a05c5b81717b8af2b666c07", size = 12078792 }, { url = "https://files.pythonhosted.org/packages/3d/c8/413225de79e71dd9ca353d597ea4890a43fa60ff98cf9615b1606680ab95/spacy-3.7.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:bf54c3c2425428b328b53a65913d47eb4cb27a1429aa4e8ed979ffc97d4663e0", size = 6324302 }, { url = "https://files.pythonhosted.org/packages/60/f9/726e977c5430c44912ed97d7d965ef35d2563978b38076b254379652a522/spacy-3.7.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4145cea7f9814fa7d86b2028c2dd83e02f13f80d5ac604a400b2f7d7b26a0e8c", size = 6112434 }, { url = "https://files.pythonhosted.org/packages/53/ff/4b3a9d3063ba98d3ce27a0c2a60e3c25e4650b7c3c7555a47179dac5c282/spacy-3.7.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:262f8ebb71f7ed5ffe8e4f384b2594b7a296be50241ce9fbd9277b5da2f46f38", size = 6065925 }, @@ -3162,6 +3450,16 @@ version = "0.3.5" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/bd/76/bb4288728fa00410bee939e9c23a0762a247c69b13c2ef3ee011f0cb33de/sqlglotrs-0.3.5.tar.gz", hash = "sha256:a945f88f21e9d952a129ed16c9201fefd7b0199d076b7a8c9cb02021374e5a4f", size = 15318 } wheels = [ + { url = "https://files.pythonhosted.org/packages/a8/40/2b90f38674d4706cb672a6051c98f45b8dc9ac9f18b57a17831c27016e84/sqlglotrs-0.3.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:47b5743340ac3096328b9483a1ef38b4e04a75b9ab37c58378a077a24421b406", size = 295690 }, + { url = "https://files.pythonhosted.org/packages/01/85/5d597c499d9b0bd4f215f31394a59000ba2127c6b885cec4877ac26897b6/sqlglotrs-0.3.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cd78c9329687dcd5ffca7e58d8b7149870010f0a1f56780ad686397f5551e49d", size = 283413 }, + { url = "https://files.pythonhosted.org/packages/ef/92/02326ef7ac34f96241e29685418fc4de1a1d789950440966519f9d613d76/sqlglotrs-0.3.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:340503046cc9969212e0986808bbacafc5ecf143c33677f049b10c2d491e4ab1", size = 326138 }, + { url = "https://files.pythonhosted.org/packages/71/8d/f3d6436a97ecd5c8f5a27d09288a88f7998aa4d81b0018351af645f69f98/sqlglotrs-0.3.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c58c987f9d9640815c7d476d673d4b9764fb1d0af782c3226be18c8b24ca1914", size = 332401 }, + { url = "https://files.pythonhosted.org/packages/34/d1/6f60e371c6851b41c8b75ecdd9439c516836b5cf6d9bb0e6fa163becdfae/sqlglotrs-0.3.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0644013e833e23fca14884f74172e9b3695391b5bd435d568f53888c40fcf5ec", size = 394955 }, + { url = "https://files.pythonhosted.org/packages/da/f9/40f26cd462bbbbcc1fe6f4cccde13e2e2c3a2fb22a9c5a3a437a091a5f05/sqlglotrs-0.3.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f8b12002b7526bef4682fe7fc6015a8fcdbc92ead80ad9f2622247203313dd17", size = 385790 }, + { url = "https://files.pythonhosted.org/packages/b5/8e/f9bebb40e7643fac8d7eddb93510e0f5bb8a800b81d87e9322924f00a598/sqlglotrs-0.3.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0056bc5ee81ab1de22a22c964403da6f99056ff23ee0d1544b85322c94ff8a05", size = 331043 }, + { url = "https://files.pythonhosted.org/packages/8d/35/cf9260f629a25b9a91c857d3def3d8a186f0d5b83a61ce486fa50a8f7cbc/sqlglotrs-0.3.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdfc6a8f7be92193c823568e2467a9b2e0d739274160e538117950afba57e1ab", size = 348245 }, + { url = "https://files.pythonhosted.org/packages/70/ab/e14b861d91c5f4c2c499c844c364d69fd7dcd479dc6d804626e7aae7e2a4/sqlglotrs-0.3.5-cp311-cp311-win32.whl", hash = "sha256:0ca2945cdcb4335124886b09aa61dc61507f309eb3580431a0d4cbea91150edd", size = 173443 }, + { url = "https://files.pythonhosted.org/packages/75/9b/29e0684923e0c2bac8a7d363fdb7d0b047d6c70d0c2cfc30d2cf1405e92c/sqlglotrs-0.3.5-cp311-cp311-win_amd64.whl", hash = "sha256:f75ec7d8cc825120fdf6d878b2b3707f7bc7069a919dcfacf8b8426b67596312", size = 189237 }, { url = "https://files.pythonhosted.org/packages/d1/26/803a0e5f41c29f1d35e693816fb70e63377fc9541c04b650d03863b7c88d/sqlglotrs-0.3.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:91226d385734aa186b0e1ac402d7d12dbec92073bf7e51b6d026db01b497bf99", size = 295736 }, { url = "https://files.pythonhosted.org/packages/04/1c/f3def87b02edbf4b07ba4d4bb15fa7727bb9a46b775053eb0308d0d36cb1/sqlglotrs-0.3.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d21beeaa3508f9e69dd8d2836d767faff2cf5d44c6acf0714d6bac71259b704c", size = 283773 }, { url = "https://files.pythonhosted.org/packages/90/1d/ba039b604e5a9f1f8f0afb7991745ab3f69fbb733be7f2b32c5933b80fbb/sqlglotrs-0.3.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5daea06ac755b17512eaaf234320f283f6b019def43bc27e9f980026f8e9482c", size = 326529 }, @@ -3202,6 +3500,13 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/b7/e8/eb51b1349f50bac0222398af0942613fdc9d1453ae67cbe4bf9936a1a54b/srsly-2.5.1.tar.gz", hash = "sha256:ab1b4bf6cf3e29da23dae0493dd1517fb787075206512351421b89b4fc27c77e", size = 466464 } wheels = [ + { url = "https://files.pythonhosted.org/packages/df/9c/a248bb49de499fe0990e3cb0fb341c2373d8863ef9a8b5799353cade5731/srsly-2.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58f0736794ce00a71d62a39cbba1d62ea8d5be4751df956e802d147da20ecad7", size = 635917 }, + { url = "https://files.pythonhosted.org/packages/41/47/1bdaad84502df973ecb8ca658117234cf7fb20e1dec60da71dce82de993f/srsly-2.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7a8269c40859806d71920396d185f4f38dc985cdb6a28d3a326a701e29a5f629", size = 634374 }, + { url = "https://files.pythonhosted.org/packages/e5/2a/d73c71989fcf2a6d1fa518d75322aff4db01a8763f167f8c5e00aac11097/srsly-2.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:889905900401fefc1032e22b73aecbed8b4251aa363f632b2d1f86fc16f1ad8e", size = 1108390 }, + { url = "https://files.pythonhosted.org/packages/35/a3/9eda9997a8bd011caed18fdaa5ce606714eb06d8dab587ed0522b3e92ab1/srsly-2.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf454755f22589df49c25dc799d8af7b47dce3d861dded35baf0f0b6ceab4422", size = 1110712 }, + { url = "https://files.pythonhosted.org/packages/8a/ef/4b50bc05d06349f905b27f824cc23b652098efd4be19aead3af4981df647/srsly-2.5.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cc0607c8a59013a51dde5c1b4e465558728e9e0a35dcfa73c7cbefa91a0aad50", size = 1081244 }, + { url = "https://files.pythonhosted.org/packages/90/af/d4a2512d9a5048d2b18efead39d4c4404bddd4972935bbc68211292a736c/srsly-2.5.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d5421ba3ab3c790e8b41939c51a1d0f44326bfc052d7a0508860fb79a47aee7f", size = 1091692 }, + { url = "https://files.pythonhosted.org/packages/bb/da/657a685f63028dcb00ccdc4ac125ed347c8bff6fa0dab6a9eb3dc45f3223/srsly-2.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:b96ea5a9a0d0379a79c46d255464a372fb14c30f59a8bc113e4316d131a530ab", size = 632627 }, { url = "https://files.pythonhosted.org/packages/fb/f6/bebc20d75bd02121fc0f65ad8c92a5dd2570e870005e940faa55a263e61a/srsly-2.5.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:683b54ed63d7dfee03bc2abc4b4a5f2152f81ec217bbadbac01ef1aaf2a75790", size = 636717 }, { url = "https://files.pythonhosted.org/packages/b6/e8/9372317a4742c70b87b413335adfcdfb2bee4f88f3faba89fabb9e6abf21/srsly-2.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:459d987130e57e83ce9e160899afbeb871d975f811e6958158763dd9a8a20f23", size = 634697 }, { url = "https://files.pythonhosted.org/packages/d5/00/c6a7b99ab27b051a27bd26fe1a8c1885225bb8980282bf9cb99f70610368/srsly-2.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:184e3c98389aab68ff04aab9095bd5f1a8e5a72cc5edcba9d733bac928f5cf9f", size = 1134655 }, @@ -3373,6 +3678,11 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/3b/2a/0e2e961e6152bedecca70e6833f6e827ee621efcee7496643242b506d54f/thinc-8.2.5.tar.gz", hash = "sha256:c2963791c934cc7fbd8f9b942d571cac79892ad11630bfca690a868c32752b75", size = 193031 } wheels = [ + { url = "https://files.pythonhosted.org/packages/76/37/8acfeba6bb25b08c2a33bfae5301a5df4dc164d2d17040bebbcf66d783a1/thinc-8.2.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a75c0de3340afed594beda293661de145f3842873df56d9989bc338148f13fab", size = 839072 }, + { url = "https://files.pythonhosted.org/packages/e9/eb/753a85875fb0261c83ca87a1a36d41346bde662c3a029ace9d68fe32bc5b/thinc-8.2.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6b166d1a22003ee03bc236370fff2884744c1fb758a6209a2512d305773d07d7", size = 773885 }, + { url = "https://files.pythonhosted.org/packages/34/47/06810a1bd9d3287076ba17299abec82c8c643563661b1af9b1d5d9aeab38/thinc-8.2.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34db8a023b9f70645fdf06c510584ba6d8b97ec53c1e094f42d95652bf8c875f", size = 868332 }, + { url = "https://files.pythonhosted.org/packages/1a/19/cd73e3b5f22d5d9399f6f2931ab0fb985415f34030dcfead070181866761/thinc-8.2.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8901b30db1071ea8d5e4437429c8632535bf5ed87938ce3bb5057bed9f15aed8", size = 920152 }, + { url = "https://files.pythonhosted.org/packages/5e/0e/5e7b24e046e0725eafc37ded0cd9bfaf789efb894101a7aca8a73dba81de/thinc-8.2.5-cp311-cp311-win_amd64.whl", hash = "sha256:8ef5d46d62e31f2450224ab22391a606cf427b13e20cfc570f70422e2f333872", size = 1480120 }, { url = "https://files.pythonhosted.org/packages/a4/9d/d2ed3aef9bb75ab86c521bde58f897db6a572c9fd639448173b516269a69/thinc-8.2.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9fc26697e2358c71a5fe243d52e98ae67ee1a3b314eead5031845b6d1c0d121c", size = 824150 }, { url = "https://files.pythonhosted.org/packages/66/a6/30ed1edb2adab585b5f7d5d99e89b5be3014dcbf3f4e263997b2c2426681/thinc-8.2.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8e299d4dc41107385d6d14d8604a060825798a031cabe2b894b22f9d75d9eaad", size = 760640 }, { url = "https://files.pythonhosted.org/packages/82/ce/aaff1f39bcc1e9a97bec5f3d20aa771c005a9faff3944fc56c7492c24466/thinc-8.2.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8a8f2f249f2be9a5ce2a81a6efe7503b68be7b57e47ad54ab28204e1f0c723b", size = 818820 }, @@ -3399,6 +3709,12 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/37/02/576ff3a6639e755c4f70997b2d315f56d6d71e0d046f4fb64cb81a3fb099/tiktoken-0.8.0.tar.gz", hash = "sha256:9ccbb2740f24542534369c5635cfd9b2b3c2490754a78ac8831d99f89f94eeb2", size = 35107 } wheels = [ + { url = "https://files.pythonhosted.org/packages/f6/1e/ca48e7bfeeccaf76f3a501bd84db1fa28b3c22c9d1a1f41af9fb7579c5f6/tiktoken-0.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d622d8011e6d6f239297efa42a2657043aaed06c4f68833550cac9e9bc723ef1", size = 1039700 }, + { url = "https://files.pythonhosted.org/packages/8c/f8/f0101d98d661b34534769c3818f5af631e59c36ac6d07268fbfc89e539ce/tiktoken-0.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2efaf6199717b4485031b4d6edb94075e4d79177a172f38dd934d911b588d54a", size = 982413 }, + { url = "https://files.pythonhosted.org/packages/ac/3c/2b95391d9bd520a73830469f80a96e3790e6c0a5ac2444f80f20b4b31051/tiktoken-0.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5637e425ce1fc49cf716d88df3092048359a4b3bbb7da762840426e937ada06d", size = 1144242 }, + { url = "https://files.pythonhosted.org/packages/01/c4/c4a4360de845217b6aa9709c15773484b50479f36bb50419c443204e5de9/tiktoken-0.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fb0e352d1dbe15aba082883058b3cce9e48d33101bdaac1eccf66424feb5b47", size = 1176588 }, + { url = "https://files.pythonhosted.org/packages/f8/a3/ef984e976822cd6c2227c854f74d2e60cf4cd6fbfca46251199914746f78/tiktoken-0.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:56edfefe896c8f10aba372ab5706b9e3558e78db39dd497c940b47bf228bc419", size = 1237261 }, + { url = "https://files.pythonhosted.org/packages/1e/86/eea2309dc258fb86c7d9b10db536434fc16420feaa3b6113df18b23db7c2/tiktoken-0.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:326624128590def898775b722ccc327e90b073714227175ea8febbc920ac0a99", size = 884537 }, { url = "https://files.pythonhosted.org/packages/c1/22/34b2e136a6f4af186b6640cbfd6f93400783c9ef6cd550d9eab80628d9de/tiktoken-0.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:881839cfeae051b3628d9823b2e56b5cc93a9e2efb435f4cf15f17dc45f21586", size = 1039357 }, { url = "https://files.pythonhosted.org/packages/04/d2/c793cf49c20f5855fd6ce05d080c0537d7418f22c58e71f392d5e8c8dbf7/tiktoken-0.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fe9399bdc3f29d428f16a2f86c3c8ec20be3eac5f53693ce4980371c3245729b", size = 982616 }, { url = "https://files.pythonhosted.org/packages/b3/a1/79846e5ef911cd5d75c844de3fa496a10c91b4b5f550aad695c5df153d72/tiktoken-0.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a58deb7075d5b69237a3ff4bb51a726670419db6ea62bdcd8bd80c78497d7ab", size = 1144011 }, @@ -3655,6 +3971,17 @@ version = "1.17.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/c3/fc/e91cc220803d7bc4db93fb02facd8461c37364151b8494762cc88b0fbcef/wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3", size = 55531 } wheels = [ + { url = "https://files.pythonhosted.org/packages/cd/f7/a2aab2cbc7a665efab072344a8949a71081eed1d2f451f7f7d2b966594a2/wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58", size = 53308 }, + { url = "https://files.pythonhosted.org/packages/50/ff/149aba8365fdacef52b31a258c4dc1c57c79759c335eff0b3316a2664a64/wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda", size = 38488 }, + { url = "https://files.pythonhosted.org/packages/65/46/5a917ce85b5c3b490d35c02bf71aedaa9f2f63f2d15d9949cc4ba56e8ba9/wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438", size = 38776 }, + { url = "https://files.pythonhosted.org/packages/ca/74/336c918d2915a4943501c77566db41d1bd6e9f4dbc317f356b9a244dfe83/wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a", size = 83776 }, + { url = "https://files.pythonhosted.org/packages/09/99/c0c844a5ccde0fe5761d4305485297f91d67cf2a1a824c5f282e661ec7ff/wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000", size = 75420 }, + { url = "https://files.pythonhosted.org/packages/b4/b0/9fc566b0fe08b282c850063591a756057c3247b2362b9286429ec5bf1721/wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6", size = 83199 }, + { url = "https://files.pythonhosted.org/packages/9d/4b/71996e62d543b0a0bd95dda485219856def3347e3e9380cc0d6cf10cfb2f/wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b", size = 82307 }, + { url = "https://files.pythonhosted.org/packages/39/35/0282c0d8789c0dc9bcc738911776c762a701f95cfe113fb8f0b40e45c2b9/wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662", size = 75025 }, + { url = "https://files.pythonhosted.org/packages/4f/6d/90c9fd2c3c6fee181feecb620d95105370198b6b98a0770cba090441a828/wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72", size = 81879 }, + { url = "https://files.pythonhosted.org/packages/8f/fa/9fb6e594f2ce03ef03eddbdb5f4f90acb1452221a5351116c7c4708ac865/wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317", size = 36419 }, + { url = "https://files.pythonhosted.org/packages/47/f8/fb1773491a253cbc123c5d5dc15c86041f746ed30416535f2a8df1f4a392/wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3", size = 38773 }, { url = "https://files.pythonhosted.org/packages/a1/bd/ab55f849fd1f9a58ed7ea47f5559ff09741b25f00c191231f9f059c83949/wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925", size = 53799 }, { url = "https://files.pythonhosted.org/packages/53/18/75ddc64c3f63988f5a1d7e10fb204ffe5762bc663f8023f18ecaf31a332e/wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392", size = 38821 }, { url = "https://files.pythonhosted.org/packages/48/2a/97928387d6ed1c1ebbfd4efc4133a0633546bec8481a2dd5ec961313a1c7/wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40", size = 38919 }, @@ -3702,6 +4029,22 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/b7/9d/4b94a8e6d2b51b599516a5cb88e5bc99b4d8d4583e468057eaa29d5f0918/yarl-1.18.3.tar.gz", hash = "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1", size = 181062 } wheels = [ + { url = "https://files.pythonhosted.org/packages/40/93/282b5f4898d8e8efaf0790ba6d10e2245d2c9f30e199d1a85cae9356098c/yarl-1.18.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069", size = 141555 }, + { url = "https://files.pythonhosted.org/packages/6d/9c/0a49af78df099c283ca3444560f10718fadb8a18dc8b3edf8c7bd9fd7d89/yarl-1.18.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193", size = 94351 }, + { url = "https://files.pythonhosted.org/packages/5a/a1/205ab51e148fdcedad189ca8dd587794c6f119882437d04c33c01a75dece/yarl-1.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889", size = 92286 }, + { url = "https://files.pythonhosted.org/packages/ed/fe/88b690b30f3f59275fb674f5f93ddd4a3ae796c2b62e5bb9ece8a4914b83/yarl-1.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d980e0325b6eddc81331d3f4551e2a333999fb176fd153e075c6d1c2530aa8a8", size = 340649 }, + { url = "https://files.pythonhosted.org/packages/07/eb/3b65499b568e01f36e847cebdc8d7ccb51fff716dbda1ae83c3cbb8ca1c9/yarl-1.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca", size = 356623 }, + { url = "https://files.pythonhosted.org/packages/33/46/f559dc184280b745fc76ec6b1954de2c55595f0ec0a7614238b9ebf69618/yarl-1.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8", size = 354007 }, + { url = "https://files.pythonhosted.org/packages/af/ba/1865d85212351ad160f19fb99808acf23aab9a0f8ff31c8c9f1b4d671fc9/yarl-1.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae", size = 344145 }, + { url = "https://files.pythonhosted.org/packages/94/cb/5c3e975d77755d7b3d5193e92056b19d83752ea2da7ab394e22260a7b824/yarl-1.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3", size = 336133 }, + { url = "https://files.pythonhosted.org/packages/19/89/b77d3fd249ab52a5c40859815765d35c91425b6bb82e7427ab2f78f5ff55/yarl-1.18.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb", size = 347967 }, + { url = "https://files.pythonhosted.org/packages/35/bd/f6b7630ba2cc06c319c3235634c582a6ab014d52311e7d7c22f9518189b5/yarl-1.18.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e", size = 346397 }, + { url = "https://files.pythonhosted.org/packages/18/1a/0b4e367d5a72d1f095318344848e93ea70da728118221f84f1bf6c1e39e7/yarl-1.18.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59", size = 350206 }, + { url = "https://files.pythonhosted.org/packages/b5/cf/320fff4367341fb77809a2d8d7fe75b5d323a8e1b35710aafe41fdbf327b/yarl-1.18.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d", size = 362089 }, + { url = "https://files.pythonhosted.org/packages/57/cf/aadba261d8b920253204085268bad5e8cdd86b50162fcb1b10c10834885a/yarl-1.18.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e", size = 366267 }, + { url = "https://files.pythonhosted.org/packages/54/58/fb4cadd81acdee6dafe14abeb258f876e4dd410518099ae9a35c88d8097c/yarl-1.18.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a", size = 359141 }, + { url = "https://files.pythonhosted.org/packages/9a/7a/4c571597589da4cd5c14ed2a0b17ac56ec9ee7ee615013f74653169e702d/yarl-1.18.3-cp311-cp311-win32.whl", hash = "sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1", size = 84402 }, + { url = "https://files.pythonhosted.org/packages/ae/7b/8600250b3d89b625f1121d897062f629883c2f45339623b69b1747ec65fa/yarl-1.18.3-cp311-cp311-win_amd64.whl", hash = "sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5", size = 91030 }, { url = "https://files.pythonhosted.org/packages/33/85/bd2e2729752ff4c77338e0102914897512e92496375e079ce0150a6dc306/yarl-1.18.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50", size = 142644 }, { url = "https://files.pythonhosted.org/packages/ff/74/1178322cc0f10288d7eefa6e4a85d8d2e28187ccab13d5b844e8b5d7c88d/yarl-1.18.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576", size = 94962 }, { url = "https://files.pythonhosted.org/packages/be/75/79c6acc0261e2c2ae8a1c41cf12265e91628c8c58ae91f5ff59e29c0787f/yarl-1.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640", size = 92795 }, From dead88705249b954904a74de43464cb0f0a9317a Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 20:14:13 +0000 Subject: [PATCH 46/64] Bump version --- .github/workflows/ci-checks.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-checks.yaml b/.github/workflows/ci-checks.yaml index 04228acd..e8c59ffb 100644 --- a/.github/workflows/ci-checks.yaml +++ b/.github/workflows/ci-checks.yaml @@ -10,7 +10,7 @@ on: - "*" # Run on all branches env: - MIN_PYTHON_VERSION: 3.11 + MIN_PYTHON_VERSION: 3.12 jobs: job-pre-commit-check: From 0a9c4bcf2f51642e62a03b398b898e1779456e97 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 20:16:34 +0000 Subject: [PATCH 47/64] Don't update lock --- .pre-commit-config.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dd5675ee..cb5e31e6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -45,12 +45,12 @@ repos: args: [--fix, --ignore, UP007] exclude: samples - - repo: https://github.com/astral-sh/uv-pre-commit - # uv version. - rev: 0.5.20 - hooks: - # Update the uv lockfile - - id: uv-lock + # - repo: https://github.com/astral-sh/uv-pre-commit + # # uv version. + # rev: 0.5.20 + # hooks: + # # Update the uv lockfile + # - id: uv-lock - repo: local hooks: From 7a0b5902058eed4ca87ee0436da9af42869700d4 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 20:20:07 +0000 Subject: [PATCH 48/64] Update --- .python-version | 2 +- pyproject.toml | 6 ------ uv.lock | 12 ------------ 3 files changed, 1 insertion(+), 19 deletions(-) diff --git a/.python-version b/.python-version index e4fba218..2c073331 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.12 +3.11 diff --git a/pyproject.toml b/pyproject.toml index 1a8292b5..ab9e813f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,12 +4,6 @@ version = "0.1.0" description = "This repo accelerates development of RAG applications with rich data sources including SQL Warehouses and documents analysed with Azure Document Intelligence." readme = "README.md" requires-python = ">=3.11" -dependencies = [ - "deploy_ai_search_indexes", - "image_processing", - "text_2_sql_core", - "autogen_text_2_sql", -] [dependency-groups] dev = [ diff --git a/uv.lock b/uv.lock index 01b1b134..afd07b14 100644 --- a/uv.lock +++ b/uv.lock @@ -1027,12 +1027,6 @@ wheels = [ name = "dstoolkit-text2sql-and-imageprocessing" version = "0.1.0" source = { virtual = "." } -dependencies = [ - { name = "autogen-text-2-sql" }, - { name = "deploy-ai-search-indexes" }, - { name = "image-processing" }, - { name = "text-2-sql-core" }, -] [package.dev-dependencies] dev = [ @@ -1046,12 +1040,6 @@ dev = [ ] [package.metadata] -requires-dist = [ - { name = "autogen-text-2-sql", virtual = "text_2_sql/autogen" }, - { name = "deploy-ai-search-indexes", virtual = "deploy_ai_search_indexes" }, - { name = "image-processing", virtual = "image_processing" }, - { name = "text-2-sql-core", editable = "text_2_sql/text_2_sql_core" }, -] [package.metadata.requires-dev] dev = [ From 9aa4a7739d067dd20ffce927b92a7d2fef63fe7f Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 20:24:56 +0000 Subject: [PATCH 49/64] Update --- .pre-commit-config.yaml | 28 ++--- .../src/image_processing/requirements.txt | 107 ------------------ 2 files changed, 15 insertions(+), 120 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cb5e31e6..aa440f7d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -45,17 +45,19 @@ repos: args: [--fix, --ignore, UP007] exclude: samples - # - repo: https://github.com/astral-sh/uv-pre-commit - # # uv version. - # rev: 0.5.20 - # hooks: - # # Update the uv lockfile - # - id: uv-lock - - - repo: local + - repo: https://github.com/astral-sh/uv-pre-commit + # uv version. + rev: 0.5.20 hooks: - - id: compile-image-processing-requirements - name: compile-image-processing-requirements - language: system - entry: bash -c 'cd image_processing && exec uv export --frozen --no-hashes --no-editable --no-sources --verbose --no-group dev > src/image_processing/requirements.txt && cat src/image_processing/requirements.txt' - pass_filenames: false + # Update the uv lockfile + - id: uv-lock + - id: uv-export + args: [--frozen, --no-hashes, --no-editable, --no-sources, --verbose, --no-group, dev, --project, image_processing] + + # - repo: local + # hooks: + # - id: compile-image-processing-requirements + # name: compile-image-processing-requirements + # language: system + # entry: bash -c 'cd image_processing && exec uv export --frozen --no-hashes --no-editable --no-sources --verbose --no-group dev > src/image_processing/requirements.txt && cat src/image_processing/requirements.txt' + # pass_filenames: false diff --git a/image_processing/src/image_processing/requirements.txt b/image_processing/src/image_processing/requirements.txt index c3bca5fc..e69de29b 100644 --- a/image_processing/src/image_processing/requirements.txt +++ b/image_processing/src/image_processing/requirements.txt @@ -1,107 +0,0 @@ -# This file was autogenerated by uv via the following command: -# uv export --frozen --no-hashes --no-editable --no-sources --no-group dev -aiohappyeyeballs==2.4.4 -aiohttp==3.11.11 -aiosignal==1.3.2 -annotated-types==0.7.0 -anyio==4.8.0 -attrs==24.3.0 -azure-ai-documentintelligence==1.0.0 -azure-ai-textanalytics==5.3.0 -azure-ai-vision-imageanalysis==1.0.0 -azure-common==1.1.28 -azure-core==1.32.0 -azure-functions==1.21.3 -azure-identity==1.19.0 -azure-search==1.0.0b2 -azure-search-documents==11.6.0b8 -azure-storage-blob==12.24.0 -beautifulsoup4==4.12.3 -blis==0.7.11 -bs4==0.0.2 -catalogue==2.0.10 -certifi==2024.12.14 -cffi==1.17.1 ; platform_python_implementation != 'PyPy' -charset-normalizer==3.4.1 -click==8.1.8 -cloudpathlib==0.20.0 -colorama==0.4.6 ; sys_platform == 'win32' or platform_system == 'Windows' -confection==0.1.5 -cryptography==44.0.0 -cymem==2.0.11 -distro==1.9.0 -en-core-web-md @ https://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.7.1/en_core_web_md-3.7.1.tar.gz -et-xmlfile==2.0.0 -filelock==3.17.0 -frozenlist==1.5.0 -fsspec==2024.12.0 -h11==0.14.0 -httpcore==1.0.7 -httpx==0.28.1 -huggingface-hub==0.27.1 -idna==3.10 -isodate==0.7.2 -jinja2==3.1.5 -jiter==0.8.2 -joblib==1.4.2 -langcodes==3.5.0 -language-data==1.3.0 -marisa-trie==1.2.1 -markdown-it-py==3.0.0 -markupsafe==3.0.2 -mdurl==0.1.2 -model2vec==0.3.7 -msal==1.31.1 -msal-extensions==1.2.0 -msrest==0.7.1 -multidict==6.1.0 -murmurhash==1.0.12 -numpy==1.26.4 -oauthlib==3.2.2 -openai==1.60.0 -openpyxl==3.1.5 -packaging==24.2 -pandas==2.2.3 -pillow==11.1.0 -portalocker==2.10.1 -preshed==3.0.9 -propcache==0.2.1 -pycparser==2.22 ; platform_python_implementation != 'PyPy' -pydantic==2.10.5 -pydantic-core==2.27.2 -pygments==2.19.1 -pyjwt==2.10.1 -pymupdf==1.25.2 -python-dateutil==2.9.0.post0 -python-dotenv==1.0.1 -pytz==2024.2 -pywin32==308 ; platform_system == 'Windows' -pyyaml==6.0.2 -regex==2024.11.6 -requests==2.32.3 -requests-oauthlib==2.0.0 -rich==13.9.4 -safetensors==0.5.2 -setuptools==75.8.0 -shellingham==1.5.4 -six==1.17.0 -smart-open==7.1.0 -sniffio==1.3.1 -soupsieve==2.6 -spacy==3.7.5 -spacy-legacy==3.0.12 -spacy-loggers==1.0.5 -srsly==2.5.1 -tenacity==9.0.0 -thinc==8.2.5 -tiktoken==0.8.0 -tokenizers==0.21.0 -tqdm==4.67.1 -typer==0.15.1 -typing-extensions==4.12.2 -tzdata==2025.1 -urllib3==2.3.0 -wasabi==1.1.3 -weasel==0.4.1 -wrapt==1.17.2 -yarl==1.18.3 From f3dcbb2374f03ad75fbade1308d927c7f93ce781 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 20:25:47 +0000 Subject: [PATCH 50/64] Update --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aa440f7d..9b95b7ae 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -52,7 +52,7 @@ repos: # Update the uv lockfile - id: uv-lock - id: uv-export - args: [--frozen, --no-hashes, --no-editable, --no-sources, --verbose, --no-group, dev, --project, image_processing] + args: [--frozen, --no-hashes, --no-editable, --no-sources, --verbose, --no-group, dev, --directory, image_processing] # - repo: local # hooks: From 64c5cc72bf1e64f3ae53d4c518fd461c3e168a4d Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 20:30:17 +0000 Subject: [PATCH 51/64] Add export --- .pre-commit-config.yaml | 2 +- image_processing/requirements.txt | 107 ++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 image_processing/requirements.txt diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9b95b7ae..4988af7a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -52,7 +52,7 @@ repos: # Update the uv lockfile - id: uv-lock - id: uv-export - args: [--frozen, --no-hashes, --no-editable, --no-sources, --verbose, --no-group, dev, --directory, image_processing] + args: [--frozen, --no-hashes, --no-editable, --no-sources, --verbose, --no-group, dev, --directory, image_processing, -o, requirements.txt] # - repo: local # hooks: diff --git a/image_processing/requirements.txt b/image_processing/requirements.txt new file mode 100644 index 00000000..ea5185a3 --- /dev/null +++ b/image_processing/requirements.txt @@ -0,0 +1,107 @@ +# This file was autogenerated by uv via the following command: +# uv export --frozen --no-hashes --no-editable --no-sources --no-group dev --directory image_processing -o requirements.txt +aiohappyeyeballs==2.4.4 +aiohttp==3.11.11 +aiosignal==1.3.2 +annotated-types==0.7.0 +anyio==4.8.0 +attrs==24.3.0 +azure-ai-documentintelligence==1.0.0 +azure-ai-textanalytics==5.3.0 +azure-ai-vision-imageanalysis==1.0.0 +azure-common==1.1.28 +azure-core==1.32.0 +azure-functions==1.21.3 +azure-identity==1.19.0 +azure-search==1.0.0b2 +azure-search-documents==11.6.0b8 +azure-storage-blob==12.24.0 +beautifulsoup4==4.12.3 +blis==0.7.11 +bs4==0.0.2 +catalogue==2.0.10 +certifi==2024.12.14 +cffi==1.17.1 ; platform_python_implementation != 'PyPy' +charset-normalizer==3.4.1 +click==8.1.8 +cloudpathlib==0.20.0 +colorama==0.4.6 ; sys_platform == 'win32' +confection==0.1.5 +cryptography==44.0.0 +cymem==2.0.11 +distro==1.9.0 +en-core-web-md @ https://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.7.1/en_core_web_md-3.7.1.tar.gz +et-xmlfile==2.0.0 +filelock==3.17.0 +frozenlist==1.5.0 +fsspec==2024.12.0 +h11==0.14.0 +httpcore==1.0.7 +httpx==0.28.1 +huggingface-hub==0.27.1 +idna==3.10 +isodate==0.7.2 +jinja2==3.1.5 +jiter==0.8.2 +joblib==1.4.2 +langcodes==3.5.0 +language-data==1.3.0 +marisa-trie==1.2.1 +markdown-it-py==3.0.0 +markupsafe==3.0.2 +mdurl==0.1.2 +model2vec==0.3.7 +msal==1.31.1 +msal-extensions==1.2.0 +msrest==0.7.1 +multidict==6.1.0 +murmurhash==1.0.12 +numpy==1.26.4 +oauthlib==3.2.2 +openai==1.60.0 +openpyxl==3.1.5 +packaging==24.2 +pandas==2.2.3 +pillow==11.1.0 +portalocker==2.10.1 +preshed==3.0.9 +propcache==0.2.1 +pycparser==2.22 ; platform_python_implementation != 'PyPy' +pydantic==2.10.5 +pydantic-core==2.27.2 +pygments==2.19.1 +pyjwt==2.10.1 +pymupdf==1.25.2 +python-dateutil==2.9.0.post0 +python-dotenv==1.0.1 +pytz==2024.2 +pywin32==308 ; sys_platform == 'win32' +pyyaml==6.0.2 +regex==2024.11.6 +requests==2.32.3 +requests-oauthlib==2.0.0 +rich==13.9.4 +safetensors==0.5.2 +setuptools==75.8.0 +shellingham==1.5.4 +six==1.17.0 +smart-open==7.1.0 +sniffio==1.3.1 +soupsieve==2.6 +spacy==3.7.5 +spacy-legacy==3.0.12 +spacy-loggers==1.0.5 +srsly==2.5.1 +tenacity==9.0.0 +thinc==8.2.5 +tiktoken==0.8.0 +tokenizers==0.21.0 +tqdm==4.67.1 +typer==0.15.1 +typing-extensions==4.12.2 +tzdata==2025.1 +urllib3==2.3.0 +wasabi==1.1.3 +weasel==0.4.1 +wrapt==1.17.2 +yarl==1.18.3 From d70244231046d8fdd7be44310a11d336bc2dacc6 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 20:31:29 +0000 Subject: [PATCH 52/64] Update --- .pre-commit-config.yaml | 10 +--------- image_processing/src/image_processing/requirements.txt | 0 2 files changed, 1 insertion(+), 9 deletions(-) delete mode 100644 image_processing/src/image_processing/requirements.txt diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4988af7a..96101597 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -52,12 +52,4 @@ repos: # Update the uv lockfile - id: uv-lock - id: uv-export - args: [--frozen, --no-hashes, --no-editable, --no-sources, --verbose, --no-group, dev, --directory, image_processing, -o, requirements.txt] - - # - repo: local - # hooks: - # - id: compile-image-processing-requirements - # name: compile-image-processing-requirements - # language: system - # entry: bash -c 'cd image_processing && exec uv export --frozen --no-hashes --no-editable --no-sources --verbose --no-group dev > src/image_processing/requirements.txt && cat src/image_processing/requirements.txt' - # pass_filenames: false + args: [--frozen, --no-hashes, --no-editable, --no-sources, --verbose, --no-group, dev, --directory, image_processing, -o, src/image_processing/requirements.txt] diff --git a/image_processing/src/image_processing/requirements.txt b/image_processing/src/image_processing/requirements.txt deleted file mode 100644 index e69de29b..00000000 From f317f08a2130980663967ec14d661bef35b86d4e Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 20:38:07 +0000 Subject: [PATCH 53/64] Update --- .vscode/settings.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index 3156ab10..aad287c3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,7 @@ "azureFunctions.projectLanguage": "Python", "azureFunctions.projectLanguageModel": 2, "azureFunctions.projectRuntime": "~4", + "azureFunctions.pythonVenv": ".venv", "azureFunctions.scmDoBuildDuringDeployment": true, "debug.internalConsoleOptions": "neverOpen" } From 5f8bec3a745b4e1b26a7accf86a6585c23a344a0 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 20:38:50 +0000 Subject: [PATCH 54/64] Update --- image_processing/{ => src/image_processing}/requirements.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename image_processing/{ => src/image_processing}/requirements.txt (100%) diff --git a/image_processing/requirements.txt b/image_processing/src/image_processing/requirements.txt similarity index 100% rename from image_processing/requirements.txt rename to image_processing/src/image_processing/requirements.txt From 7f0a7fd628842c5865118aad6afc8bfef32b251c Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 20:41:25 +0000 Subject: [PATCH 55/64] Change diff --- image_processing/src/image_processing/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/image_processing/src/image_processing/requirements.txt b/image_processing/src/image_processing/requirements.txt index ea5185a3..6c2688c4 100644 --- a/image_processing/src/image_processing/requirements.txt +++ b/image_processing/src/image_processing/requirements.txt @@ -1,5 +1,5 @@ # This file was autogenerated by uv via the following command: -# uv export --frozen --no-hashes --no-editable --no-sources --no-group dev --directory image_processing -o requirements.txt +# uv export --frozen --no-hashes --no-editable --no-sources --no-group dev --directory image_processing -o src/image_processing/requirements.txt aiohappyeyeballs==2.4.4 aiohttp==3.11.11 aiosignal==1.3.2 From dd6a7ba522bc2dea6d1594f2b49923dad054305e Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 20:44:45 +0000 Subject: [PATCH 56/64] Update --- .vscode/settings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index aad287c3..8e016e55 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,8 +1,9 @@ { - "azureFunctions.deploySubpath": "/image_processing/src/image_processing", + "azureFunctions.deploySubpath": "image_processing/src/image_processing", "azureFunctions.projectLanguage": "Python", "azureFunctions.projectLanguageModel": 2, "azureFunctions.projectRuntime": "~4", + "azureFunctions.projectSubpath": "image_processing/src/image_processing", "azureFunctions.pythonVenv": ".venv", "azureFunctions.scmDoBuildDuringDeployment": true, "debug.internalConsoleOptions": "neverOpen" From f3437462f39999e1327a2187cb86e7bd1639d1e0 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 20:46:21 +0000 Subject: [PATCH 57/64] Update --- .funcignore | 1 + image_processing/src/image_processing/.funcignore | 1 + 2 files changed, 2 insertions(+) diff --git a/.funcignore b/.funcignore index 6fd5d88e..ed87b86e 100644 --- a/.funcignore +++ b/.funcignore @@ -13,3 +13,4 @@ deploy_ai_search_indexes/* text_2_sql/* documentation/* images/ +__pycache__ diff --git a/image_processing/src/image_processing/.funcignore b/image_processing/src/image_processing/.funcignore index f1110d33..89e3f65e 100644 --- a/image_processing/src/image_processing/.funcignore +++ b/image_processing/src/image_processing/.funcignore @@ -6,3 +6,4 @@ __queuestorage__ local.settings.json test .venv +__pycache__ From 19ccc7425b953a134bdce8849e42345a54cdb707 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 21:14:05 +0000 Subject: [PATCH 58/64] trey --- .vscode/settings.json | 1 - image_processing/src/image_processing/__init__.py | 0 image_processing/src/image_processing/local.settings.json | 1 + 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 image_processing/src/image_processing/__init__.py diff --git a/.vscode/settings.json b/.vscode/settings.json index 8e016e55..6e020f80 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,7 +3,6 @@ "azureFunctions.projectLanguage": "Python", "azureFunctions.projectLanguageModel": 2, "azureFunctions.projectRuntime": "~4", - "azureFunctions.projectSubpath": "image_processing/src/image_processing", "azureFunctions.pythonVenv": ".venv", "azureFunctions.scmDoBuildDuringDeployment": true, "debug.internalConsoleOptions": "neverOpen" diff --git a/image_processing/src/image_processing/__init__.py b/image_processing/src/image_processing/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/image_processing/src/image_processing/local.settings.json b/image_processing/src/image_processing/local.settings.json index 08ab8000..e209c0c0 100644 --- a/image_processing/src/image_processing/local.settings.json +++ b/image_processing/src/image_processing/local.settings.json @@ -2,6 +2,7 @@ "IsEncrypted": false, "Values": { "AIService__DocumentIntelligence__Endpoint": "", + "AzureWebJobsFeatureFlags": "EnableWorkerIndexing", "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "python", "OpenAI__ApiKey": "", From f1c6a4c702b82f0d2e0746f2ed1776e305262e35 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 22:06:13 +0000 Subject: [PATCH 59/64] Change imports --- deploy_ai_search_indexes/src/deploy_ai_search_indexes/deploy.py | 2 +- image_processing/src/image_processing/function_app.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/deploy.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/deploy.py index 492bbed1..2506f0ca 100644 --- a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/deploy.py +++ b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/deploy.py @@ -16,7 +16,7 @@ def deploy_config(arguments: argparse.Namespace): Args: arguments (argparse.Namespace): The arguments passed to the script""" - suffix = None if args.suffix == "None" else args.suffix + suffix = None if arguments.suffix == "None" else arguments.suffix if arguments.index_type == "image_processing": index_config = ImageProcessingAISearch( suffix=suffix, diff --git a/image_processing/src/image_processing/function_app.py b/image_processing/src/image_processing/function_app.py index 2960116e..bb0f9bee 100644 --- a/image_processing/src/image_processing/function_app.py +++ b/image_processing/src/image_processing/function_app.py @@ -8,7 +8,7 @@ from figure_analysis import FigureAnalysis from layout_and_figure_merger import LayoutAndFigureMerger from layout_analysis import process_layout_analysis -from image_processing.mark_up_cleaner import MarkUpCleaner +from mark_up_cleaner import MarkUpCleaner from semantic_text_chunker import process_semantic_text_chunker, SemanticTextChunker logging.basicConfig(level=logging.DEBUG) From afa4f7d7a80ffcd2ff30a20a1d5fb520a9a211cd Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Wed, 22 Jan 2025 22:11:31 +0000 Subject: [PATCH 60/64] Update --- .../src/image_processing/__init__.py | 0 .../src/image_processing/function_app.py | 26 ++++++++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) delete mode 100644 image_processing/src/image_processing/__init__.py diff --git a/image_processing/src/image_processing/__init__.py b/image_processing/src/image_processing/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/image_processing/src/image_processing/function_app.py b/image_processing/src/image_processing/function_app.py index bb0f9bee..22bc39a8 100644 --- a/image_processing/src/image_processing/function_app.py +++ b/image_processing/src/image_processing/function_app.py @@ -54,7 +54,7 @@ async def layout_analysis(req: func.HttpRequest) -> func.HttpResponse: @app.route(route="figure_analysis", methods=[func.HttpMethod.POST]) -async def main(req: func.HttpRequest) -> func.HttpResponse: +async def figure_analysis(req: func.HttpRequest) -> func.HttpResponse: try: req_body = req.get_json() values = req_body.get("values") @@ -67,10 +67,12 @@ async def main(req: func.HttpRequest) -> func.HttpResponse: record_tasks = [] - figure_analysis = FigureAnalysis() + figure_analysis_processor = FigureAnalysis() for value in values: - record_tasks.append(asyncio.create_task(figure_analysis.analyse(value))) + record_tasks.append( + asyncio.create_task(figure_analysis_processor.analyse(value)) + ) results = await asyncio.gather(*record_tasks) logging.info("Results: %s", results) @@ -96,11 +98,11 @@ async def layout_and_figure_merger(req: func.HttpRequest) -> func.HttpResponse: record_tasks = [] - layout_and_figure_merger = LayoutAndFigureMerger() + layout_and_figure_merger_processor = LayoutAndFigureMerger() for value in values: record_tasks.append( - asyncio.create_task(layout_and_figure_merger.merge(value)) + asyncio.create_task(layout_and_figure_merger_processor.merge(value)) ) results = await asyncio.gather(*record_tasks) @@ -136,10 +138,12 @@ async def mark_up_cleaner(req: func.HttpRequest) -> func.HttpResponse: record_tasks = [] - mark_up_cleaner = MarkUpCleaner() + mark_up_cleaner_processor = MarkUpCleaner() for value in values: - record_tasks.append(asyncio.create_task(mark_up_cleaner.clean(value))) + record_tasks.append( + asyncio.create_task(mark_up_cleaner_processor.clean(value)) + ) results = await asyncio.gather(*record_tasks) logging.debug("Results: %s", results) @@ -185,7 +189,7 @@ async def semantic_text_chunker(req: func.HttpRequest) -> func.HttpResponse: record_tasks = [] - semantic_text_chunker = SemanticTextChunker( + semantic_text_chunker_processor = SemanticTextChunker( num_surrounding_sentences=num_surrounding_sentences, similarity_threshold=similarity_threshold, max_chunk_tokens=max_chunk_tokens, @@ -195,7 +199,9 @@ async def semantic_text_chunker(req: func.HttpRequest) -> func.HttpResponse: for value in values: record_tasks.append( asyncio.create_task( - process_semantic_text_chunker(value, semantic_text_chunker) + process_semantic_text_chunker( + value, semantic_text_chunker_processor + ) ) ) @@ -204,5 +210,5 @@ async def semantic_text_chunker(req: func.HttpRequest) -> func.HttpResponse: cleaned_tasks = {"values": results} return func.HttpResponse( - json.dump(cleaned_tasks), status_code=200, mimetype="application/json" + json.dumps(cleaned_tasks), status_code=200, mimetype="application/json" ) From ecece2352075b74460c19657228055ce091984b6 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Thu, 23 Jan 2025 10:45:37 +0000 Subject: [PATCH 61/64] Update code --- image_processing/GETTING_STARTED.md | 1 + image_processing/src/image_processing/layout_analysis.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/image_processing/GETTING_STARTED.md b/image_processing/GETTING_STARTED.md index 3b99567c..b5e4f31c 100644 --- a/image_processing/GETTING_STARTED.md +++ b/image_processing/GETTING_STARTED.md @@ -7,6 +7,7 @@ To get started, perform the following steps: - Cognitive Services Data Contributor (Preview) on the Document Intelligence Instance - Cognitive Services OpenAI User on the Azure OpenAI Instance - Storage Blob Data Contributor on the Storage Account Instance + - Make sure the Storage Account has a container `{NAME}-figures` for storing extracted figures. 2. Clone this repository and deploy the AI Search rag documents indexes from `deploy_ai_search_indexes`. 3. Run `uv sync` within the image_processing directory to install dependencies (or used the synced `requirements.txt`) 4. Use the `.env.example` to add the required environmental variables to your function app. Not all values are required dependent on whether you are using System / User Assigned Identities or a Key based authentication. Use this template to update the environment variables in the function app. diff --git a/image_processing/src/image_processing/layout_analysis.py b/image_processing/src/image_processing/layout_analysis.py index fc280a98..081b76fa 100644 --- a/image_processing/src/image_processing/layout_analysis.py +++ b/image_processing/src/image_processing/layout_analysis.py @@ -168,7 +168,7 @@ def extract_file_info(self): self.container = source_parts[3] - self.images_container = f"{self.container}-images" + self.images_container = f"{self.container}-figures" self.file_extension = self.blob.split(".")[-1] From a5a8722487aa6ad3c035a83ff49f5fd0fffdd9f4 Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Thu, 23 Jan 2025 11:43:12 +0000 Subject: [PATCH 62/64] Update code and flows --- .../src/deploy_ai_search_indexes/ai_search.py | 2 +- .../image_processing.py | 4 ++-- .../images/Page Wise Chunking.png | Bin 0 -> 186495 bytes .../src/image_processing/figure_analysis.py | 18 +++++++++++++--- .../src/image_processing/function_app.py | 2 +- .../src/image_processing/layout_holders.py | 20 ++++++++++-------- .../src/image_processing/mark_up_cleaner.py | 10 ++++----- 7 files changed, 35 insertions(+), 21 deletions(-) create mode 100644 image_processing/images/Page Wise Chunking.png diff --git a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/ai_search.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/ai_search.py index 8ad90b68..15291431 100644 --- a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/ai_search.py +++ b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/ai_search.py @@ -425,7 +425,7 @@ def get_figure_analysis_skill(self, chunk_by_page=False) -> WebApiSkill: ] if chunk_by_page: - figure_context = "/document/page_wise_layout/*" + figure_context = "/document/page_wise_layout/*/figures/*" inputs = [ InputFieldMappingEntry( name="figure", source="/document/page_wise_layout/*/figures/*" diff --git a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py index dcc3e2ba..ba8638f6 100644 --- a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py +++ b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py @@ -250,11 +250,11 @@ def get_index_projections(self) -> SearchIndexerIndexProjection: name="DateLastModified", source="/document/DateLastModified" ), InputFieldMappingEntry( - name="PageNumber", source="/document/page_wise_layout/*/#" + name="PageNumber", source="/document/page_wise_layout/*/page_number" ), ] else: - source_context = "/document/chunks/*" + source_context = "/document/chunk_mark_ups/*" mappings = [ InputFieldMappingEntry( name="Chunk", source="/document/chunk_mark_ups/*/chunk_mark_up" diff --git a/image_processing/images/Page Wise Chunking.png b/image_processing/images/Page Wise Chunking.png new file mode 100644 index 0000000000000000000000000000000000000000..45e3a2ebcf17b2bcae1ec6be456424d90a35c480 GIT binary patch literal 186495 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

_H7C0r`Z24kM|y{oBwoM?UM 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

A;$Y^^J^ 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 dict: - record (dict): The record containing the image, its caption, and the generated description. """ - logging.info(f"Record: {record}") - figure = FigureHolder(**record["data"]["figure"]) - try: + logging.info(f"Record: {record}") + figure = FigureHolder(**record["data"]["figure"]) updated_data = await self.understand_image_with_gptv(figure) logging.info(f"Updated Figure Data: {updated_data}") except RetryError as e: @@ -230,6 +229,19 @@ async def analyse(self, record: dict) -> dict: ], "warnings": None, } + except Exception as e: + logging.error(f"Failed to analyse image. Error: {e}") + logging.error(f"Failed input: {record}") + return { + "recordId": record["recordId"], + "data": None, + "errors": [ + { + "message": "Failed to analyse image. Check the logs for more details.", + } + ], + "warnings": None, + } else: return { "recordId": record["recordId"], diff --git a/image_processing/src/image_processing/function_app.py b/image_processing/src/image_processing/function_app.py index 22bc39a8..f0cfeadd 100644 --- a/image_processing/src/image_processing/function_app.py +++ b/image_processing/src/image_processing/function_app.py @@ -22,7 +22,7 @@ async def layout_analysis(req: func.HttpRequest) -> func.HttpResponse: values = req_body.get("values") adi_config = req.headers - page_wise = adi_config.get("page_wise", "False").lower() == "true" + page_wise = adi_config.get("chunk_by_page", "False").lower() == "true" extract_figures = adi_config.get("extract_figures", "True").lower() == "true" logging.info(f"Chunk by Page: {page_wise}") except ValueError: diff --git a/image_processing/src/image_processing/layout_holders.py b/image_processing/src/image_processing/layout_holders.py index 6b8e5b7f..08d1ab37 100644 --- a/image_processing/src/image_processing/layout_holders.py +++ b/image_processing/src/image_processing/layout_holders.py @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, ConfigDict from typing import Optional @@ -9,16 +9,18 @@ class FigureHolder(BaseModel): """A class to hold the figure extracted from the document.""" - figure_id: str - container: str = Field(exclude=True) - blob: str = Field(exclude=True) - caption: Optional[str] = Field(default=None) + figure_id: str = Field(..., alias="FigureId") + container: Optional[str] = Field(exclude=True, default=None) + blob: Optional[str] = Field(exclude=True, default=None) + caption: Optional[str] = Field(default=None, alias="Caption") offset: int length: int - page_number: Optional[int] = Field(default=None) - uri: str - description: Optional[str] = Field(default="") - data: Optional[str] = Field(default=None) + page_number: Optional[int] = Field(default=None, alias="PageNumber") + uri: str = Field(..., alias="Uri") + description: Optional[str] = Field(default="", alias="Description") + data: Optional[str] = Field(default=None, alias="Data") + + model_config = ConfigDict(populate_by_name=True) @property def markdown(self) -> str: diff --git a/image_processing/src/image_processing/mark_up_cleaner.py b/image_processing/src/image_processing/mark_up_cleaner.py index 4cb75596..30a58133 100644 --- a/image_processing/src/image_processing/mark_up_cleaner.py +++ b/image_processing/src/image_processing/mark_up_cleaner.py @@ -94,18 +94,18 @@ def clean_text_and_extract_metadata( logging.error("Input text is empty") raise ValueError("Input text is empty") - return_record["marked_up_chunk"] = text + return_record["chunk_mark_up"] = text figure_ids = self.get_figure_ids(text) - return_record["sections"] = self.get_sections(text) - return_record["figures"] = [ + return_record["chunk_sections"] = self.get_sections(text) + return_record["chunk_figures"] = [ figure.model_dump(by_alias=True) for figure in figures if figure.figure_id in figure_ids ] - logging.info(f"Sections: {return_record['sections']}") + logging.info(f"Sections: {return_record['chunk_sections']}") # Define specific patterns for each tag tag_patterns = { @@ -128,7 +128,7 @@ def clean_text_and_extract_metadata( logging.error("Cleaned text is empty") raise ValueError("Cleaned text is empty") else: - return_record["cleaned_chunk"] = cleaned_text + return_record["chunk_cleaned"] = cleaned_text except Exception as e: logging.error(f"An error occurred in clean_text_and_extract_metadata: {e}") return "" From 9858d37201ec722d87e9a55155c7a3ffdf577b6d Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Thu, 23 Jan 2025 12:01:25 +0000 Subject: [PATCH 63/64] Update mapping --- .../src/deploy_ai_search_indexes/ai_search.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/ai_search.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/ai_search.py index 15291431..63debf2f 100644 --- a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/ai_search.py +++ b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/ai_search.py @@ -300,7 +300,9 @@ def get_semantic_chunker_skill( degree_of_parallelism = 16 semantic_text_chunker_skill_inputs = [ - InputFieldMappingEntry(name="content", source="/document/merged_content") + InputFieldMappingEntry( + name="content", source="/document/layout/merged_content" + ) ] semantic_text_chunker_skill_outputs = [ From 9209d5efd627dd199cacd0d76e9667d6d405a57b Mon Sep 17 00:00:00 2001 From: Ben Constable Date: Thu, 23 Jan 2025 12:21:43 +0000 Subject: [PATCH 64/64] final updates --- .../image_processing.py | 5 ++--- image_processing/README.md | 15 ++++++++++++++- image_processing/images/Semantic Chunking.png | Bin 0 -> 159641 bytes .../src/image_processing/function_app.py | 14 ++++++++------ 4 files changed, 24 insertions(+), 10 deletions(-) create mode 100644 image_processing/images/Semantic Chunking.png diff --git a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py index ba8638f6..d5645b81 100644 --- a/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py +++ b/deploy_ai_search_indexes/src/deploy_ai_search_indexes/image_processing.py @@ -187,8 +187,6 @@ def get_skills(self) -> list: self.enable_page_by_chunking ) - text_split_skill = self.get_semantic_chunker_skill(self.enable_page_by_chunking) - mark_up_cleaner_skill = self.get_mark_up_cleaner_skill( self.enable_page_by_chunking ) @@ -212,11 +210,12 @@ def get_skills(self) -> list: embedding_skill, ] else: + semantic_chunker_skill = self.get_semantic_chunker_skill() skills = [ layout_skill, figure_skill, merger_skill, - text_split_skill, + semantic_chunker_skill, mark_up_cleaner_skill, embedding_skill, ] diff --git a/image_processing/README.md b/image_processing/README.md index 10664828..50100780 100644 --- a/image_processing/README.md +++ b/image_processing/README.md @@ -25,6 +25,7 @@ Instead of using OCR to extract the contents of the document, ADIv4 is used to a Once the Markdown is obtained, several steps are carried out: 1. **Extraction of figures / charts**. The figures identified are extracted from the original document and passed to a multi-modal model (gpt-4o-mini in this case) for analysis. We obtain a description and summary of the chart / image to infer the meaning of the figure. This allows us to index and perform RAG analysis the information that is visually obtainable from a chart, without it being explicitly mentioned in the text surrounding. The information is added back into the original chart. + - **The prompt aims to generate a description and summary of the chart so it can be retrieved later during search. It does not aim to summarise every part of the figure. At runtime, retrieve the figures for the given chunk from the index and pass them to the visual model for context.** 2. **Chunking**. The obtained content is chunked accordingly depending on the chunking strategy. This function app supports two chunking methods, **page wise** and **semantic chunking**. The page wise chunking is performed natively by Azure Document Intelligence. For a Semantic Chunking, we include a customer chunker that splits the text with the following strategy: @@ -38,9 +39,21 @@ Once the Markdown is obtained, several steps are carried out: 3. **Cleaning of Markdown**. The final markdown content is cleaned of any characters or unsupported Markdown elements that we do not want in the chunk e.g. non-relevant figures. +### AI Search Enrichment Steps + > [!NOTE] > -> For scalability, the above steps are performed across 5 differnet function app endpoints that are orchestrated by AI search. +> For scalability, the above steps are performed across 5 different function app endpoints that are orchestrated by AI search. + +### Page Wise Chunking + +![AI Search Enrichment Steps & Flow for Page Wise Chunking](./images/Page%20Wise%20Chunking.png "Page Wise Chunking Enrichment Steps") + +### Semantic Chunking + +![AI Search Enrichment Steps & Flow for Semantic Chunking](./images/Semantic%20Chunking.png "Semantic Chunking Enrichment Steps") + +Here, the output from the layout is considered a single block of text and the customer semantic chunker is used before vectorisation and projections. The custom chunker aims to retain figures and tables within the same chunks, and chunks when the similarity between sentences is lower than the threshold. ## Sample Output diff --git a/image_processing/images/Semantic Chunking.png b/image_processing/images/Semantic Chunking.png new file mode 100644 index 0000000000000000000000000000000000000000..0910a9bfdd396543576c5a079d5a11b6ee0193a9 GIT binary patch literal 159641 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 func.HttpResponse: semantic_text_chunker_config = req.headers - num_surrounding_sentences = semantic_text_chunker_config.get( - "num_surrounding_sentences", 1 + num_surrounding_sentences = int( + semantic_text_chunker_config.get("num_surrounding_sentences", 1) ) - similarity_threshold = semantic_text_chunker_config.get( - "similarity_threshold", 0.8 + similarity_threshold = float( + semantic_text_chunker_config.get("similarity_threshold", 0.8) ) - max_chunk_tokens = semantic_text_chunker_config.get("max_chunk_tokens", 500) - min_chunk_tokens = semantic_text_chunker_config.get("min_chunk_tokens", 50) + max_chunk_tokens = int( + semantic_text_chunker_config.get("max_chunk_tokens", 500) + ) + min_chunk_tokens = int(semantic_text_chunker_config.get("min_chunk_tokens", 50)) except ValueError: return func.HttpResponse(