From 8fb594fd2a5cf4ce4315e91640b0807c95812392 Mon Sep 17 00:00:00 2001 From: Erick Friis Date: Wed, 28 Aug 2024 14:24:07 -0700 Subject: [PATCH] ai21: migrate to external repo (#25827) --- libs/partners/ai21/LICENSE | 21 - libs/partners/ai21/Makefile | 55 - libs/partners/ai21/README.md | 218 +-- libs/partners/ai21/langchain_ai21/__init__.py | 13 - .../partners/ai21/langchain_ai21/ai21_base.py | 64 - .../ai21/langchain_ai21/chat/__init__.py | 0 .../ai21/langchain_ai21/chat/chat_adapter.py | 324 ---- .../ai21/langchain_ai21/chat/chat_factory.py | 23 - .../ai21/langchain_ai21/chat_models.py | 271 ---- .../ai21/langchain_ai21/contextual_answers.py | 112 -- .../ai21/langchain_ai21/embeddings.py | 126 -- libs/partners/ai21/langchain_ai21/llms.py | 188 --- libs/partners/ai21/langchain_ai21/py.typed | 0 .../langchain_ai21/semantic_text_splitter.py | 158 -- libs/partners/ai21/poetry.lock | 1322 ----------------- libs/partners/ai21/pyproject.toml | 90 -- libs/partners/ai21/scripts/check_imports.py | 17 - libs/partners/ai21/scripts/check_pydantic.sh | 27 - libs/partners/ai21/scripts/lint_imports.sh | 17 - libs/partners/ai21/tests/__init__.py | 0 .../ai21/tests/integration_tests/__init__.py | 0 .../integration_tests/test_chat_models.py | 188 --- .../tests/integration_tests/test_compile.py | 7 - .../test_contextual_answers.py | 61 - .../integration_tests/test_embeddings.py | 37 - .../ai21/tests/integration_tests/test_llms.py | 104 -- .../test_semantic_text_splitter.py | 130 -- .../tests/integration_tests/test_standard.py | 89 -- .../ai21/tests/unit_tests/__init__.py | 0 .../ai21/tests/unit_tests/chat/__init__.py | 0 .../ai21/tests/unit_tests/chat/conftest.py | 9 - .../unit_tests/chat/test_chat_adapter.py | 248 ---- .../chat/test_chat_adapter_factory.py | 34 - .../ai21/tests/unit_tests/conftest.py | 207 --- .../ai21/tests/unit_tests/test_chat_models.py | 174 --- .../unit_tests/test_contextual_answers.py | 109 -- .../ai21/tests/unit_tests/test_embeddings.py | 102 -- .../ai21/tests/unit_tests/test_imports.py | 13 - .../ai21/tests/unit_tests/test_llms.py | 146 -- .../unit_tests/test_semantic_text_splitter.py | 129 -- .../ai21/tests/unit_tests/test_standard.py | 36 - .../ai21/tests/unit_tests/test_utils.py | 29 - libs/partners/upstage/.gitignore | 1 - libs/partners/upstage/README.md | 3 - 44 files changed, 2 insertions(+), 4900 deletions(-) delete mode 100644 libs/partners/ai21/LICENSE delete mode 100644 libs/partners/ai21/Makefile delete mode 100644 libs/partners/ai21/langchain_ai21/__init__.py delete mode 100644 libs/partners/ai21/langchain_ai21/ai21_base.py delete mode 100644 libs/partners/ai21/langchain_ai21/chat/__init__.py delete mode 100644 libs/partners/ai21/langchain_ai21/chat/chat_adapter.py delete mode 100644 libs/partners/ai21/langchain_ai21/chat/chat_factory.py delete mode 100644 libs/partners/ai21/langchain_ai21/chat_models.py delete mode 100644 libs/partners/ai21/langchain_ai21/contextual_answers.py delete mode 100644 libs/partners/ai21/langchain_ai21/embeddings.py delete mode 100644 libs/partners/ai21/langchain_ai21/llms.py delete mode 100644 libs/partners/ai21/langchain_ai21/py.typed delete mode 100644 libs/partners/ai21/langchain_ai21/semantic_text_splitter.py delete mode 100644 libs/partners/ai21/poetry.lock delete mode 100644 libs/partners/ai21/pyproject.toml delete mode 100644 libs/partners/ai21/scripts/check_imports.py delete mode 100755 libs/partners/ai21/scripts/check_pydantic.sh delete mode 100755 libs/partners/ai21/scripts/lint_imports.sh delete mode 100644 libs/partners/ai21/tests/__init__.py delete mode 100644 libs/partners/ai21/tests/integration_tests/__init__.py delete mode 100644 libs/partners/ai21/tests/integration_tests/test_chat_models.py delete mode 100644 libs/partners/ai21/tests/integration_tests/test_compile.py delete mode 100644 libs/partners/ai21/tests/integration_tests/test_contextual_answers.py delete mode 100644 libs/partners/ai21/tests/integration_tests/test_embeddings.py delete mode 100644 libs/partners/ai21/tests/integration_tests/test_llms.py delete mode 100644 libs/partners/ai21/tests/integration_tests/test_semantic_text_splitter.py delete mode 100644 libs/partners/ai21/tests/integration_tests/test_standard.py delete mode 100644 libs/partners/ai21/tests/unit_tests/__init__.py delete mode 100644 libs/partners/ai21/tests/unit_tests/chat/__init__.py delete mode 100644 libs/partners/ai21/tests/unit_tests/chat/conftest.py delete mode 100644 libs/partners/ai21/tests/unit_tests/chat/test_chat_adapter.py delete mode 100644 libs/partners/ai21/tests/unit_tests/chat/test_chat_adapter_factory.py delete mode 100644 libs/partners/ai21/tests/unit_tests/conftest.py delete mode 100644 libs/partners/ai21/tests/unit_tests/test_chat_models.py delete mode 100644 libs/partners/ai21/tests/unit_tests/test_contextual_answers.py delete mode 100644 libs/partners/ai21/tests/unit_tests/test_embeddings.py delete mode 100644 libs/partners/ai21/tests/unit_tests/test_imports.py delete mode 100644 libs/partners/ai21/tests/unit_tests/test_llms.py delete mode 100644 libs/partners/ai21/tests/unit_tests/test_semantic_text_splitter.py delete mode 100644 libs/partners/ai21/tests/unit_tests/test_standard.py delete mode 100644 libs/partners/ai21/tests/unit_tests/test_utils.py delete mode 100644 libs/partners/upstage/.gitignore delete mode 100644 libs/partners/upstage/README.md diff --git a/libs/partners/ai21/LICENSE b/libs/partners/ai21/LICENSE deleted file mode 100644 index 426b6509034..00000000000 --- a/libs/partners/ai21/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 LangChain, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/libs/partners/ai21/Makefile b/libs/partners/ai21/Makefile deleted file mode 100644 index ed548aa4100..00000000000 --- a/libs/partners/ai21/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -.PHONY: all format lint test tests integration_tests docker_tests help extended_tests - -# Default target executed when no arguments are given to make. -all: help - -# Define a variable for the test file path. -TEST_FILE ?= tests/unit_tests/ -integration_test integration_tests: TEST_FILE = tests/integration_tests/ -test tests integration_test integration_tests: - poetry run pytest $(TEST_FILE) - - -###################### -# LINTING AND FORMATTING -###################### - -# Define a variable for Python and notebook files. -PYTHON_FILES=. -MYPY_CACHE=.mypy_cache -lint format: PYTHON_FILES=. -lint_diff format_diff: PYTHON_FILES=$(shell git diff --relative=libs/partners/ai21 --name-only --diff-filter=d master | grep -E '\.py$$|\.ipynb$$') -lint_package: PYTHON_FILES=langchain_ai21 -lint_tests: PYTHON_FILES=tests -lint_tests: MYPY_CACHE=.mypy_cache_test - -lint lint_diff lint_package lint_tests: - [ "$(PYTHON_FILES)" = "" ] || poetry run ruff check $(PYTHON_FILES) - [ "$(PYTHON_FILES)" = "" ] || poetry run ruff format $(PYTHON_FILES) --diff - [ "$(PYTHON_FILES)" = "" ] || mkdir -p $(MYPY_CACHE) && poetry run mypy $(PYTHON_FILES) --cache-dir $(MYPY_CACHE) - -format format_diff: - [ "$(PYTHON_FILES)" = "" ] || poetry run ruff format $(PYTHON_FILES) - [ "$(PYTHON_FILES)" = "" ] || poetry run ruff check --select I --fix $(PYTHON_FILES) - -spell_check: - poetry run codespell --toml pyproject.toml - -spell_fix: - poetry run codespell --toml pyproject.toml -w - -check_imports: $(shell find langchain_ai21 -name '*.py') - poetry run python ./scripts/check_imports.py $^ - -###################### -# HELP -###################### - -help: - @echo '----' - @echo 'check_imports - check imports' - @echo 'format - run code formatters' - @echo 'lint - run linters' - @echo 'test - run unit tests' - @echo 'tests - run unit tests' - @echo 'test TEST_FILE= - run all tests in file' diff --git a/libs/partners/ai21/README.md b/libs/partners/ai21/README.md index 7cb09fd9334..a4a3cc65aec 100644 --- a/libs/partners/ai21/README.md +++ b/libs/partners/ai21/README.md @@ -1,217 +1,3 @@ -# langchain-ai21 +This package has moved! -This package contains the LangChain integrations for [AI21](https://docs.ai21.com/) models and tools. - -## Installation and Setup - -- Install the AI21 partner package -```bash -pip install langchain-ai21 -``` -- Get an AI21 api key and set it as an environment variable (`AI21_API_KEY`) - - -## Chat Models - -This package contains the `ChatAI21` class, which is the recommended way to interface with AI21 chat models, including Jamba-Instruct -and any Jurassic chat models. - -To use, install the requirements and configure your environment. - -```bash -export AI21_API_KEY=your-api-key -``` - -Then initialize - -```python -from langchain_core.messages import HumanMessage -from langchain_ai21.chat_models import ChatAI21 - -chat = ChatAI21(model="jamba-instruct") -messages = [HumanMessage(content="Hello from AI21")] -chat.invoke(messages) -``` - -For a list of the supported models, see [this page](https://docs.ai21.com/reference/python-sdk#chat) - -### Streaming in Chat -Streaming is supported by the latest models. To use streaming, set the `streaming` parameter to `True` when initializing the model. - -```python -from langchain_core.messages import HumanMessage -from langchain_ai21.chat_models import ChatAI21 - -chat = ChatAI21(model="jamba-instruct", streaming=True) -messages = [HumanMessage(content="Hello from AI21")] - -response = chat.invoke(messages) -``` - -or use the `stream` method directly - -```python -from langchain_core.messages import HumanMessage -from langchain_ai21.chat_models import ChatAI21 - -chat = ChatAI21(model="jamba-instruct") -messages = [HumanMessage(content="Hello from AI21")] - -for chunk in chat.stream(messages): - print(chunk) -``` - - -## LLMs -You can use AI21's Jurassic generative AI models as LangChain LLMs. -To use the newer Jamba model, use the [ChatAI21 chat model](#chat-models), which -supports single-turn instruction/question answering capabilities. - -```python -from langchain_core.prompts import PromptTemplate -from langchain_ai21 import AI21LLM - -llm = AI21LLM(model="j2-ultra") - -template = """Question: {question} - -Answer: Let's think step by step.""" -prompt = PromptTemplate.from_template(template) - -chain = prompt | llm - -question = "Which scientist discovered relativity?" -print(chain.invoke({"question": question})) -``` - -## Embeddings - -You can use AI21's [embeddings model](https://docs.ai21.com/reference/embeddings-ref) as shown here: - -### Query - -```python -from langchain_ai21 import AI21Embeddings - -embeddings = AI21Embeddings() -embeddings.embed_query("Hello! This is some query") -``` - -### Document - -```python -from langchain_ai21 import AI21Embeddings - -embeddings = AI21Embeddings() -embeddings.embed_documents(["Hello! This is document 1", "And this is document 2!"]) -``` - -## Task-Specific Models - -### Contextual Answers - -You can use AI21's [contextual answers model](https://docs.ai21.com/reference/contextual-answers-ref) to parse -given text and answer a question based entirely on the provided information. - -This means that if the answer to your question is not in the document, -the model will indicate it (instead of providing a false answer) - -```python -from langchain_ai21 import AI21ContextualAnswers - -tsm = AI21ContextualAnswers() - -response = tsm.invoke(input={"context": "Lots of information here", "question": "Your question about the context"}) -``` -You can also use it with chains and output parsers and vector DBs: -```python -from langchain_ai21 import AI21ContextualAnswers -from langchain_core.output_parsers import StrOutputParser - -tsm = AI21ContextualAnswers() -chain = tsm | StrOutputParser() - -response = chain.invoke( - {"context": "Your context", "question": "Your question"}, -) -``` - -## Text Splitters - -### Semantic Text Splitter - -You can use AI21's semantic [text segmentation model](https://docs.ai21.com/reference/text-segmentation-ref) to split a text into segments by topic. -Text is split at each point where the topic changes. - -For a list for examples, see [this page](https://github.com/langchain-ai/langchain/blob/master/docs/docs/modules/data_connection/document_transformers/semantic_text_splitter.ipynb). - -```python -from langchain_ai21 import AI21SemanticTextSplitter - -splitter = AI21SemanticTextSplitter() -response = splitter.split_text("Your text") -``` - -## Tool calls - -### Function calling - -AI21 models incorporate the Function Calling feature to support custom user functions. The models generate structured -data that includes the function name and proposed arguments. This data empowers applications to call external APIs and -incorporate the resulting information into subsequent model prompts, enriching responses with real-time data and -context. Through function calling, users can access and utilize various services like transportation APIs and financial -data providers to obtain more accurate and relevant answers. Here is an example of how to use function calling -with AI21 models in LangChain: - -```python -import os -from getpass import getpass -from langchain_core.messages import HumanMessage, ToolMessage, SystemMessage -from langchain_core.tools import tool -from langchain_ai21.chat_models import ChatAI21 -from langchain_core.utils.function_calling import convert_to_openai_tool - -os.environ["AI21_API_KEY"] = getpass() - -@tool -def get_weather(location: str, date: str) -> str: - """“Provide the weather for the specified location on the given date.”""" - if location == "New York" and date == "2024-12-05": - return "25 celsius" - elif location == "New York" and date == "2024-12-06": - return "27 celsius" - elif location == "London" and date == "2024-12-05": - return "22 celsius" - return "32 celsius" - -llm = ChatAI21(model="jamba-1.5-mini") - -llm_with_tools = llm.bind_tools([convert_to_openai_tool(get_weather)]) - -chat_messages = [SystemMessage(content="You are a helpful assistant. You can use the provided tools " - "to assist with various tasks and provide accurate information")] - -human_messages = [ - HumanMessage(content="What is the forecast for the weather in New York on December 5, 2024?"), - HumanMessage(content="And what about the 2024-12-06?"), - HumanMessage(content="OK, thank you."), - HumanMessage(content="What is the expected weather in London on December 5, 2024?")] - - -for human_message in human_messages: - print(f"User: {human_message.content}") - chat_messages.append(human_message) - response = llm_with_tools.invoke(chat_messages) - chat_messages.append(response) - if response.tool_calls: - tool_call = response.tool_calls[0] - if tool_call["name"] == "get_weather": - weather = get_weather.invoke( - {"location": tool_call["args"]["location"], "date": tool_call["args"]["date"]}) - chat_messages.append(ToolMessage(content=weather, tool_call_id=tool_call["id"])) - llm_answer = llm_with_tools.invoke(chat_messages) - print(f"Assistant: {llm_answer.content}") - else: - print(f"Assistant: {response.content}") - -``` \ No newline at end of file +https://github.com/langchain-ai/langchain-ai21/tree/main/libs/ai21 \ No newline at end of file diff --git a/libs/partners/ai21/langchain_ai21/__init__.py b/libs/partners/ai21/langchain_ai21/__init__.py deleted file mode 100644 index fd766fb075c..00000000000 --- a/libs/partners/ai21/langchain_ai21/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -from langchain_ai21.chat_models import ChatAI21 -from langchain_ai21.contextual_answers import AI21ContextualAnswers -from langchain_ai21.embeddings import AI21Embeddings -from langchain_ai21.llms import AI21LLM -from langchain_ai21.semantic_text_splitter import AI21SemanticTextSplitter - -__all__ = [ - "AI21LLM", - "ChatAI21", - "AI21Embeddings", - "AI21ContextualAnswers", - "AI21SemanticTextSplitter", -] diff --git a/libs/partners/ai21/langchain_ai21/ai21_base.py b/libs/partners/ai21/langchain_ai21/ai21_base.py deleted file mode 100644 index c681b887217..00000000000 --- a/libs/partners/ai21/langchain_ai21/ai21_base.py +++ /dev/null @@ -1,64 +0,0 @@ -import os -from typing import Any, Dict, Optional - -from ai21 import AI21Client -from langchain_core.pydantic_v1 import BaseModel, Field, SecretStr, root_validator -from langchain_core.utils import convert_to_secret_str - -_DEFAULT_TIMEOUT_SEC = 300 - - -class AI21Base(BaseModel): - """Base class for AI21 models.""" - - class Config: - arbitrary_types_allowed = True - - client: Any = Field(default=None, exclude=True) #: :meta private: - api_key: Optional[SecretStr] = None - """API key for AI21 API.""" - api_host: Optional[str] = None - """Host URL""" - timeout_sec: Optional[float] = None - """Timeout in seconds. - - If not set, it will default to the value of the environment - variable `AI21_TIMEOUT_SEC` or 300 seconds. - """ - num_retries: Optional[int] = None - """Maximum number of retries for API requests before giving up.""" - - @root_validator(pre=True) - def validate_environment(cls, values: Dict) -> Dict: - api_key = convert_to_secret_str( - values.get("api_key") or os.getenv("AI21_API_KEY") or "" - ) - values["api_key"] = api_key - - api_host = ( - values.get("api_host") - or os.getenv("AI21_API_URL") - or "https://api.ai21.com" - ) - values["api_host"] = api_host - - timeout_sec = values.get("timeout_sec") or float( - os.getenv("AI21_TIMEOUT_SEC", _DEFAULT_TIMEOUT_SEC) - ) - values["timeout_sec"] = timeout_sec - return values - - @root_validator(pre=False, skip_on_failure=True) - def post_init(cls, values: Dict) -> Dict: - api_key = values["api_key"] - api_host = values["api_host"] - timeout_sec = values["timeout_sec"] - if values.get("client") is None: - values["client"] = AI21Client( - api_key=api_key.get_secret_value(), - api_host=api_host, - timeout_sec=None if timeout_sec is None else float(timeout_sec), - via="langchain", - ) - - return values diff --git a/libs/partners/ai21/langchain_ai21/chat/__init__.py b/libs/partners/ai21/langchain_ai21/chat/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libs/partners/ai21/langchain_ai21/chat/chat_adapter.py b/libs/partners/ai21/langchain_ai21/chat/chat_adapter.py deleted file mode 100644 index 793ae241674..00000000000 --- a/libs/partners/ai21/langchain_ai21/chat/chat_adapter.py +++ /dev/null @@ -1,324 +0,0 @@ -from __future__ import annotations - -from abc import ABC, abstractmethod -from typing import Any, Dict, Iterator, List, Literal, Optional, Union, cast, overload - -from ai21.models import ChatMessage as J2ChatMessage -from ai21.models import RoleType -from ai21.models.chat import ( - AssistantMessage as AI21AssistantMessage, -) -from ai21.models.chat import ChatCompletionChunk, ChatMessageParam -from ai21.models.chat import ChatMessage as AI21ChatMessage -from ai21.models.chat import SystemMessage as AI21SystemMessage -from ai21.models.chat import ToolCall as AI21ToolCall -from ai21.models.chat import ToolFunction as AI21ToolFunction -from ai21.models.chat import ToolMessage as AI21ToolMessage -from ai21.models.chat import UserMessage as AI21UserMessage -from ai21.stream.stream import Stream as AI21Stream -from langchain_core.messages import ( - AIMessage, - AIMessageChunk, - BaseMessage, - BaseMessageChunk, - HumanMessage, - SystemMessage, - ToolCall, - ToolMessage, -) -from langchain_core.messages.ai import UsageMetadata -from langchain_core.output_parsers.openai_tools import parse_tool_call -from langchain_core.outputs import ChatGenerationChunk - -_ChatMessageTypes = Union[AI21ChatMessage, J2ChatMessage] -_SYSTEM_ERR_MESSAGE = "System message must be at beginning of message list." -_ROLE_TYPE = Union[str, RoleType] - - -class ChatAdapter(ABC): - """Common interface for the different Chat models available in AI21. - - It converts LangChain messages to AI21 messages. - Calls the appropriate AI21 model API with the converted messages. - """ - - @abstractmethod - def convert_messages( - self, - messages: List[BaseMessage], - ) -> Dict[str, Any]: - pass - - def _convert_message_to_ai21_message( - self, - message: BaseMessage, - ) -> _ChatMessageTypes: - role = self._parse_role(message) - return self._chat_message(role=role, message=message) - - def _parse_role(self, message: BaseMessage) -> _ROLE_TYPE: - role = None - - if isinstance(message, SystemMessage): - return RoleType.SYSTEM - - if isinstance(message, HumanMessage): - return RoleType.USER - - if isinstance(message, AIMessage): - return RoleType.ASSISTANT - - if isinstance(message, ToolMessage): - return RoleType.TOOL - - if isinstance(self, J2ChatAdapter): - if not role: - raise ValueError( - f"Could not resolve role type from message {message}. " - f"Only support {HumanMessage.__name__} and {AIMessage.__name__}." - ) - - # if it gets here, we rely on the server to handle the role type - return message.type - - @abstractmethod - def _chat_message( - self, - role: _ROLE_TYPE, - message: BaseMessage, - ) -> _ChatMessageTypes: - pass - - @overload - def call( - self, - client: Any, - stream: Literal[True], - **params: Any, - ) -> Iterator[ChatGenerationChunk]: - pass - - @overload - def call( - self, - client: Any, - stream: Literal[False], - **params: Any, - ) -> List[BaseMessage]: - pass - - @abstractmethod - def call( - self, - client: Any, - stream: Literal[True] | Literal[False], - **params: Any, - ) -> List[BaseMessage] | Iterator[ChatGenerationChunk]: - pass - - def _get_system_message_from_message(self, message: BaseMessage) -> str: - if not isinstance(message.content, str): - raise ValueError( - f"System Message must be of type str. Got {type(message.content)}" - ) - - return message.content - - -class J2ChatAdapter(ChatAdapter): - """Adapter for J2Chat models.""" - - def convert_messages(self, messages: List[BaseMessage]) -> Dict[str, Any]: - system_message = "" - converted_messages = [] # type: ignore - - for i, message in enumerate(messages): - if message.type == "system": - if i != 0: - raise ValueError(_SYSTEM_ERR_MESSAGE) - else: - system_message = self._get_system_message_from_message(message) - else: - converted_message = self._convert_message_to_ai21_message(message) - converted_messages.append(converted_message) - - return {"system": system_message, "messages": converted_messages} - - def _chat_message( - self, - role: _ROLE_TYPE, - message: BaseMessage, - ) -> J2ChatMessage: - return J2ChatMessage(role=RoleType(role), text=cast(str, message.content)) - - @overload - def call( - self, - client: Any, - stream: Literal[True], - **params: Any, - ) -> Iterator[ChatGenerationChunk]: ... - - @overload - def call( - self, - client: Any, - stream: Literal[False], - **params: Any, - ) -> List[BaseMessage]: ... - - def call( - self, - client: Any, - stream: Literal[True] | Literal[False], - **params: Any, - ) -> List[BaseMessage] | Iterator[ChatGenerationChunk]: - if stream: - raise NotImplementedError("Streaming is not supported for Jurassic models.") - - response = client.chat.create(**params) - - return [AIMessage(output.text) for output in response.outputs] - - -class JambaChatCompletionsAdapter(ChatAdapter): - """Adapter for Jamba Chat Completions.""" - - def convert_messages(self, messages: List[BaseMessage]) -> Dict[str, Any]: - return { - "messages": [ - self._convert_message_to_ai21_message(message) for message in messages - ], - } - - def _convert_lc_tool_calls_to_ai21_tool_calls( - self, tool_calls: List[ToolCall] - ) -> Optional[List[AI21ToolCall]]: - """ - Convert Langchain ToolCalls to AI21 ToolCalls. - """ - ai21_tool_calls: List[AI21ToolCall] = [] - for lc_tool_call in tool_calls: - if "id" not in lc_tool_call or not lc_tool_call["id"]: - raise ValueError("Tool call ID is missing or empty.") - - ai21_tool_call = AI21ToolCall( - id=lc_tool_call["id"], - type="function", - function=AI21ToolFunction( - name=lc_tool_call["name"], - arguments=str(lc_tool_call["args"]), - ), - ) - ai21_tool_calls.append(ai21_tool_call) - - return ai21_tool_calls - - def _get_content_as_string(self, base_message: BaseMessage) -> str: - if isinstance(base_message.content, str): - return base_message.content - elif isinstance(base_message.content, list): - return "\n".join(str(item) for item in base_message.content) - else: - raise ValueError("Unsupported content type") - - def _chat_message( - self, - role: _ROLE_TYPE, - message: BaseMessage, - ) -> ChatMessageParam: - content = self._get_content_as_string(message) - - if isinstance(message, AIMessage): - return AI21AssistantMessage( - tool_calls=self._convert_lc_tool_calls_to_ai21_tool_calls( - message.tool_calls - ), - content=content or None, - ) - if isinstance(message, ToolMessage): - return AI21ToolMessage( - tool_call_id=message.tool_call_id, - content=content, - ) - if isinstance(message, HumanMessage): - return AI21UserMessage( - content=content, - ) - if isinstance(message, SystemMessage): - return AI21SystemMessage( - content=content, - ) - return AI21ChatMessage( - role=role.value if isinstance(role, RoleType) else role, - content=content, - ) - - @overload - def call( - self, - client: Any, - stream: Literal[True], - **params: Any, - ) -> Iterator[ChatGenerationChunk]: ... - - @overload - def call( - self, - client: Any, - stream: Literal[False], - **params: Any, - ) -> List[BaseMessage]: ... - - def call( - self, - client: Any, - stream: Literal[True] | Literal[False], - **params: Any, - ) -> List[BaseMessage] | Iterator[ChatGenerationChunk]: - response = client.chat.completions.create(stream=stream, **params) - - if stream: - return self._stream_response(response) - - ai_messages: List[BaseMessage] = [] - for message in response.choices: - if message.message.tool_calls: - tool_calls = [ - parse_tool_call(tool_call.model_dump(), return_id=True) - for tool_call in message.message.tool_calls - ] - ai_messages.append(AIMessage("", tool_calls=tool_calls)) - else: - ai_messages.append(AIMessage(message.message.content)) - - return ai_messages - - def _stream_response( - self, - response: AI21Stream[ChatCompletionChunk], - ) -> Iterator[ChatGenerationChunk]: - for chunk in response: - converted_message = self._convert_ai21_chunk_to_chunk(chunk) - yield ChatGenerationChunk(message=converted_message) - - def _convert_ai21_chunk_to_chunk( - self, - chunk: ChatCompletionChunk, - ) -> BaseMessageChunk: - usage = chunk.usage - content = chunk.choices[0].delta.content or "" - - if usage is None: - return AIMessageChunk( - content=content, - ) - - return AIMessageChunk( - content=content, - usage_metadata=UsageMetadata( - input_tokens=usage.prompt_tokens, - output_tokens=usage.completion_tokens, - total_tokens=usage.total_tokens, - ), - ) diff --git a/libs/partners/ai21/langchain_ai21/chat/chat_factory.py b/libs/partners/ai21/langchain_ai21/chat/chat_factory.py deleted file mode 100644 index 1fdeb5436f4..00000000000 --- a/libs/partners/ai21/langchain_ai21/chat/chat_factory.py +++ /dev/null @@ -1,23 +0,0 @@ -from langchain_ai21.chat.chat_adapter import ( - ChatAdapter, - J2ChatAdapter, - JambaChatCompletionsAdapter, -) - - -def create_chat_adapter(model: str) -> ChatAdapter: - """Create a chat adapter based on the model. - - Args: - model: The model to create the chat adapter for. - - Returns: - The chat adapter. - """ - if "j2" in model: - return J2ChatAdapter() - - if "jamba" in model: - return JambaChatCompletionsAdapter() - - raise ValueError(f"Model {model} not supported.") diff --git a/libs/partners/ai21/langchain_ai21/chat_models.py b/libs/partners/ai21/langchain_ai21/chat_models.py deleted file mode 100644 index a1ee06c4bae..00000000000 --- a/libs/partners/ai21/langchain_ai21/chat_models.py +++ /dev/null @@ -1,271 +0,0 @@ -import asyncio -from functools import partial -from typing import ( - Any, - Callable, - Dict, - Iterator, - List, - Mapping, - Optional, - Sequence, - Type, - Union, -) - -from langchain_core.callbacks import ( - AsyncCallbackManagerForLLMRun, - CallbackManagerForLLMRun, -) -from langchain_core.language_models import LanguageModelInput -from langchain_core.language_models.chat_models import ( - BaseChatModel, - LangSmithParams, - generate_from_stream, -) -from langchain_core.messages import ( - BaseMessage, -) -from langchain_core.outputs import ChatGeneration, ChatGenerationChunk, ChatResult -from langchain_core.pydantic_v1 import root_validator -from langchain_core.runnables import Runnable -from langchain_core.tools import BaseTool -from langchain_core.utils.function_calling import convert_to_openai_tool - -from langchain_ai21.ai21_base import AI21Base -from langchain_ai21.chat.chat_adapter import ChatAdapter -from langchain_ai21.chat.chat_factory import create_chat_adapter - - -class ChatAI21(BaseChatModel, AI21Base): - """ChatAI21 chat model. Different model types support different parameters and - different parameter values. Please read the [AI21 reference documentation] - (https://docs.ai21.com/reference) for your model to understand which parameters - are available. - - Example: - .. code-block:: python - - from langchain_ai21 import ChatAI21 - - - model = ChatAI21( - # defaults to os.environ.get("AI21_API_KEY") - api_key="my_api_key" - ) - """ - - model: str - """Model type you wish to interact with. - You can view the options at https://github.com/AI21Labs/ai21-python?tab=readme-ov-file#model-types""" - num_results: int = 1 - """The number of responses to generate for a given prompt.""" - stop: Optional[List[str]] = None - """Default stop sequences.""" - - max_tokens: int = 512 - """The maximum number of tokens to generate for each response.""" - - min_tokens: int = 0 - """The minimum number of tokens to generate for each response. - _Not supported for all models._""" - - temperature: float = 0.4 - """A value controlling the "creativity" of the model's responses.""" - - top_p: float = 1 - """A value controlling the diversity of the model's responses.""" - - top_k_return: int = 0 - """The number of top-scoring tokens to consider for each generation step. - _Not supported for all models._""" - - frequency_penalty: Optional[Any] = None - """A penalty applied to tokens that are frequently generated. - _Not supported for all models._""" - - presence_penalty: Optional[Any] = None - """ A penalty applied to tokens that are already present in the prompt. - _Not supported for all models._""" - - count_penalty: Optional[Any] = None - """A penalty applied to tokens based on their frequency - in the generated responses. _Not supported for all models._""" - - n: int = 1 - """Number of chat completions to generate for each prompt.""" - streaming: bool = False - - _chat_adapter: ChatAdapter - - @root_validator(pre=False, skip_on_failure=True) - def validate_environment(cls, values: Dict) -> Dict: - """Validate the environment.""" - model = values["model"] - values["_chat_adapter"] = create_chat_adapter(model) - return values - - class Config: - """Configuration for this pydantic object.""" - - arbitrary_types_allowed = True - - @property - def _llm_type(self) -> str: - """Return type of chat model.""" - return "chat-ai21" - - @property - def _default_params(self) -> Mapping[str, Any]: - base_params = { - "model": self.model, - "num_results": self.num_results, - "max_tokens": self.max_tokens, - "min_tokens": self.min_tokens, - "temperature": self.temperature, - "top_p": self.top_p, - "top_k_return": self.top_k_return, - "n": self.n, - } - if self.stop: - base_params["stop_sequences"] = self.stop - - if self.count_penalty is not None: - base_params["count_penalty"] = self.count_penalty.to_dict() - - if self.frequency_penalty is not None: - base_params["frequency_penalty"] = self.frequency_penalty.to_dict() - - if self.presence_penalty is not None: - base_params["presence_penalty"] = self.presence_penalty.to_dict() - - return base_params - - def _get_ls_params( - self, stop: Optional[List[str]] = None, **kwargs: Any - ) -> LangSmithParams: - """Get standard params for tracing.""" - params = self._get_invocation_params(stop=stop, **kwargs) - ls_params = LangSmithParams( - ls_provider="ai21", - ls_model_name=self.model, - ls_model_type="chat", - ls_temperature=params.get("temperature", self.temperature), - ) - if ls_max_tokens := params.get("max_tokens", self.max_tokens): - ls_params["ls_max_tokens"] = ls_max_tokens - if ls_stop := stop or params.get("stop", None) or self.stop: - ls_params["ls_stop"] = ls_stop - return ls_params - - def _build_params_for_request( - self, - messages: List[BaseMessage], - stop: Optional[List[str]] = None, - **kwargs: Any, - ) -> Mapping[str, Any]: - params = {} - converted_messages = self._chat_adapter.convert_messages(messages) - - if stop is not None: - if "stop" in kwargs: - raise ValueError("stop is defined in both stop and kwargs") - params["stop_sequences"] = stop - - return { - **converted_messages, - **self._default_params, - **params, - **kwargs, - } - - def _generate( - self, - messages: List[BaseMessage], - stop: Optional[List[str]] = None, - run_manager: Optional[CallbackManagerForLLMRun] = None, - stream: Optional[bool] = None, - **kwargs: Any, - ) -> ChatResult: - should_stream = stream or self.streaming - - if should_stream: - return self._handle_stream_from_generate( - messages=messages, - stop=stop, - run_manager=run_manager, - **kwargs, - ) - - params = self._build_params_for_request( - messages=messages, - stop=stop, - stream=should_stream, - **kwargs, - ) - - messages = self._chat_adapter.call(self.client, **params) - generations = [ChatGeneration(message=message) for message in messages] - - return ChatResult(generations=generations) - - def _handle_stream_from_generate( - self, - messages: List[BaseMessage], - stop: Optional[List[str]] = None, - run_manager: Optional[CallbackManagerForLLMRun] = None, - **kwargs: Any, - ) -> ChatResult: - stream_iter = self._stream( - messages=messages, - stop=stop, - run_manager=run_manager, - **kwargs, - ) - return generate_from_stream(stream_iter) - - def _stream( - self, - messages: List[BaseMessage], - stop: Optional[List[str]] = None, - run_manager: Optional[CallbackManagerForLLMRun] = None, - **kwargs: Any, - ) -> Iterator[ChatGenerationChunk]: - params = self._build_params_for_request( - messages=messages, - stop=stop, - stream=True, - **kwargs, - ) - - for chunk in self._chat_adapter.call(self.client, **params): - if run_manager and isinstance(chunk.message.content, str): - run_manager.on_llm_new_token(token=chunk.message.content, chunk=chunk) - yield chunk - - async def _agenerate( - self, - messages: List[BaseMessage], - stop: Optional[List[str]] = None, - run_manager: Optional[AsyncCallbackManagerForLLMRun] = None, - **kwargs: Any, - ) -> ChatResult: - return await asyncio.get_running_loop().run_in_executor( - None, partial(self._generate, **kwargs), messages, stop, run_manager - ) - - def _get_system_message_from_message(self, message: BaseMessage) -> str: - if not isinstance(message.content, str): - raise ValueError( - f"System Message must be of type str. Got {type(message.content)}" - ) - - return message.content - - def bind_tools( - self, - tools: Sequence[Union[Dict[str, Any], Type, Callable, BaseTool]], - **kwargs: Any, - ) -> Runnable[LanguageModelInput, BaseMessage]: - formatted_tools = [convert_to_openai_tool(tool) for tool in tools] - return super().bind(tools=formatted_tools, **kwargs) diff --git a/libs/partners/ai21/langchain_ai21/contextual_answers.py b/libs/partners/ai21/langchain_ai21/contextual_answers.py deleted file mode 100644 index 79b091adac7..00000000000 --- a/libs/partners/ai21/langchain_ai21/contextual_answers.py +++ /dev/null @@ -1,112 +0,0 @@ -from typing import ( - Any, - List, - Optional, - Tuple, - Type, - TypedDict, - Union, -) - -from langchain_core.documents import Document -from langchain_core.runnables import RunnableConfig, RunnableSerializable, ensure_config - -from langchain_ai21.ai21_base import AI21Base - -ANSWER_NOT_IN_CONTEXT_RESPONSE = "Answer not in context" - -ContextType = Union[str, List[Union[Document, str]]] - - -class ContextualAnswerInput(TypedDict): - """Input for the ContextualAnswers runnable.""" - - context: ContextType - question: str - - -class AI21ContextualAnswers(RunnableSerializable[ContextualAnswerInput, str], AI21Base): - """Runnable for the AI21 Contextual Answers API.""" - - class Config: - """Configuration for this pydantic object.""" - - arbitrary_types_allowed = True - - @property - def InputType(self) -> Type[ContextualAnswerInput]: - """Get the input type for this runnable.""" - return ContextualAnswerInput - - @property - def OutputType(self) -> Type[str]: - """Get the input type for this runnable.""" - return str - - def invoke( - self, - input: ContextualAnswerInput, - config: Optional[RunnableConfig] = None, - response_if_no_answer_found: str = ANSWER_NOT_IN_CONTEXT_RESPONSE, - **kwargs: Any, - ) -> str: - config = ensure_config(config) - return self._call_with_config( - func=lambda inner_input: self._call_contextual_answers( - inner_input, response_if_no_answer_found - ), - input=input, - config=config, - run_type="llm", - ) - - def _call_contextual_answers( - self, - input: ContextualAnswerInput, - response_if_no_answer_found: str, - ) -> str: - context, question = self._convert_input(input) - response = self.client.answer.create(context=context, question=question) - - if response.answer is None: - return response_if_no_answer_found - - return response.answer - - def _convert_input(self, input: ContextualAnswerInput) -> Tuple[str, str]: - context, question = self._extract_context_and_question(input) - - context = self._parse_context(context) - - return context, question - - def _extract_context_and_question( - self, - input: ContextualAnswerInput, - ) -> Tuple[ContextType, str]: - context = input.get("context") - question = input.get("question") - - if not context or not question: - raise ValueError( - f"Input must contain a 'context' and 'question' fields. Got {input}" - ) - - if not isinstance(context, list) and not isinstance(context, str): - raise ValueError( - f"Expected input to be a list of strings or Documents." - f" Received {type(input)}" - ) - - return context, question - - def _parse_context(self, context: ContextType) -> str: - if isinstance(context, str): - return context - - docs = [ - item.page_content if isinstance(item, Document) else item - for item in context - ] - - return "\n".join(docs) diff --git a/libs/partners/ai21/langchain_ai21/embeddings.py b/libs/partners/ai21/langchain_ai21/embeddings.py deleted file mode 100644 index 9d18c55e4b9..00000000000 --- a/libs/partners/ai21/langchain_ai21/embeddings.py +++ /dev/null @@ -1,126 +0,0 @@ -from itertools import islice -from typing import Any, Iterator, List, Optional - -from ai21.models import EmbedType -from langchain_core.embeddings import Embeddings - -from langchain_ai21.ai21_base import AI21Base - -_DEFAULT_BATCH_SIZE = 128 - - -def _split_texts_into_batches(texts: List[str], batch_size: int) -> Iterator[List[str]]: - texts_itr = iter(texts) - return iter(lambda: list(islice(texts_itr, batch_size)), []) - - -class AI21Embeddings(Embeddings, AI21Base): - """AI21 embedding model integration. - - Install ``langchain_ai21`` and set environment variable ``AI21_API_KEY``. - - .. code-block:: bash - - pip install -U langchain_ai21 - export AI21_API_KEY="your-api-key" - - Key init args — client params: - api_key: Optional[SecretStr] - batch_size: int - The number of texts that will be sent to the API in each batch. - Use larger batch sizes if working with many short texts. This will reduce - the number of API calls made, and can improve the time it takes to embed - a large number of texts. - num_retries: Optional[int] - Maximum number of retries for API requests before giving up. - timeout_sec: Optional[float] - Timeout in seconds for API requests. If not set, it will default to the - value of the environment variable `AI21_TIMEOUT_SEC` or 300 seconds. - - See full list of supported init args and their descriptions in the params section. - - Instantiate: - .. code-block:: python - - from langchain_ai21 import AI21Embeddings - - embed = AI21Embeddings( - # api_key="...", - # batch_size=128, - ) - - Embed single text: - .. code-block:: python - - input_text = "The meaning of life is 42" - vector = embed.embed_query(input_text) - print(vector[:3]) - - .. code-block:: python - - [-0.024603435769677162, -0.007543657906353474, 0.0039630369283258915] - - Embed multiple texts: - .. code-block:: python - - input_texts = ["Document 1...", "Document 2..."] - vectors = embed.embed_documents(input_texts) - print(len(vectors)) - # The first 3 coordinates for the first vector - print(vectors[0][:3]) - - .. code-block:: python - - 2 - [-0.024603435769677162, -0.007543657906353474, 0.0039630369283258915] - """ - - batch_size: int = _DEFAULT_BATCH_SIZE - """Maximum number of texts to embed in each batch""" - - def embed_documents( - self, - texts: List[str], - *, - batch_size: Optional[int] = None, - **kwargs: Any, - ) -> List[List[float]]: - """Embed search docs.""" - return self._send_embeddings( - texts=texts, - batch_size=batch_size or self.batch_size, - embed_type=EmbedType.SEGMENT, - **kwargs, - ) - - def embed_query( - self, - text: str, - *, - batch_size: Optional[int] = None, - **kwargs: Any, - ) -> List[float]: - """Embed query text.""" - return self._send_embeddings( - texts=[text], - batch_size=batch_size or self.batch_size, - embed_type=EmbedType.QUERY, - **kwargs, - )[0] - - def _send_embeddings( - self, texts: List[str], *, batch_size: int, embed_type: EmbedType, **kwargs: Any - ) -> List[List[float]]: - chunks = _split_texts_into_batches(texts, batch_size) - responses = [ - self.client.embed.create( - texts=chunk, - type=embed_type, - **kwargs, - ) - for chunk in chunks - ] - - return [ - result.embedding for response in responses for result in response.results - ] diff --git a/libs/partners/ai21/langchain_ai21/llms.py b/libs/partners/ai21/langchain_ai21/llms.py deleted file mode 100644 index f5c4489583f..00000000000 --- a/libs/partners/ai21/langchain_ai21/llms.py +++ /dev/null @@ -1,188 +0,0 @@ -import asyncio -from functools import partial -from typing import ( - Any, - List, - Mapping, - Optional, -) - -from ai21.models import CompletionsResponse -from langchain_core.callbacks import ( - AsyncCallbackManagerForLLMRun, - CallbackManagerForLLMRun, -) -from langchain_core.language_models import BaseLLM -from langchain_core.outputs import Generation, LLMResult - -from langchain_ai21.ai21_base import AI21Base - - -class AI21LLM(BaseLLM, AI21Base): - """AI21 large language models. Different model types support different parameters - and different parameter values. Please read the [AI21 reference documentation] - (https://docs.ai21.com/reference) for your model to understand which parameters - are available. - - AI21LLM supports only the older Jurassic models. - We recommend using ChatAI21 with the newest models, for better results and more - features. - - Example: - .. code-block:: python - - from langchain_ai21 import AI21LLM - - model = AI21LLM( - # defaults to os.environ.get("AI21_API_KEY") - api_key="my_api_key" - ) - """ - - model: str - """Model type you wish to interact with. - You can view the options at https://github.com/AI21Labs/ai21-python?tab=readme-ov-file#model-types""" - - num_results: int = 1 - """The number of responses to generate for a given prompt.""" - - max_tokens: int = 16 - """The maximum number of tokens to generate for each response.""" - - min_tokens: int = 0 - """The minimum number of tokens to generate for each response. - _Not supported for all models._""" - - temperature: float = 0.7 - """A value controlling the "creativity" of the model's responses.""" - - top_p: float = 1 - """A value controlling the diversity of the model's responses.""" - - top_k_return: int = 0 - """The number of top-scoring tokens to consider for each generation step. - _Not supported for all models._""" - - frequency_penalty: Optional[Any] = None - """A penalty applied to tokens that are frequently generated. - _Not supported for all models._""" - - presence_penalty: Optional[Any] = None - """ A penalty applied to tokens that are already present in the prompt. - _Not supported for all models._""" - - count_penalty: Optional[Any] = None - """A penalty applied to tokens based on their frequency - in the generated responses. _Not supported for all models._""" - - custom_model: Optional[str] = None - epoch: Optional[int] = None - - class Config: - """Configuration for this pydantic object.""" - - allow_population_by_field_name = True - - @property - def _llm_type(self) -> str: - """Return type of LLM.""" - return "ai21-llm" - - @property - def _default_params(self) -> Mapping[str, Any]: - base_params = { - "model": self.model, - "num_results": self.num_results, - "max_tokens": self.max_tokens, - "min_tokens": self.min_tokens, - "temperature": self.temperature, - "top_p": self.top_p, - "top_k_return": self.top_k_return, - } - - if self.count_penalty is not None: - base_params["count_penalty"] = self.count_penalty.to_dict() - - if self.custom_model is not None: - base_params["custom_model"] = self.custom_model - - if self.epoch is not None: - base_params["epoch"] = self.epoch - - if self.frequency_penalty is not None: - base_params["frequency_penalty"] = self.frequency_penalty.to_dict() - - if self.presence_penalty is not None: - base_params["presence_penalty"] = self.presence_penalty.to_dict() - - return base_params - - def _build_params_for_request( - self, stop: Optional[List[str]] = None, **kwargs: Any - ) -> Mapping[str, Any]: - params = {} - - if stop is not None: - if "stop" in kwargs: - raise ValueError("stop is defined in both stop and kwargs") - params["stop_sequences"] = stop - - return { - **self._default_params, - **params, - **kwargs, - } - - def _generate( - self, - prompts: List[str], - stop: Optional[List[str]] = None, - run_manager: Optional[CallbackManagerForLLMRun] = None, - **kwargs: Any, - ) -> LLMResult: - generations: List[List[Generation]] = [] - token_count = 0 - - params = self._build_params_for_request(stop=stop, **kwargs) - - for prompt in prompts: - response = self._invoke_completion(prompt=prompt, **params) - generation = self._response_to_generation(response) - generations.append(generation) - token_count += self.client.count_tokens(prompt) - - llm_output = {"token_count": token_count, "model_name": self.model} - return LLMResult(generations=generations, llm_output=llm_output) - - async def _agenerate( - self, - prompts: List[str], - stop: Optional[List[str]] = None, - run_manager: Optional[AsyncCallbackManagerForLLMRun] = None, - **kwargs: Any, - ) -> LLMResult: - # Change implementation if integration natively supports async generation. - return await asyncio.get_running_loop().run_in_executor( - None, partial(self._generate, **kwargs), prompts, stop, run_manager - ) - - def _invoke_completion( - self, - prompt: str, - **kwargs: Any, - ) -> CompletionsResponse: - return self.client.completion.create( - prompt=prompt, - **kwargs, - ) - - def _response_to_generation( - self, response: CompletionsResponse - ) -> List[Generation]: - return [ - Generation( - text=completion.data.text, # type: ignore[arg-type] - generation_info=completion.to_dict(), - ) - for completion in response.completions - ] diff --git a/libs/partners/ai21/langchain_ai21/py.typed b/libs/partners/ai21/langchain_ai21/py.typed deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libs/partners/ai21/langchain_ai21/semantic_text_splitter.py b/libs/partners/ai21/langchain_ai21/semantic_text_splitter.py deleted file mode 100644 index 974ba6bc237..00000000000 --- a/libs/partners/ai21/langchain_ai21/semantic_text_splitter.py +++ /dev/null @@ -1,158 +0,0 @@ -import copy -import logging -import re -from typing import ( - Any, - Iterable, - List, - Optional, -) - -from ai21.models import DocumentType -from langchain_core.documents import Document -from langchain_core.pydantic_v1 import SecretStr -from langchain_text_splitters import TextSplitter - -from langchain_ai21.ai21_base import AI21Base - -logger = logging.getLogger(__name__) - - -class AI21SemanticTextSplitter(TextSplitter): - """Splitting text into coherent and readable units, - based on distinct topics and lines. - """ - - def __init__( - self, - chunk_size: int = 0, - chunk_overlap: int = 0, - client: Optional[Any] = None, - api_key: Optional[SecretStr] = None, - api_host: Optional[str] = None, - timeout_sec: Optional[float] = None, - num_retries: Optional[int] = None, - **kwargs: Any, - ) -> None: - """Create a new TextSplitter.""" - super().__init__( - chunk_size=chunk_size, - chunk_overlap=chunk_overlap, - **kwargs, - ) - - self._segmentation = AI21Base( - client=client, - api_key=api_key, - api_host=api_host, - timeout_sec=timeout_sec, - num_retries=num_retries, - ).client.segmentation - - def split_text(self, source: str) -> List[str]: - """Split text into multiple components. - - Args: - source: Specifies the text input for text segmentation - """ - response = self._segmentation.create( - source=source, source_type=DocumentType.TEXT - ) - - segments = [segment.segment_text for segment in response.segments] - - if self._chunk_size > 0: - return self._merge_splits_no_seperator(segments) - - return segments - - def split_text_to_documents(self, source: str) -> List[Document]: - """Split text into multiple documents. - - Args: - source: Specifies the text input for text segmentation - """ - response = self._segmentation.create( - source=source, source_type=DocumentType.TEXT - ) - - return [ - Document( - page_content=segment.segment_text, - metadata={"source_type": segment.segment_type}, - ) - for segment in response.segments - ] - - def create_documents( - self, texts: List[str], metadatas: Optional[List[dict]] = None - ) -> List[Document]: - """Create documents from a list of texts.""" - _metadatas = metadatas or [{}] * len(texts) - documents = [] - - for i, text in enumerate(texts): - normalized_text = self._normalized_text(text) - index = 0 - previous_chunk_len = 0 - - for chunk in self.split_text_to_documents(text): - # merge metadata from user (if exists) and from segmentation api - metadata = copy.deepcopy(_metadatas[i]) - metadata.update(chunk.metadata) - - if self._add_start_index: - # find the start index of the chunk - offset = index + previous_chunk_len - self._chunk_overlap - normalized_chunk = self._normalized_text(chunk.page_content) - index = normalized_text.find(normalized_chunk, max(0, offset)) - metadata["start_index"] = index - previous_chunk_len = len(normalized_chunk) - - documents.append( - Document( - page_content=chunk.page_content, - metadata=metadata, - ) - ) - - return documents - - def _normalized_text(self, string: str) -> str: - """Use regular expression to replace sequences of '\n'""" - return re.sub(r"\s+", "", string) - - def _merge_splits(self, splits: Iterable[str], separator: str) -> List[str]: - """This method overrides the default implementation of TextSplitter""" - return self._merge_splits_no_seperator(splits) - - def _merge_splits_no_seperator(self, splits: Iterable[str]) -> List[str]: - """Merge splits into chunks. - If the segment size is bigger than chunk_size, - it will be left as is (won't be cut to match to chunk_size). - If the segment size is smaller than chunk_size, - it will be merged with the next segment until the chunk_size is reached. - """ - chunks = [] - current_chunk = "" - - for split in splits: - split_len = self._length_function(split) - - if split_len > self._chunk_size: - logger.warning( - f"Split of length {split_len}" - f"exceeds chunk size {self._chunk_size}." - ) - - if self._length_function(current_chunk) + split_len > self._chunk_size: - if current_chunk != "": - chunks.append(current_chunk) - current_chunk = "" - - current_chunk += split - - if current_chunk != "": - chunks.append(current_chunk) - - return chunks diff --git a/libs/partners/ai21/poetry.lock b/libs/partners/ai21/poetry.lock deleted file mode 100644 index 15cc04d5e8b..00000000000 --- a/libs/partners/ai21/poetry.lock +++ /dev/null @@ -1,1322 +0,0 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. - -[[package]] -name = "ai21" -version = "2.14.1" -description = "" -optional = false -python-versions = "<4.0,>=3.8" -files = [ - {file = "ai21-2.14.1-py3-none-any.whl", hash = "sha256:618c0b5c025123c703645258472330a07ae2de17020438f6a33b29668275995c"}, - {file = "ai21-2.14.1.tar.gz", hash = "sha256:05d9626b82206e0a5be43d17c39d4e0c7b51c2b7634d2ea38a2c698ac3e2fd5b"}, -] - -[package.dependencies] -ai21-tokenizer = ">=0.12.0,<1.0.0" -httpx = ">=0.27.0,<0.28.0" -pydantic = ">=1.9.0,<3.0.0" -tenacity = ">=8.3.0,<9.0.0" -typing-extensions = ">=4.9.0,<5.0.0" - -[package.extras] -aws = ["boto3 (>=1.28.82,<2.0.0)"] -vertex = ["google-auth (>=2.31.0,<3.0.0)"] - -[[package]] -name = "ai21-tokenizer" -version = "0.12.0" -description = "" -optional = false -python-versions = "<4.0,>=3.8" -files = [ - {file = "ai21_tokenizer-0.12.0-py3-none-any.whl", hash = "sha256:7fd37b9093894b30b0f200e5f44fc8fb8772e2b272ef71b6d73722b4696e63c4"}, - {file = "ai21_tokenizer-0.12.0.tar.gz", hash = "sha256:d2a5b17789d21572504b7693148bf66e692bdb3ab563023dbcbee340bcbd11c6"}, -] - -[package.dependencies] -anyio = ">=4.4.0,<5.0.0" -sentencepiece = ">=0.2.0,<1.0.0" -tokenizers = ">=0.15.0,<1.0.0" - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[package.dependencies] -typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} - -[[package]] -name = "anyio" -version = "4.4.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.8" -files = [ - {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, - {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, -] - -[package.dependencies] -exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} -idna = ">=2.8" -sniffio = ">=1.1" -typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} - -[package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (>=0.23)"] - -[[package]] -name = "certifi" -version = "2024.7.4" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -files = [ - {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, - {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, -] - -[[package]] -name = "charset-normalizer" -version = "3.3.2" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, -] - -[[package]] -name = "codespell" -version = "2.3.0" -description = "Codespell" -optional = false -python-versions = ">=3.8" -files = [ - {file = "codespell-2.3.0-py3-none-any.whl", hash = "sha256:a9c7cef2501c9cfede2110fd6d4e5e62296920efe9abfb84648df866e47f58d1"}, - {file = "codespell-2.3.0.tar.gz", hash = "sha256:360c7d10f75e65f67bad720af7007e1060a5d395670ec11a7ed1fed9dd17471f"}, -] - -[package.extras] -dev = ["Pygments", "build", "chardet", "pre-commit", "pytest", "pytest-cov", "pytest-dependency", "ruff", "tomli", "twine"] -hard-encoding-detection = ["chardet"] -toml = ["tomli"] -types = ["chardet (>=5.1.0)", "mypy", "pytest", "pytest-cov", "pytest-dependency"] - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "exceptiongroup" -version = "1.2.2" -description = "Backport of PEP 654 (exception groups)" -optional = false -python-versions = ">=3.7" -files = [ - {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, - {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, -] - -[package.extras] -test = ["pytest (>=6)"] - -[[package]] -name = "filelock" -version = "3.15.4" -description = "A platform independent file lock." -optional = false -python-versions = ">=3.8" -files = [ - {file = "filelock-3.15.4-py3-none-any.whl", hash = "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7"}, - {file = "filelock-3.15.4.tar.gz", hash = "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb"}, -] - -[package.extras] -docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)", "virtualenv (>=20.26.2)"] -typing = ["typing-extensions (>=4.8)"] - -[[package]] -name = "freezegun" -version = "1.5.1" -description = "Let your Python tests travel through time" -optional = false -python-versions = ">=3.7" -files = [ - {file = "freezegun-1.5.1-py3-none-any.whl", hash = "sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1"}, - {file = "freezegun-1.5.1.tar.gz", hash = "sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9"}, -] - -[package.dependencies] -python-dateutil = ">=2.7" - -[[package]] -name = "fsspec" -version = "2024.6.1" -description = "File-system specification" -optional = false -python-versions = ">=3.8" -files = [ - {file = "fsspec-2024.6.1-py3-none-any.whl", hash = "sha256:3cb443f8bcd2efb31295a5b9fdb02aee81d8452c80d28f97a6d0959e6cee101e"}, - {file = "fsspec-2024.6.1.tar.gz", hash = "sha256:fad7d7e209dd4c1208e3bbfda706620e0da5142bebbd9c384afb95b07e798e49"}, -] - -[package.extras] -abfs = ["adlfs"] -adl = ["adlfs"] -arrow = ["pyarrow (>=1)"] -dask = ["dask", "distributed"] -dev = ["pre-commit", "ruff"] -doc = ["numpydoc", "sphinx", "sphinx-design", "sphinx-rtd-theme", "yarl"] -dropbox = ["dropbox", "dropboxdrivefs", "requests"] -full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] -fuse = ["fusepy"] -gcs = ["gcsfs"] -git = ["pygit2"] -github = ["requests"] -gs = ["gcsfs"] -gui = ["panel"] -hdfs = ["pyarrow (>=1)"] -http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)"] -libarchive = ["libarchive-c"] -oci = ["ocifs"] -s3 = ["s3fs"] -sftp = ["paramiko"] -smb = ["smbprotocol"] -ssh = ["paramiko"] -test = ["aiohttp (!=4.0.0a0,!=4.0.0a1)", "numpy", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "requests"] -test-downstream = ["aiobotocore (>=2.5.4,<3.0.0)", "dask-expr", "dask[dataframe,test]", "moto[server] (>4,<5)", "pytest-timeout", "xarray"] -test-full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "cloudpickle", "dask", "distributed", "dropbox", "dropboxdrivefs", "fastparquet", "fusepy", "gcsfs", "jinja2", "kerchunk", "libarchive-c", "lz4", "notebook", "numpy", "ocifs", "pandas", "panel", "paramiko", "pyarrow", "pyarrow (>=1)", "pyftpdlib", "pygit2", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "python-snappy", "requests", "smbprotocol", "tqdm", "urllib3", "zarr", "zstandard"] -tqdm = ["tqdm"] - -[[package]] -name = "h11" -version = "0.14.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -optional = false -python-versions = ">=3.7" -files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, -] - -[[package]] -name = "httpcore" -version = "1.0.5" -description = "A minimal low-level HTTP client." -optional = false -python-versions = ">=3.8" -files = [ - {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, - {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, -] - -[package.dependencies] -certifi = "*" -h11 = ">=0.13,<0.15" - -[package.extras] -asyncio = ["anyio (>=4.0,<5.0)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<0.26.0)"] - -[[package]] -name = "httpx" -version = "0.27.0" -description = "The next generation HTTP client." -optional = false -python-versions = ">=3.8" -files = [ - {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, - {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, -] - -[package.dependencies] -anyio = "*" -certifi = "*" -httpcore = "==1.*" -idna = "*" -sniffio = "*" - -[package.extras] -brotli = ["brotli", "brotlicffi"] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] - -[[package]] -name = "huggingface-hub" -version = "0.24.6" -description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "huggingface_hub-0.24.6-py3-none-any.whl", hash = "sha256:a990f3232aa985fe749bc9474060cbad75e8b2f115f6665a9fda5b9c97818970"}, - {file = "huggingface_hub-0.24.6.tar.gz", hash = "sha256:cc2579e761d070713eaa9c323e3debe39d5b464ae3a7261c39a9195b27bb8000"}, -] - -[package.dependencies] -filelock = "*" -fsspec = ">=2023.5.0" -packaging = ">=20.9" -pyyaml = ">=5.1" -requests = "*" -tqdm = ">=4.42.1" -typing-extensions = ">=3.7.4.3" - -[package.extras] -all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.5.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] -cli = ["InquirerPy (==0.3.4)"] -dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.5.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] -fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"] -hf-transfer = ["hf-transfer (>=0.1.4)"] -inference = ["aiohttp", "minijinja (>=1.0)"] -quality = ["mypy (==1.5.1)", "ruff (>=0.5.0)"] -tensorflow = ["graphviz", "pydot", "tensorflow"] -tensorflow-testing = ["keras (<3.0)", "tensorflow"] -testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] -torch = ["safetensors[torch]", "torch"] -typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"] - -[[package]] -name = "idna" -version = "3.8" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.6" -files = [ - {file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"}, - {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, -] - -[[package]] -name = "iniconfig" -version = "2.0.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.7" -files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] - -[[package]] -name = "jsonpatch" -version = "1.33" -description = "Apply JSON-Patches (RFC 6902)" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" -files = [ - {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, - {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"}, -] - -[package.dependencies] -jsonpointer = ">=1.9" - -[[package]] -name = "jsonpointer" -version = "3.0.0" -description = "Identify specific nodes in a JSON document (RFC 6901)" -optional = false -python-versions = ">=3.7" -files = [ - {file = "jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942"}, - {file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"}, -] - -[[package]] -name = "langchain-core" -version = "0.2.35" -description = "Building applications with LLMs through composability" -optional = false -python-versions = ">=3.8.1,<4.0" -files = [] -develop = true - -[package.dependencies] -jsonpatch = "^1.33" -langsmith = "^0.1.75" -packaging = ">=23.2,<25" -pydantic = [ - {version = ">=1,<3", markers = "python_full_version < \"3.12.4\""}, - {version = ">=2.7.4,<3.0.0", markers = "python_full_version >= \"3.12.4\""}, -] -PyYAML = ">=5.3" -tenacity = "^8.1.0,!=8.4.0" -typing-extensions = ">=4.7" - -[package.source] -type = "directory" -url = "../../core" - -[[package]] -name = "langchain-standard-tests" -version = "0.1.1" -description = "Standard tests for LangChain implementations" -optional = false -python-versions = ">=3.8.1,<4.0" -files = [] -develop = true - -[package.dependencies] -httpx = "^0.27.0" -langchain-core = ">=0.1.40,<0.3" -pytest = ">=7,<9" - -[package.source] -type = "directory" -url = "../../standard-tests" - -[[package]] -name = "langchain-text-splitters" -version = "0.2.3" -description = "LangChain text splitting utilities" -optional = false -python-versions = ">=3.8.1,<4.0" -files = [] -develop = true - -[package.dependencies] -langchain-core = "^0.2.10" - -[package.source] -type = "directory" -url = "../../text-splitters" - -[[package]] -name = "langsmith" -version = "0.1.104" -description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." -optional = false -python-versions = "<4.0,>=3.8.1" -files = [ - {file = "langsmith-0.1.104-py3-none-any.whl", hash = "sha256:049cd312952a0db9f5edeed3b9a8616e66ef86e5490c835c8bb054569203b0d0"}, - {file = "langsmith-0.1.104.tar.gz", hash = "sha256:7892dfe452d143fba573d7eb28dbff3202d2f2daacab8c7276ffe4a850179d4d"}, -] - -[package.dependencies] -httpx = ">=0.23.0,<1" -orjson = ">=3.9.14,<4.0.0" -pydantic = [ - {version = ">=1,<3", markers = "python_full_version < \"3.12.4\""}, - {version = ">=2.7.4,<3.0.0", markers = "python_full_version >= \"3.12.4\""}, -] -requests = ">=2,<3" - -[[package]] -name = "mypy" -version = "1.11.2" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "mypy-1.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d42a6dd818ffce7be66cce644f1dff482f1d97c53ca70908dff0b9ddc120b77a"}, - {file = "mypy-1.11.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:801780c56d1cdb896eacd5619a83e427ce436d86a3bdf9112527f24a66618fef"}, - {file = "mypy-1.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41ea707d036a5307ac674ea172875f40c9d55c5394f888b168033177fce47383"}, - {file = "mypy-1.11.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6e658bd2d20565ea86da7d91331b0eed6d2eee22dc031579e6297f3e12c758c8"}, - {file = "mypy-1.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:478db5f5036817fe45adb7332d927daa62417159d49783041338921dcf646fc7"}, - {file = "mypy-1.11.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75746e06d5fa1e91bfd5432448d00d34593b52e7e91a187d981d08d1f33d4385"}, - {file = "mypy-1.11.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a976775ab2256aadc6add633d44f100a2517d2388906ec4f13231fafbb0eccca"}, - {file = "mypy-1.11.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd953f221ac1379050a8a646585a29574488974f79d8082cedef62744f0a0104"}, - {file = "mypy-1.11.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:57555a7715c0a34421013144a33d280e73c08df70f3a18a552938587ce9274f4"}, - {file = "mypy-1.11.2-cp311-cp311-win_amd64.whl", hash = "sha256:36383a4fcbad95f2657642a07ba22ff797de26277158f1cc7bd234821468b1b6"}, - {file = "mypy-1.11.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e8960dbbbf36906c5c0b7f4fbf2f0c7ffb20f4898e6a879fcf56a41a08b0d318"}, - {file = "mypy-1.11.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:06d26c277962f3fb50e13044674aa10553981ae514288cb7d0a738f495550b36"}, - {file = "mypy-1.11.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e7184632d89d677973a14d00ae4d03214c8bc301ceefcdaf5c474866814c987"}, - {file = "mypy-1.11.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3a66169b92452f72117e2da3a576087025449018afc2d8e9bfe5ffab865709ca"}, - {file = "mypy-1.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:969ea3ef09617aff826885a22ece0ddef69d95852cdad2f60c8bb06bf1f71f70"}, - {file = "mypy-1.11.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:37c7fa6121c1cdfcaac97ce3d3b5588e847aa79b580c1e922bb5d5d2902df19b"}, - {file = "mypy-1.11.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4a8a53bc3ffbd161b5b2a4fff2f0f1e23a33b0168f1c0778ec70e1a3d66deb86"}, - {file = "mypy-1.11.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ff93107f01968ed834f4256bc1fc4475e2fecf6c661260066a985b52741ddce"}, - {file = "mypy-1.11.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:edb91dded4df17eae4537668b23f0ff6baf3707683734b6a818d5b9d0c0c31a1"}, - {file = "mypy-1.11.2-cp38-cp38-win_amd64.whl", hash = "sha256:ee23de8530d99b6db0573c4ef4bd8f39a2a6f9b60655bf7a1357e585a3486f2b"}, - {file = "mypy-1.11.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:801ca29f43d5acce85f8e999b1e431fb479cb02d0e11deb7d2abb56bdaf24fd6"}, - {file = "mypy-1.11.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af8d155170fcf87a2afb55b35dc1a0ac21df4431e7d96717621962e4b9192e70"}, - {file = "mypy-1.11.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7821776e5c4286b6a13138cc935e2e9b6fde05e081bdebf5cdb2bb97c9df81d"}, - {file = "mypy-1.11.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:539c570477a96a4e6fb718b8d5c3e0c0eba1f485df13f86d2970c91f0673148d"}, - {file = "mypy-1.11.2-cp39-cp39-win_amd64.whl", hash = "sha256:3f14cd3d386ac4d05c5a39a51b84387403dadbd936e17cb35882134d4f8f0d24"}, - {file = "mypy-1.11.2-py3-none-any.whl", hash = "sha256:b499bc07dbdcd3de92b0a8b29fdf592c111276f6a12fe29c30f6c417dd546d12"}, - {file = "mypy-1.11.2.tar.gz", hash = "sha256:7f9993ad3e0ffdc95c2a14b66dee63729f021968bff8ad911867579c65d13a79"}, -] - -[package.dependencies] -mypy-extensions = ">=1.0.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - -[[package]] -name = "orjson" -version = "3.10.7" -description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" -optional = false -python-versions = ">=3.8" -files = [ - {file = "orjson-3.10.7-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:74f4544f5a6405b90da8ea724d15ac9c36da4d72a738c64685003337401f5c12"}, - {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34a566f22c28222b08875b18b0dfbf8a947e69df21a9ed5c51a6bf91cfb944ac"}, - {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf6ba8ebc8ef5792e2337fb0419f8009729335bb400ece005606336b7fd7bab7"}, - {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac7cf6222b29fbda9e3a472b41e6a5538b48f2c8f99261eecd60aafbdb60690c"}, - {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de817e2f5fc75a9e7dd350c4b0f54617b280e26d1631811a43e7e968fa71e3e9"}, - {file = "orjson-3.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:348bdd16b32556cf8d7257b17cf2bdb7ab7976af4af41ebe79f9796c218f7e91"}, - {file = "orjson-3.10.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:479fd0844ddc3ca77e0fd99644c7fe2de8e8be1efcd57705b5c92e5186e8a250"}, - {file = "orjson-3.10.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fdf5197a21dd660cf19dfd2a3ce79574588f8f5e2dbf21bda9ee2d2b46924d84"}, - {file = "orjson-3.10.7-cp310-none-win32.whl", hash = "sha256:d374d36726746c81a49f3ff8daa2898dccab6596864ebe43d50733275c629175"}, - {file = "orjson-3.10.7-cp310-none-win_amd64.whl", hash = "sha256:cb61938aec8b0ffb6eef484d480188a1777e67b05d58e41b435c74b9d84e0b9c"}, - {file = "orjson-3.10.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:7db8539039698ddfb9a524b4dd19508256107568cdad24f3682d5773e60504a2"}, - {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:480f455222cb7a1dea35c57a67578848537d2602b46c464472c995297117fa09"}, - {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8a9c9b168b3a19e37fe2778c0003359f07822c90fdff8f98d9d2a91b3144d8e0"}, - {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8de062de550f63185e4c1c54151bdddfc5625e37daf0aa1e75d2a1293e3b7d9a"}, - {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6b0dd04483499d1de9c8f6203f8975caf17a6000b9c0c54630cef02e44ee624e"}, - {file = "orjson-3.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b58d3795dafa334fc8fd46f7c5dc013e6ad06fd5b9a4cc98cb1456e7d3558bd6"}, - {file = "orjson-3.10.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:33cfb96c24034a878d83d1a9415799a73dc77480e6c40417e5dda0710d559ee6"}, - {file = "orjson-3.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e724cebe1fadc2b23c6f7415bad5ee6239e00a69f30ee423f319c6af70e2a5c0"}, - {file = "orjson-3.10.7-cp311-none-win32.whl", hash = "sha256:82763b46053727a7168d29c772ed5c870fdae2f61aa8a25994c7984a19b1021f"}, - {file = "orjson-3.10.7-cp311-none-win_amd64.whl", hash = "sha256:eb8d384a24778abf29afb8e41d68fdd9a156cf6e5390c04cc07bbc24b89e98b5"}, - {file = "orjson-3.10.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:44a96f2d4c3af51bfac6bc4ef7b182aa33f2f054fd7f34cc0ee9a320d051d41f"}, - {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76ac14cd57df0572453543f8f2575e2d01ae9e790c21f57627803f5e79b0d3c3"}, - {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bdbb61dcc365dd9be94e8f7df91975edc9364d6a78c8f7adb69c1cdff318ec93"}, - {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b48b3db6bb6e0a08fa8c83b47bc169623f801e5cc4f24442ab2b6617da3b5313"}, - {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23820a1563a1d386414fef15c249040042b8e5d07b40ab3fe3efbfbbcbcb8864"}, - {file = "orjson-3.10.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0c6a008e91d10a2564edbb6ee5069a9e66df3fbe11c9a005cb411f441fd2c09"}, - {file = "orjson-3.10.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d352ee8ac1926d6193f602cbe36b1643bbd1bbcb25e3c1a657a4390f3000c9a5"}, - {file = "orjson-3.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d2d9f990623f15c0ae7ac608103c33dfe1486d2ed974ac3f40b693bad1a22a7b"}, - {file = "orjson-3.10.7-cp312-none-win32.whl", hash = "sha256:7c4c17f8157bd520cdb7195f75ddbd31671997cbe10aee559c2d613592e7d7eb"}, - {file = "orjson-3.10.7-cp312-none-win_amd64.whl", hash = "sha256:1d9c0e733e02ada3ed6098a10a8ee0052dd55774de3d9110d29868d24b17faa1"}, - {file = "orjson-3.10.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:77d325ed866876c0fa6492598ec01fe30e803272a6e8b10e992288b009cbe149"}, - {file = "orjson-3.10.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ea2c232deedcb605e853ae1db2cc94f7390ac776743b699b50b071b02bea6fe"}, - {file = "orjson-3.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3dcfbede6737fdbef3ce9c37af3fb6142e8e1ebc10336daa05872bfb1d87839c"}, - {file = "orjson-3.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:11748c135f281203f4ee695b7f80bb1358a82a63905f9f0b794769483ea854ad"}, - {file = "orjson-3.10.7-cp313-none-win32.whl", hash = "sha256:a7e19150d215c7a13f39eb787d84db274298d3f83d85463e61d277bbd7f401d2"}, - {file = "orjson-3.10.7-cp313-none-win_amd64.whl", hash = "sha256:eef44224729e9525d5261cc8d28d6b11cafc90e6bd0be2157bde69a52ec83024"}, - {file = "orjson-3.10.7-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6ea2b2258eff652c82652d5e0f02bd5e0463a6a52abb78e49ac288827aaa1469"}, - {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:430ee4d85841e1483d487e7b81401785a5dfd69db5de01314538f31f8fbf7ee1"}, - {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4b6146e439af4c2472c56f8540d799a67a81226e11992008cb47e1267a9b3225"}, - {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:084e537806b458911137f76097e53ce7bf5806dda33ddf6aaa66a028f8d43a23"}, - {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4829cf2195838e3f93b70fd3b4292156fc5e097aac3739859ac0dcc722b27ac0"}, - {file = "orjson-3.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1193b2416cbad1a769f868b1749535d5da47626ac29445803dae7cc64b3f5c98"}, - {file = "orjson-3.10.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:4e6c3da13e5a57e4b3dca2de059f243ebec705857522f188f0180ae88badd354"}, - {file = "orjson-3.10.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c31008598424dfbe52ce8c5b47e0752dca918a4fdc4a2a32004efd9fab41d866"}, - {file = "orjson-3.10.7-cp38-none-win32.whl", hash = "sha256:7122a99831f9e7fe977dc45784d3b2edc821c172d545e6420c375e5a935f5a1c"}, - {file = "orjson-3.10.7-cp38-none-win_amd64.whl", hash = "sha256:a763bc0e58504cc803739e7df040685816145a6f3c8a589787084b54ebc9f16e"}, - {file = "orjson-3.10.7-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e76be12658a6fa376fcd331b1ea4e58f5a06fd0220653450f0d415b8fd0fbe20"}, - {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed350d6978d28b92939bfeb1a0570c523f6170efc3f0a0ef1f1df287cd4f4960"}, - {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:144888c76f8520e39bfa121b31fd637e18d4cc2f115727865fdf9fa325b10412"}, - {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09b2d92fd95ad2402188cf51573acde57eb269eddabaa60f69ea0d733e789fe9"}, - {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b24a579123fa884f3a3caadaed7b75eb5715ee2b17ab5c66ac97d29b18fe57f"}, - {file = "orjson-3.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591bcfe7512353bd609875ab38050efe3d55e18934e2f18950c108334b4ff"}, - {file = "orjson-3.10.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f4db56635b58cd1a200b0a23744ff44206ee6aa428185e2b6c4a65b3197abdcd"}, - {file = "orjson-3.10.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0fa5886854673222618638c6df7718ea7fe2f3f2384c452c9ccedc70b4a510a5"}, - {file = "orjson-3.10.7-cp39-none-win32.whl", hash = "sha256:8272527d08450ab16eb405f47e0f4ef0e5ff5981c3d82afe0efd25dcbef2bcd2"}, - {file = "orjson-3.10.7-cp39-none-win_amd64.whl", hash = "sha256:974683d4618c0c7dbf4f69c95a979734bf183d0658611760017f6e70a145af58"}, - {file = "orjson-3.10.7.tar.gz", hash = "sha256:75ef0640403f945f3a1f9f6400686560dbfb0fb5b16589ad62cd477043c4eee3"}, -] - -[[package]] -name = "packaging" -version = "24.1" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, - {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, -] - -[[package]] -name = "pluggy" -version = "1.5.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "pydantic" -version = "2.8.2" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pydantic-2.8.2-py3-none-any.whl", hash = "sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8"}, - {file = "pydantic-2.8.2.tar.gz", hash = "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a"}, -] - -[package.dependencies] -annotated-types = ">=0.4.0" -pydantic-core = "2.20.1" -typing-extensions = [ - {version = ">=4.6.1", markers = "python_version < \"3.13\""}, - {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, -] - -[package.extras] -email = ["email-validator (>=2.0.0)"] - -[[package]] -name = "pydantic-core" -version = "2.20.1" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840"}, - {file = "pydantic_core-2.20.1-cp310-none-win32.whl", hash = "sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250"}, - {file = "pydantic_core-2.20.1-cp310-none-win_amd64.whl", hash = "sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b"}, - {file = "pydantic_core-2.20.1-cp311-none-win32.whl", hash = "sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a"}, - {file = "pydantic_core-2.20.1-cp311-none-win_amd64.whl", hash = "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd"}, - {file = "pydantic_core-2.20.1-cp312-none-win32.whl", hash = "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688"}, - {file = "pydantic_core-2.20.1-cp312-none-win_amd64.whl", hash = "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0"}, - {file = "pydantic_core-2.20.1-cp313-none-win32.whl", hash = "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e"}, - {file = "pydantic_core-2.20.1-cp313-none-win_amd64.whl", hash = "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:4745f4ac52cc6686390c40eaa01d48b18997cb130833154801a442323cc78f91"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8ad4c766d3f33ba8fd692f9aa297c9058970530a32c728a2c4bfd2616d3358b"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41e81317dd6a0127cabce83c0c9c3fbecceae981c8391e6f1dec88a77c8a569a"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04024d270cf63f586ad41fff13fde4311c4fc13ea74676962c876d9577bcc78f"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaad4ff2de1c3823fddf82f41121bdf453d922e9a238642b1dedb33c4e4f98ad"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26ab812fa0c845df815e506be30337e2df27e88399b985d0bb4e3ecfe72df31c"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c5ebac750d9d5f2706654c638c041635c385596caf68f81342011ddfa1e5598"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2aafc5a503855ea5885559eae883978c9b6d8c8993d67766ee73d82e841300dd"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4868f6bd7c9d98904b748a2653031fc9c2f85b6237009d475b1008bfaeb0a5aa"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa2f457b4af386254372dfa78a2eda2563680d982422641a85f271c859df1987"}, - {file = "pydantic_core-2.20.1-cp38-none-win32.whl", hash = "sha256:225b67a1f6d602de0ce7f6c1c3ae89a4aa25d3de9be857999e9124f15dab486a"}, - {file = "pydantic_core-2.20.1-cp38-none-win_amd64.whl", hash = "sha256:6b507132dcfc0dea440cce23ee2182c0ce7aba7054576efc65634f080dbe9434"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b03f7941783b4c4a26051846dea594628b38f6940a2fdc0df00b221aed39314c"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1eedfeb6089ed3fad42e81a67755846ad4dcc14d73698c120a82e4ccf0f1f9f6"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:635fee4e041ab9c479e31edda27fcf966ea9614fff1317e280d99eb3e5ab6fe2"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77bf3ac639c1ff567ae3b47f8d4cc3dc20f9966a2a6dd2311dcc055d3d04fb8a"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ed1b0132f24beeec5a78b67d9388656d03e6a7c837394f99257e2d55b461611"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6514f963b023aeee506678a1cf821fe31159b925c4b76fe2afa94cc70b3222b"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10d4204d8ca33146e761c79f83cc861df20e7ae9f6487ca290a97702daf56006"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d036c7187b9422ae5b262badb87a20a49eb6c5238b2004e96d4da1231badef1"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ebfef07dbe1d93efb94b4700f2d278494e9162565a54f124c404a5656d7ff09"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6b9d9bb600328a1ce523ab4f454859e9d439150abb0906c5a1983c146580ebab"}, - {file = "pydantic_core-2.20.1-cp39-none-win32.whl", hash = "sha256:784c1214cb6dd1e3b15dd8b91b9a53852aed16671cc3fbe4786f4f1db07089e2"}, - {file = "pydantic_core-2.20.1-cp39-none-win_amd64.whl", hash = "sha256:d2fe69c5434391727efa54b47a1e7986bb0186e72a41b203df8f5b0a19a4f669"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7"}, - {file = "pydantic_core-2.20.1.tar.gz", hash = "sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pytest" -version = "7.4.4" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} - -[package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "pytest-asyncio" -version = "0.21.2" -description = "Pytest support for asyncio" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pytest_asyncio-0.21.2-py3-none-any.whl", hash = "sha256:ab664c88bb7998f711d8039cacd4884da6430886ae8bbd4eded552ed2004f16b"}, - {file = "pytest_asyncio-0.21.2.tar.gz", hash = "sha256:d67738fc232b94b326b9d060750beb16e0074210b98dd8b58a5239fa2a154f45"}, -] - -[package.dependencies] -pytest = ">=7.0.0" - -[package.extras] -docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] -testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"] - -[[package]] -name = "pytest-mock" -version = "3.14.0" -description = "Thin-wrapper around the mock package for easier use with pytest" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, - {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, -] - -[package.dependencies] -pytest = ">=6.2.5" - -[package.extras] -dev = ["pre-commit", "pytest-asyncio", "tox"] - -[[package]] -name = "pytest-watcher" -version = "0.3.5" -description = "Automatically rerun your tests on file modifications" -optional = false -python-versions = ">=3.7.0,<4.0.0" -files = [ - {file = "pytest_watcher-0.3.5-py3-none-any.whl", hash = "sha256:af00ca52c7be22dc34c0fd3d7ffef99057207a73b05dc5161fe3b2fe91f58130"}, - {file = "pytest_watcher-0.3.5.tar.gz", hash = "sha256:8896152460ba2b1a8200c12117c6611008ec96c8b2d811f0a05ab8a82b043ff8"}, -] - -[package.dependencies] -tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version < \"3.11\""} -watchdog = ">=2.0.0" - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -files = [ - {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, - {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "pyyaml" -version = "6.0.2" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, - {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, - {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, - {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, - {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, - {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, - {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, - {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, - {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, - {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, - {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, - {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, - {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, - {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, - {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, - {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, - {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, -] - -[[package]] -name = "requests" -version = "2.32.3" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.8" -files = [ - {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, - {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "ruff" -version = "0.5.7" -description = "An extremely fast Python linter and code formatter, written in Rust." -optional = false -python-versions = ">=3.7" -files = [ - {file = "ruff-0.5.7-py3-none-linux_armv6l.whl", hash = "sha256:548992d342fc404ee2e15a242cdbea4f8e39a52f2e7752d0e4cbe88d2d2f416a"}, - {file = "ruff-0.5.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:00cc8872331055ee017c4f1071a8a31ca0809ccc0657da1d154a1d2abac5c0be"}, - {file = "ruff-0.5.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:eaf3d86a1fdac1aec8a3417a63587d93f906c678bb9ed0b796da7b59c1114a1e"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a01c34400097b06cf8a6e61b35d6d456d5bd1ae6961542de18ec81eaf33b4cb8"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcc8054f1a717e2213500edaddcf1dbb0abad40d98e1bd9d0ad364f75c763eea"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f70284e73f36558ef51602254451e50dd6cc479f8b6f8413a95fcb5db4a55fc"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:a78ad870ae3c460394fc95437d43deb5c04b5c29297815a2a1de028903f19692"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9ccd078c66a8e419475174bfe60a69adb36ce04f8d4e91b006f1329d5cd44bcf"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e31c9bad4ebf8fdb77b59cae75814440731060a09a0e0077d559a556453acbb"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d796327eed8e168164346b769dd9a27a70e0298d667b4ecee6877ce8095ec8e"}, - {file = "ruff-0.5.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4a09ea2c3f7778cc635e7f6edf57d566a8ee8f485f3c4454db7771efb692c499"}, - {file = "ruff-0.5.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a36d8dcf55b3a3bc353270d544fb170d75d2dff41eba5df57b4e0b67a95bb64e"}, - {file = "ruff-0.5.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9369c218f789eefbd1b8d82a8cf25017b523ac47d96b2f531eba73770971c9e5"}, - {file = "ruff-0.5.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b88ca3db7eb377eb24fb7c82840546fb7acef75af4a74bd36e9ceb37a890257e"}, - {file = "ruff-0.5.7-py3-none-win32.whl", hash = "sha256:33d61fc0e902198a3e55719f4be6b375b28f860b09c281e4bdbf783c0566576a"}, - {file = "ruff-0.5.7-py3-none-win_amd64.whl", hash = "sha256:083bbcbe6fadb93cd86709037acc510f86eed5a314203079df174c40bbbca6b3"}, - {file = "ruff-0.5.7-py3-none-win_arm64.whl", hash = "sha256:2dca26154ff9571995107221d0aeaad0e75a77b5a682d6236cf89a58c70b76f4"}, - {file = "ruff-0.5.7.tar.gz", hash = "sha256:8dfc0a458797f5d9fb622dd0efc52d796f23f0a1493a9527f4e49a550ae9a7e5"}, -] - -[[package]] -name = "sentencepiece" -version = "0.2.0" -description = "SentencePiece python wrapper" -optional = false -python-versions = "*" -files = [ - {file = "sentencepiece-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:188779e1298a1c8b8253c7d3ad729cb0a9891e5cef5e5d07ce4592c54869e227"}, - {file = "sentencepiece-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bed9cf85b296fa2b76fc2547b9cbb691a523864cebaee86304c43a7b4cb1b452"}, - {file = "sentencepiece-0.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d7b67e724bead13f18db6e1d10b6bbdc454af574d70efbb36f27d90387be1ca3"}, - {file = "sentencepiece-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fde4b08cfe237be4484c6c7c2e2c75fb862cfeab6bd5449ce4caeafd97b767a"}, - {file = "sentencepiece-0.2.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c378492056202d1c48a4979650981635fd97875a00eabb1f00c6a236b013b5e"}, - {file = "sentencepiece-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1380ce6540a368de2ef6d7e6ba14ba8f3258df650d39ba7d833b79ee68a52040"}, - {file = "sentencepiece-0.2.0-cp310-cp310-win32.whl", hash = "sha256:a1151d6a6dd4b43e552394aed0edfe9292820272f0194bd56c7c1660a0c06c3d"}, - {file = "sentencepiece-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:d490142b0521ef22bc1085f061d922a2a6666175bb6b42e588ff95c0db6819b2"}, - {file = "sentencepiece-0.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:17982700c4f6dbb55fa3594f3d7e5dd1c8659a274af3738e33c987d2a27c9d5c"}, - {file = "sentencepiece-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7c867012c0e8bcd5bdad0f791609101cb5c66acb303ab3270218d6debc68a65e"}, - {file = "sentencepiece-0.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7fd6071249c74f779c5b27183295b9202f8dedb68034e716784364443879eaa6"}, - {file = "sentencepiece-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27f90c55a65013cbb8f4d7aab0599bf925cde4adc67ae43a0d323677b5a1c6cb"}, - {file = "sentencepiece-0.2.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b293734059ef656dcd65be62ff771507bea8fed0a711b6733976e1ed3add4553"}, - {file = "sentencepiece-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e58b47f933aca74c6a60a79dcb21d5b9e47416256c795c2d58d55cec27f9551d"}, - {file = "sentencepiece-0.2.0-cp311-cp311-win32.whl", hash = "sha256:c581258cf346b327c62c4f1cebd32691826306f6a41d8c4bec43b010dee08e75"}, - {file = "sentencepiece-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:0993dbc665f4113017892f1b87c3904a44d0640eda510abcacdfb07f74286d36"}, - {file = "sentencepiece-0.2.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ea5f536e32ea8ec96086ee00d7a4a131ce583a1b18d130711707c10e69601cb2"}, - {file = "sentencepiece-0.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d0cb51f53b6aae3c36bafe41e86167c71af8370a039f542c43b0cce5ef24a68c"}, - {file = "sentencepiece-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3212121805afc58d8b00ab4e7dd1f8f76c203ddb9dc94aa4079618a31cf5da0f"}, - {file = "sentencepiece-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a3149e3066c2a75e0d68a43eb632d7ae728c7925b517f4c05c40f6f7280ce08"}, - {file = "sentencepiece-0.2.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:632f3594d3e7ac8b367bca204cb3fd05a01d5b21455acd097ea4c0e30e2f63d7"}, - {file = "sentencepiece-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f295105c6bdbb05bd5e1b0cafbd78ff95036f5d3641e7949455a3f4e5e7c3109"}, - {file = "sentencepiece-0.2.0-cp312-cp312-win32.whl", hash = "sha256:fb89f811e5efd18bab141afc3fea3de141c3f69f3fe9e898f710ae7fe3aab251"}, - {file = "sentencepiece-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:7a673a72aab81fef5ebe755c6e0cc60087d1f3a4700835d40537183c1703a45f"}, - {file = "sentencepiece-0.2.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4547683f330289ec4f093027bfeb87f9ef023b2eb6f879fdc4a8187c7e0ffb90"}, - {file = "sentencepiece-0.2.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7cd6175f7eaec7142d2bf6f6597ce7db4c9ac89acf93fcdb17410c3a8b781eeb"}, - {file = "sentencepiece-0.2.0-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:859ba1acde782609a0910a26a60e16c191a82bf39b5621107552c0cd79fad00f"}, - {file = "sentencepiece-0.2.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcbbef6cc277f8f18f36959e305f10b1c620442d75addc79c21d7073ae581b50"}, - {file = "sentencepiece-0.2.0-cp36-cp36m-win32.whl", hash = "sha256:536b934e244829e3fe6c4f198652cd82da48adb9aa145c9f00889542726dee3d"}, - {file = "sentencepiece-0.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:0a91aaa3c769b52440df56fafda683b3aa48e3f2169cf7ee5b8c8454a7f3ae9b"}, - {file = "sentencepiece-0.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:787e480ca4c1d08c9985a7eb1eae4345c107729c99e9b5a9a00f2575fc7d4b4b"}, - {file = "sentencepiece-0.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4d158189eb2ecffea3a51edf6d25e110b3678ec47f1a40f2d541eafbd8f6250"}, - {file = "sentencepiece-0.2.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1e5ca43013e8935f25457a4fca47e315780172c3e821b4b13a890668911c792"}, - {file = "sentencepiece-0.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7140d9e5a74a0908493bb4a13f1f16a401297bd755ada4c707e842fbf6f0f5bf"}, - {file = "sentencepiece-0.2.0-cp37-cp37m-win32.whl", hash = "sha256:6cf333625234f247ab357b0bd9836638405ea9082e1543d5b8408f014979dcbf"}, - {file = "sentencepiece-0.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ff88712338b01031910e8e61e7239aff3ce8869ee31a47df63cb38aadd591bea"}, - {file = "sentencepiece-0.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20813a68d4c221b1849c62c30e1281ea81687894d894b8d4a0f4677d9311e0f5"}, - {file = "sentencepiece-0.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:926ef920ae2e8182db31d3f5d081ada57804e3e1d3a8c4ef8b117f9d9fb5a945"}, - {file = "sentencepiece-0.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:89f65f69636b7e9c015b79dff9c9985a9bc7d19ded6f79ef9f1ec920fdd73ecf"}, - {file = "sentencepiece-0.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f67eae0dbe6f2d7d6ba50a354623d787c99965f068b81e145d53240198021b0"}, - {file = "sentencepiece-0.2.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:98501e075f35dd1a1d5a20f65be26839fcb1938752ec61539af008a5aa6f510b"}, - {file = "sentencepiece-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3d1d2cc4882e8d6a1adf9d5927d7716f80617fc693385661caff21888972269"}, - {file = "sentencepiece-0.2.0-cp38-cp38-win32.whl", hash = "sha256:b99a308a2e5e569031ab164b74e6fab0b6f37dfb493c32f7816225f4d411a6dd"}, - {file = "sentencepiece-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:cdb701eec783d3ec86b7cd4c763adad8eaf6b46db37ee1c36e5e6c44b3fe1b5f"}, - {file = "sentencepiece-0.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1e0f9c4d0a6b0af59b613175f019916e28ade076e21242fd5be24340d8a2f64a"}, - {file = "sentencepiece-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:298f21cc1366eb60311aedba3169d30f885c363ddbf44214b0a587d2908141ad"}, - {file = "sentencepiece-0.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3f1ec95aa1e5dab11f37ac7eff190493fd87770f7a8b81ebc9dd768d1a3c8704"}, - {file = "sentencepiece-0.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b06b70af54daa4b4904cbb90b4eb6d35c9f3252fdc86c9c32d5afd4d30118d8"}, - {file = "sentencepiece-0.2.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22e37bac44dd6603388cb598c64ff7a76e41ca774646f21c23aadfbf5a2228ab"}, - {file = "sentencepiece-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0461324897735512a32d222e3d886e24ad6a499761952b6bda2a9ee6e4313ea5"}, - {file = "sentencepiece-0.2.0-cp39-cp39-win32.whl", hash = "sha256:38aed822fb76435fa1f12185f10465a94ab9e51d5e8a9159e9a540ce926f0ffd"}, - {file = "sentencepiece-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:d8cf876516548b5a1d6ac4745d8b554f5c07891d55da557925e5c13ff0b4e6ad"}, - {file = "sentencepiece-0.2.0.tar.gz", hash = "sha256:a52c19171daaf2e697dc6cbe67684e0fa341b1248966f6aebb541de654d15843"}, -] - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] - -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - -[[package]] -name = "syrupy" -version = "4.7.1" -description = "Pytest Snapshot Test Utility" -optional = false -python-versions = ">=3.8.1" -files = [ - {file = "syrupy-4.7.1-py3-none-any.whl", hash = "sha256:be002267a512a4bedddfae2e026c93df1ea928ae10baadc09640516923376d41"}, - {file = "syrupy-4.7.1.tar.gz", hash = "sha256:f9d4485f3f27d0e5df6ed299cac6fa32eb40a441915d988e82be5a4bdda335c8"}, -] - -[package.dependencies] -pytest = ">=7.0.0,<9.0.0" - -[[package]] -name = "tenacity" -version = "8.5.0" -description = "Retry code until it succeeds" -optional = false -python-versions = ">=3.8" -files = [ - {file = "tenacity-8.5.0-py3-none-any.whl", hash = "sha256:b594c2a5945830c267ce6b79a166228323ed52718f30302c1359836112346687"}, - {file = "tenacity-8.5.0.tar.gz", hash = "sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78"}, -] - -[package.extras] -doc = ["reno", "sphinx"] -test = ["pytest", "tornado (>=4.5)", "typeguard"] - -[[package]] -name = "tokenizers" -version = "0.20.0" -description = "" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tokenizers-0.20.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:6cff5c5e37c41bc5faa519d6f3df0679e4b37da54ea1f42121719c5e2b4905c0"}, - {file = "tokenizers-0.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:62a56bf75c27443432456f4ca5ca055befa95e25be8a28141cc495cac8ae4d6d"}, - {file = "tokenizers-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68cc7de6a63f09c4a86909c2597b995aa66e19df852a23aea894929c74369929"}, - {file = "tokenizers-0.20.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:053c37ecee482cc958fdee53af3c6534286a86f5d35aac476f7c246830e53ae5"}, - {file = "tokenizers-0.20.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3d7074aaabc151a6363fa03db5493fc95b423b2a1874456783989e96d541c7b6"}, - {file = "tokenizers-0.20.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a11435780f2acd89e8fefe5e81cecf01776f6edb9b3ac95bcb76baee76b30b90"}, - {file = "tokenizers-0.20.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9a81cd2712973b007d84268d45fc3f6f90a79c31dfe7f1925e6732f8d2959987"}, - {file = "tokenizers-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7dfd796ab9d909f76fb93080e1c7c8309f196ecb316eb130718cd5e34231c69"}, - {file = "tokenizers-0.20.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8029ad2aa8cb00605c9374566034c1cc1b15130713e0eb5afcef6cface8255c9"}, - {file = "tokenizers-0.20.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ca4d54260ebe97d59dfa9a30baa20d0c4dd9137d99a8801700055c561145c24e"}, - {file = "tokenizers-0.20.0-cp310-none-win32.whl", hash = "sha256:95ee16b57cec11b86a7940174ec5197d506439b0f415ab3859f254b1dffe9df0"}, - {file = "tokenizers-0.20.0-cp310-none-win_amd64.whl", hash = "sha256:0a61a11e93eeadbf02aea082ffc75241c4198e0608bbbac4f65a9026851dcf37"}, - {file = "tokenizers-0.20.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6636b798b3c4d6c9b1af1a918bd07c867808e5a21c64324e95318a237e6366c3"}, - {file = "tokenizers-0.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ec603e42eaf499ffd58b9258162add948717cf21372458132f14e13a6bc7172"}, - {file = "tokenizers-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cce124264903a8ea6f8f48e1cc7669e5ef638c18bd4ab0a88769d5f92debdf7f"}, - {file = "tokenizers-0.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07bbeba0231cf8de07aa6b9e33e9779ff103d47042eeeb859a8c432e3292fb98"}, - {file = "tokenizers-0.20.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:06c0ca8397b35d38b83a44a9c6929790c1692957d88541df061cb34d82ebbf08"}, - {file = "tokenizers-0.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ca6557ac3b83d912dfbb1f70ab56bd4b0594043916688e906ede09f42e192401"}, - {file = "tokenizers-0.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a5ad94c9e80ac6098328bee2e3264dbced4c6faa34429994d473f795ec58ef4"}, - {file = "tokenizers-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b5c7f906ee6bec30a9dc20268a8b80f3b9584de1c9f051671cb057dc6ce28f6"}, - {file = "tokenizers-0.20.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:31e087e9ee1b8f075b002bfee257e858dc695f955b43903e1bb4aa9f170e37fe"}, - {file = "tokenizers-0.20.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c3124fb6f3346cb3d8d775375d3b429bf4dcfc24f739822702009d20a4297990"}, - {file = "tokenizers-0.20.0-cp311-none-win32.whl", hash = "sha256:a4bb8b40ba9eefa621fdcabf04a74aa6038ae3be0c614c6458bd91a4697a452f"}, - {file = "tokenizers-0.20.0-cp311-none-win_amd64.whl", hash = "sha256:2b709d371f1fe60a28ef0c5c67815952d455ca7f34dbe7197eaaed3cc54b658e"}, - {file = "tokenizers-0.20.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:15c81a17d0d66f4987c6ca16f4bea7ec253b8c7ed1bb00fdc5d038b1bb56e714"}, - {file = "tokenizers-0.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6a531cdf1fb6dc41c984c785a3b299cb0586de0b35683842a3afbb1e5207f910"}, - {file = "tokenizers-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06caabeb4587f8404e0cd9d40f458e9cba3e815c8155a38e579a74ff3e2a4301"}, - {file = "tokenizers-0.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8768f964f23f5b9f50546c0369c75ab3262de926983888bbe8b98be05392a79c"}, - {file = "tokenizers-0.20.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:626403860152c816f97b649fd279bd622c3d417678c93b4b1a8909b6380b69a8"}, - {file = "tokenizers-0.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9c1b88fa9e5ff062326f4bf82681da5a96fca7104d921a6bd7b1e6fcf224af26"}, - {file = "tokenizers-0.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d7e559436a07dc547f22ce1101f26d8b2fad387e28ec8e7e1e3b11695d681d8"}, - {file = "tokenizers-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e48afb75e50449848964e4a67b0da01261dd3aa8df8daecf10db8fd7f5b076eb"}, - {file = "tokenizers-0.20.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:baf5d0e1ff44710a95eefc196dd87666ffc609fd447c5e5b68272a7c3d342a1d"}, - {file = "tokenizers-0.20.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e5e56df0e8ed23ba60ae3848c3f069a0710c4b197218fe4f89e27eba38510768"}, - {file = "tokenizers-0.20.0-cp312-none-win32.whl", hash = "sha256:ec53e5ecc142a82432f9c6c677dbbe5a2bfee92b8abf409a9ecb0d425ee0ce75"}, - {file = "tokenizers-0.20.0-cp312-none-win_amd64.whl", hash = "sha256:f18661ece72e39c0dfaa174d6223248a15b457dbd4b0fc07809b8e6d3ca1a234"}, - {file = "tokenizers-0.20.0-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:f7065b1084d8d1a03dc89d9aad69bcbc8415d4bc123c367063eb32958cd85054"}, - {file = "tokenizers-0.20.0-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:e5d4069e4714e3f7ba0a4d3d44f9d84a432cd4e4aa85c3d7dd1f51440f12e4a1"}, - {file = "tokenizers-0.20.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:799b808529e54b7e1a36350bda2aeb470e8390e484d3e98c10395cee61d4e3c6"}, - {file = "tokenizers-0.20.0-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f9baa027cc8a281ad5f7725a93c204d7a46986f88edbe8ef7357f40a23fb9c7"}, - {file = "tokenizers-0.20.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:010ec7f3f7a96adc4c2a34a3ada41fa14b4b936b5628b4ff7b33791258646c6b"}, - {file = "tokenizers-0.20.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98d88f06155335b14fd78e32ee28ca5b2eb30fced4614e06eb14ae5f7fba24ed"}, - {file = "tokenizers-0.20.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e13eb000ef540c2280758d1b9cfa5fe424b0424ae4458f440e6340a4f18b2638"}, - {file = "tokenizers-0.20.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fab3cf066ff426f7e6d70435dc28a9ff01b2747be83810e397cba106f39430b0"}, - {file = "tokenizers-0.20.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:39fa3761b30a89368f322e5daf4130dce8495b79ad831f370449cdacfb0c0d37"}, - {file = "tokenizers-0.20.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c8da0fba4d179ddf2607821575998df3c294aa59aa8df5a6646dc64bc7352bce"}, - {file = "tokenizers-0.20.0-cp37-none-win32.whl", hash = "sha256:fada996d6da8cf213f6e3c91c12297ad4f6cdf7a85c2fadcd05ec32fa6846fcd"}, - {file = "tokenizers-0.20.0-cp37-none-win_amd64.whl", hash = "sha256:7d29aad702279e0760c265fcae832e89349078e3418dd329732d4503259fd6bd"}, - {file = "tokenizers-0.20.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:099c68207f3ef0227ecb6f80ab98ea74de559f7b124adc7b17778af0250ee90a"}, - {file = "tokenizers-0.20.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:68012d8a8cddb2eab3880870d7e2086cb359c7f7a2b03f5795044f5abff4e850"}, - {file = "tokenizers-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9253bdd209c6aee168deca7d0e780581bf303e0058f268f9bb06859379de19b6"}, - {file = "tokenizers-0.20.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8f868600ddbcb0545905ed075eb7218a0756bf6c09dae7528ea2f8436ebd2c93"}, - {file = "tokenizers-0.20.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a9643d9c8c5f99b6aba43fd10034f77cc6c22c31f496d2f0ee183047d948fa0"}, - {file = "tokenizers-0.20.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c375c6a889aeab44734028bc65cc070acf93ccb0f9368be42b67a98e1063d3f6"}, - {file = "tokenizers-0.20.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e359f852328e254f070bbd09a19a568421d23388f04aad9f2fb7da7704c7228d"}, - {file = "tokenizers-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d98b01a309d4387f3b1c1dd68a8b8136af50376cf146c1b7e8d8ead217a5be4b"}, - {file = "tokenizers-0.20.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:459f7537119554c2899067dec1ac74a00d02beef6558f4ee2e99513bf6d568af"}, - {file = "tokenizers-0.20.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:392b87ec89452628c045c9f2a88bc2a827f4c79e7d84bc3b72752b74c2581f70"}, - {file = "tokenizers-0.20.0-cp38-none-win32.whl", hash = "sha256:55a393f893d2ed4dd95a1553c2e42d4d4086878266f437b03590d3f81984c4fe"}, - {file = "tokenizers-0.20.0-cp38-none-win_amd64.whl", hash = "sha256:30ffe33c5c2f2aab8e9a3340d0110dd9f7ace7eec7362e20a697802306bd8068"}, - {file = "tokenizers-0.20.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:aa2d4a6fed2a7e3f860c7fc9d48764bb30f2649d83915d66150d6340e06742b8"}, - {file = "tokenizers-0.20.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b5ef0f814084a897e9071fc4a868595f018c5c92889197bdc4bf19018769b148"}, - {file = "tokenizers-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc1e1b791e8c3bf4c4f265f180dadaff1c957bf27129e16fdd5e5d43c2d3762c"}, - {file = "tokenizers-0.20.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b69e55e481459c07885263743a0d3c18d52db19bae8226a19bcca4aaa213fff"}, - {file = "tokenizers-0.20.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4806b4d82e27a2512bc23057b2986bc8b85824914286975b84d8105ff40d03d9"}, - {file = "tokenizers-0.20.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9859e9ef13adf5a473ccab39d31bff9c550606ae3c784bf772b40f615742a24f"}, - {file = "tokenizers-0.20.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef703efedf4c20488a8eb17637b55973745b27997ff87bad88ed499b397d1144"}, - {file = "tokenizers-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6eec0061bab94b1841ab87d10831fdf1b48ebaed60e6d66d66dbe1d873f92bf5"}, - {file = "tokenizers-0.20.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:980f3d0d7e73f845b69087f29a63c11c7eb924c4ad6b358da60f3db4cf24bdb4"}, - {file = "tokenizers-0.20.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7c157550a2f3851b29d7fdc9dc059fcf81ff0c0fc49a1e5173a89d533ed043fa"}, - {file = "tokenizers-0.20.0-cp39-none-win32.whl", hash = "sha256:8a3d2f4d08608ec4f9895ec25b4b36a97f05812543190a5f2c3cd19e8f041e5a"}, - {file = "tokenizers-0.20.0-cp39-none-win_amd64.whl", hash = "sha256:d90188d12afd0c75e537f9a1d92f9c7375650188ee4f48fdc76f9e38afbd2251"}, - {file = "tokenizers-0.20.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d68e15f1815357b059ec266062340c343ea7f98f7f330602df81ffa3474b6122"}, - {file = "tokenizers-0.20.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:23f9ecec637b9bc80da5f703808d29ed5329e56b5aa8d791d1088014f48afadc"}, - {file = "tokenizers-0.20.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f830b318ee599e3d0665b3e325f85bc75ee2d2ca6285f52e439dc22b64691580"}, - {file = "tokenizers-0.20.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3dc750def789cb1de1b5a37657919545e1d9ffa667658b3fa9cb7862407a1b8"}, - {file = "tokenizers-0.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e26e6c755ae884c2ea6135cd215bdd0fccafe4ee62405014b8c3cd19954e3ab9"}, - {file = "tokenizers-0.20.0-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:a1158c7174f427182e08baa2a8ded2940f2b4a3e94969a85cc9cfd16004cbcea"}, - {file = "tokenizers-0.20.0-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:6324826287a3fc198898d3dcf758fe4a8479e42d6039f4c59e2cedd3cf92f64e"}, - {file = "tokenizers-0.20.0-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7d8653149405bb0c16feaf9cfee327fdb6aaef9dc2998349fec686f35e81c4e2"}, - {file = "tokenizers-0.20.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8a2dc1e402a155e97309287ca085c80eb1b7fab8ae91527d3b729181639fa51"}, - {file = "tokenizers-0.20.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07bef67b20aa6e5f7868c42c7c5eae4d24f856274a464ae62e47a0f2cccec3da"}, - {file = "tokenizers-0.20.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da06e397182ff53789c506c7833220c192952c57e1581a53f503d8d953e2d67e"}, - {file = "tokenizers-0.20.0-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:302f7e11a14814028b7fc88c45a41f1bbe9b5b35fd76d6869558d1d1809baa43"}, - {file = "tokenizers-0.20.0-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:055ec46e807b875589dfbe3d9259f9a6ee43394fb553b03b3d1e9541662dbf25"}, - {file = "tokenizers-0.20.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e3144b8acebfa6ae062e8f45f7ed52e4b50fb6c62f93afc8871b525ab9fdcab3"}, - {file = "tokenizers-0.20.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b52aa3fd14b2a07588c00a19f66511cff5cca8f7266ca3edcdd17f3512ad159f"}, - {file = "tokenizers-0.20.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b8cf52779ffc5d4d63a0170fbeb512372bad0dd014ce92bbb9149756c831124"}, - {file = "tokenizers-0.20.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:983a45dd11a876124378dae71d6d9761822199b68a4c73f32873d8cdaf326a5b"}, - {file = "tokenizers-0.20.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df6b819c9a19831ebec581e71a7686a54ab45d90faf3842269a10c11d746de0c"}, - {file = "tokenizers-0.20.0-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e738cfd80795fcafcef89c5731c84b05638a4ab3f412f97d5ed7765466576eb1"}, - {file = "tokenizers-0.20.0-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:c8842c7be2fadb9c9edcee233b1b7fe7ade406c99b0973f07439985c1c1d0683"}, - {file = "tokenizers-0.20.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e47a82355511c373a4a430c4909dc1e518e00031207b1fec536c49127388886b"}, - {file = "tokenizers-0.20.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:9afbf359004551179a5db19424180c81276682773cff2c5d002f6eaaffe17230"}, - {file = "tokenizers-0.20.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a07eaa8799a92e6af6f472c21a75bf71575de2af3c0284120b7a09297c0de2f3"}, - {file = "tokenizers-0.20.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0994b2e5fc53a301071806bc4303e4bc3bdc3f490e92a21338146a36746b0872"}, - {file = "tokenizers-0.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b6466e0355b603d10e3cc3d282d350b646341b601e50969464a54939f9848d0"}, - {file = "tokenizers-0.20.0-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:1e86594c2a433cb1ea09cfbe596454448c566e57ee8905bd557e489d93e89986"}, - {file = "tokenizers-0.20.0-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3e14cdef1efa96ecead6ea64a891828432c3ebba128bdc0596e3059fea104ef3"}, - {file = "tokenizers-0.20.0.tar.gz", hash = "sha256:39d7acc43f564c274085cafcd1dae9d36f332456de1a31970296a6b8da4eac8d"}, -] - -[package.dependencies] -huggingface-hub = ">=0.16.4,<1.0" - -[package.extras] -dev = ["tokenizers[testing]"] -docs = ["setuptools-rust", "sphinx", "sphinx-rtd-theme"] -testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests", "ruff"] - -[[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] - -[[package]] -name = "tqdm" -version = "4.66.5" -description = "Fast, Extensible Progress Meter" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tqdm-4.66.5-py3-none-any.whl", hash = "sha256:90279a3770753eafc9194a0364852159802111925aa30eb3f9d85b0e805ac7cd"}, - {file = "tqdm-4.66.5.tar.gz", hash = "sha256:e1020aef2e5096702d8a025ac7d16b1577279c9d63f8375b63083e9a5f0fcbad"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[package.extras] -dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] -notebook = ["ipywidgets (>=6)"] -slack = ["slack-sdk"] -telegram = ["requests"] - -[[package]] -name = "typing-extensions" -version = "4.12.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, -] - -[[package]] -name = "urllib3" -version = "2.2.2" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.8" -files = [ - {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, - {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "watchdog" -version = "4.0.2" -description = "Filesystem events monitoring" -optional = false -python-versions = ">=3.8" -files = [ - {file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ede7f010f2239b97cc79e6cb3c249e72962404ae3865860855d5cbe708b0fd22"}, - {file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a2cffa171445b0efa0726c561eca9a27d00a1f2b83846dbd5a4f639c4f8ca8e1"}, - {file = "watchdog-4.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c50f148b31b03fbadd6d0b5980e38b558046b127dc483e5e4505fcef250f9503"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7c7d4bf585ad501c5f6c980e7be9c4f15604c7cc150e942d82083b31a7548930"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:914285126ad0b6eb2258bbbcb7b288d9dfd655ae88fa28945be05a7b475a800b"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:984306dc4720da5498b16fc037b36ac443816125a3705dfde4fd90652d8028ef"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1cdcfd8142f604630deef34722d695fb455d04ab7cfe9963055df1fc69e6727a"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d7ab624ff2f663f98cd03c8b7eedc09375a911794dfea6bf2a359fcc266bff29"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:132937547a716027bd5714383dfc40dc66c26769f1ce8a72a859d6a48f371f3a"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd67c7df93eb58f360c43802acc945fa8da70c675b6fa37a241e17ca698ca49b"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcfd02377be80ef3b6bc4ce481ef3959640458d6feaae0bd43dd90a43da90a7d"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:980b71510f59c884d684b3663d46e7a14b457c9611c481e5cef08f4dd022eed7"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:aa160781cafff2719b663c8a506156e9289d111d80f3387cf3af49cedee1f040"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f6ee8dedd255087bc7fe82adf046f0b75479b989185fb0bdf9a98b612170eac7"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0b4359067d30d5b864e09c8597b112fe0a0a59321a0f331498b013fb097406b4"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:770eef5372f146997638d737c9a3c597a3b41037cfbc5c41538fc27c09c3a3f9"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eeea812f38536a0aa859972d50c76e37f4456474b02bd93674d1947cf1e39578"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b2c45f6e1e57ebb4687690c05bc3a2c1fb6ab260550c4290b8abb1335e0fd08b"}, - {file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:10b6683df70d340ac3279eff0b2766813f00f35a1d37515d2c99959ada8f05fa"}, - {file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7c739888c20f99824f7aa9d31ac8a97353e22d0c0e54703a547a218f6637eb3"}, - {file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c100d09ac72a8a08ddbf0629ddfa0b8ee41740f9051429baa8e31bb903ad7508"}, - {file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f5315a8c8dd6dd9425b974515081fc0aadca1d1d61e078d2246509fd756141ee"}, - {file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:2d468028a77b42cc685ed694a7a550a8d1771bb05193ba7b24006b8241a571a1"}, - {file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f15edcae3830ff20e55d1f4e743e92970c847bcddc8b7509bcd172aa04de506e"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:936acba76d636f70db8f3c66e76aa6cb5136a936fc2a5088b9ce1c7a3508fc83"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_armv7l.whl", hash = "sha256:e252f8ca942a870f38cf785aef420285431311652d871409a64e2a0a52a2174c"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_i686.whl", hash = "sha256:0e83619a2d5d436a7e58a1aea957a3c1ccbf9782c43c0b4fed80580e5e4acd1a"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64.whl", hash = "sha256:88456d65f207b39f1981bf772e473799fcdc10801062c36fd5ad9f9d1d463a73"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:32be97f3b75693a93c683787a87a0dc8db98bb84701539954eef991fb35f5fbc"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:c82253cfc9be68e3e49282831afad2c1f6593af80c0daf1287f6a92657986757"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c0b14488bd336c5b1845cee83d3e631a1f8b4e9c5091ec539406e4a324f882d8"}, - {file = "watchdog-4.0.2-py3-none-win32.whl", hash = "sha256:0d8a7e523ef03757a5aa29f591437d64d0d894635f8a50f370fe37f913ce4e19"}, - {file = "watchdog-4.0.2-py3-none-win_amd64.whl", hash = "sha256:c344453ef3bf875a535b0488e3ad28e341adbd5a9ffb0f7d62cefacc8824ef2b"}, - {file = "watchdog-4.0.2-py3-none-win_ia64.whl", hash = "sha256:baececaa8edff42cd16558a639a9b0ddf425f93d892e8392a56bf904f5eff22c"}, - {file = "watchdog-4.0.2.tar.gz", hash = "sha256:b4dfbb6c49221be4535623ea4474a4d6ee0a9cef4a80b20c28db4d858b64e270"}, -] - -[package.extras] -watchmedo = ["PyYAML (>=3.10)"] - -[metadata] -lock-version = "2.0" -python-versions = ">=3.8.1,<4.0" -content-hash = "32e1777e151eef2eb3775c4f1707ec4e80241a08fd4beed2d60a36f58d68dfea" diff --git a/libs/partners/ai21/pyproject.toml b/libs/partners/ai21/pyproject.toml deleted file mode 100644 index eace5216fa1..00000000000 --- a/libs/partners/ai21/pyproject.toml +++ /dev/null @@ -1,90 +0,0 @@ -[build-system] -requires = [ "poetry-core>=1.0.0",] -build-backend = "poetry.core.masonry.api" - -[tool.poetry] -name = "langchain-ai21" -version = "0.1.8" -description = "An integration package connecting AI21 and LangChain" -authors = [] -readme = "README.md" -repository = "https://github.com/langchain-ai/langchain" -license = "MIT" - -[tool.mypy] -disallow_untyped_defs = "True" - -[tool.poetry.urls] -"Source Code" = "https://github.com/langchain-ai/langchain/tree/master/libs/partners/ai21" -"Release Notes" = "https://github.com/langchain-ai/langchain/releases?q=tag%3A%22langchain-ai21%3D%3D0%22&expanded=true" - -[tool.poetry.dependencies] -python = ">=3.8.1,<4.0" -langchain-core = "^0.2.4" -langchain-text-splitters = "^0.2.0" -ai21 = "^2.14.1" - -[tool.ruff.lint] -select = [ "E", "F", "I",] - -[tool.coverage.run] -omit = [ "tests/*",] - -[tool.pytest.ini_options] -addopts = "--snapshot-warn-unused --strict-markers --strict-config --durations=5" -markers = [ "requires: mark tests as requiring a specific library", "asyncio: mark tests as requiring asyncio", "compile: mark placeholder test used to compile integration tests without running them", "scheduled: mark tests to run in scheduled testing",] -asyncio_mode = "auto" - -[tool.poetry.group.test] -optional = true - -[tool.poetry.group.codespell] -optional = true - -[tool.poetry.group.test_integration] -optional = true - -[tool.poetry.group.lint] -optional = true - -[tool.poetry.group.dev] -optional = true - -[tool.poetry.group.test.dependencies] -pytest = "^7.3.0" -freezegun = "^1.2.2" -pytest-mock = "^3.10.0" -syrupy = "^4.0.2" -pytest-watcher = "^0.3.4" -pytest-asyncio = "^0.21.1" - -[tool.poetry.group.codespell.dependencies] -codespell = "^2.2.0" - -[tool.poetry.group.test_integration.dependencies] - -[tool.poetry.group.lint.dependencies] -ruff = "^0.5" - -[tool.poetry.group.typing.dependencies] -mypy = "^1.10" - -[tool.poetry.group.test.dependencies.langchain-core] -path = "../../core" -develop = true - -[tool.poetry.group.test.dependencies.langchain-standard-tests] -path = "../../standard-tests" -develop = true - -[tool.poetry.group.test.dependencies.langchain-text-splitters] -path = "../../text-splitters" -develop = true - -[tool.poetry.group.dev.dependencies.langchain-core] -path = "../../core" -develop = true - -[tool.poetry.group.typing.dependencies.langchain-core] -path = "../../core" -develop = true diff --git a/libs/partners/ai21/scripts/check_imports.py b/libs/partners/ai21/scripts/check_imports.py deleted file mode 100644 index ba8de50118c..00000000000 --- a/libs/partners/ai21/scripts/check_imports.py +++ /dev/null @@ -1,17 +0,0 @@ -import sys -import traceback -from importlib.machinery import SourceFileLoader - -if __name__ == "__main__": - files = sys.argv[1:] - has_failure = False - for file in files: - try: - SourceFileLoader("x", file).load_module() - except Exception: - has_failure = True - print(file) - traceback.print_exc() - print() - - sys.exit(1 if has_failure else 0) diff --git a/libs/partners/ai21/scripts/check_pydantic.sh b/libs/partners/ai21/scripts/check_pydantic.sh deleted file mode 100755 index 06b5bb81ae2..00000000000 --- a/libs/partners/ai21/scripts/check_pydantic.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -# -# This script searches for lines starting with "import pydantic" or "from pydantic" -# in tracked files within a Git repository. -# -# Usage: ./scripts/check_pydantic.sh /path/to/repository - -# Check if a path argument is provided -if [ $# -ne 1 ]; then - echo "Usage: $0 /path/to/repository" - exit 1 -fi - -repository_path="$1" - -# Search for lines matching the pattern within the specified repository -result=$(git -C "$repository_path" grep -E '^import pydantic|^from pydantic') - -# Check if any matching lines were found -if [ -n "$result" ]; then - echo "ERROR: The following lines need to be updated:" - echo "$result" - echo "Please replace the code with an import from langchain_core.pydantic_v1." - echo "For example, replace 'from pydantic import BaseModel'" - echo "with 'from langchain_core.pydantic_v1 import BaseModel'" - exit 1 -fi diff --git a/libs/partners/ai21/scripts/lint_imports.sh b/libs/partners/ai21/scripts/lint_imports.sh deleted file mode 100755 index 695613c7ba8..00000000000 --- a/libs/partners/ai21/scripts/lint_imports.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -set -eu - -# Initialize a variable to keep track of errors -errors=0 - -# make sure not importing from langchain or langchain_experimental -git --no-pager grep '^from langchain\.' . && errors=$((errors+1)) -git --no-pager grep '^from langchain_experimental\.' . && errors=$((errors+1)) - -# Decide on an exit status based on the errors -if [ "$errors" -gt 0 ]; then - exit 1 -else - exit 0 -fi diff --git a/libs/partners/ai21/tests/__init__.py b/libs/partners/ai21/tests/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libs/partners/ai21/tests/integration_tests/__init__.py b/libs/partners/ai21/tests/integration_tests/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libs/partners/ai21/tests/integration_tests/test_chat_models.py b/libs/partners/ai21/tests/integration_tests/test_chat_models.py deleted file mode 100644 index 8f5b72cbb09..00000000000 --- a/libs/partners/ai21/tests/integration_tests/test_chat_models.py +++ /dev/null @@ -1,188 +0,0 @@ -"""Test ChatAI21 chat model.""" - -import pytest -from langchain_core.messages import ( - AIMessageChunk, - HumanMessage, - SystemMessage, - ToolMessage, -) -from langchain_core.outputs import ChatGeneration -from langchain_core.rate_limiters import InMemoryRateLimiter -from langchain_core.tools import tool -from langchain_core.utils.function_calling import convert_to_openai_tool - -from langchain_ai21.chat_models import ChatAI21 -from tests.unit_tests.conftest import ( - J2_CHAT_MODEL_NAME, - JAMBA_1_5_LARGE_CHAT_MODEL_NAME, - JAMBA_1_5_MINI_CHAT_MODEL_NAME, - JAMBA_CHAT_MODEL_NAME, - JAMBA_FAMILY_MODEL_NAMES, -) - -rate_limiter = InMemoryRateLimiter(requests_per_second=0.5) - - -@pytest.mark.parametrize( - ids=[ - "when_j2_model", - "when_jamba_model", - "when_jamba1.5-mini_model", - "when_jamba1.5-large_model", - ], - argnames=["model"], - argvalues=[ - (J2_CHAT_MODEL_NAME,), - (JAMBA_CHAT_MODEL_NAME,), - (JAMBA_1_5_MINI_CHAT_MODEL_NAME,), - (JAMBA_1_5_LARGE_CHAT_MODEL_NAME,), - ], -) -def test_invoke(model: str) -> None: - """Test invoke tokens from AI21.""" - llm = ChatAI21(model=model, rate_limiter=rate_limiter) # type: ignore[call-arg] - - result = llm.invoke("I'm Pickle Rick", config=dict(tags=["foo"])) - assert isinstance(result.content, str) - - -@pytest.mark.parametrize( - ids=[ - "when_j2_model_num_results_is_1", - "when_j2_model_num_results_is_3", - "when_jamba_model_n_is_1", - "when_jamba_model_n_is_3", - "when_jamba1.5_mini_model_n_is_1", - "when_jamba1.5_mini_model_n_is_3", - "when_jamba1.5_large_model_n_is_1", - "when_jamba1.5_large_model_n_is_3", - ], - argnames=["model", "num_results"], - argvalues=[ - (J2_CHAT_MODEL_NAME, 1), - (J2_CHAT_MODEL_NAME, 3), - (JAMBA_CHAT_MODEL_NAME, 1), - (JAMBA_CHAT_MODEL_NAME, 3), - (JAMBA_1_5_MINI_CHAT_MODEL_NAME, 1), - (JAMBA_1_5_MINI_CHAT_MODEL_NAME, 3), - (JAMBA_1_5_LARGE_CHAT_MODEL_NAME, 1), - (JAMBA_1_5_LARGE_CHAT_MODEL_NAME, 3), - ], -) -def test_generation(model: str, num_results: int) -> None: - """Test generation with multiple models and different result counts.""" - # Determine the configuration key based on the model type - config_key = "n" if model in JAMBA_FAMILY_MODEL_NAMES else "num_results" - - # Create the model instance using the appropriate key for the result count - llm = ChatAI21(model=model, rate_limiter=rate_limiter, **{config_key: num_results}) # type: ignore[arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type] - - message = HumanMessage(content="Hello, this is a test. Can you help me please?") - - result = llm.generate([[message]], config=dict(tags=["foo"])) - - for generations in result.generations: - assert len(generations) == num_results - for generation in generations: - assert isinstance(generation, ChatGeneration) - assert isinstance(generation.text, str) - assert generation.text == generation.message.content - - -@pytest.mark.parametrize( - ids=[ - "when_j2_model", - "when_jamba_model", - "when_jamba1.5_mini_model", - "when_jamba1.5_large_model", - ], - argnames=["model"], - argvalues=[ - (J2_CHAT_MODEL_NAME,), - (JAMBA_CHAT_MODEL_NAME,), - (JAMBA_1_5_MINI_CHAT_MODEL_NAME,), - (JAMBA_1_5_LARGE_CHAT_MODEL_NAME,), - ], -) -async def test_ageneration(model: str) -> None: - """Test invoke tokens from AI21.""" - llm = ChatAI21(model=model, rate_limiter=rate_limiter) # type: ignore[call-arg] - message = HumanMessage(content="Hello") - - result = await llm.agenerate([[message], [message]], config=dict(tags=["foo"])) - - for generations in result.generations: - assert len(generations) == 1 - for generation in generations: - assert isinstance(generation, ChatGeneration) - assert isinstance(generation.text, str) - assert generation.text == generation.message.content - - -def test__chat_stream() -> None: - llm = ChatAI21(model="jamba-1.5-mini") # type: ignore[call-arg] - message = HumanMessage(content="What is the meaning of life?") - - for chunk in llm.stream([message]): - assert isinstance(chunk, AIMessageChunk) - assert isinstance(chunk.content, str) - - -def test__j2_chat_stream__should_raise_error() -> None: - llm = ChatAI21(model="j2-ultra") # type: ignore[call-arg] - message = HumanMessage(content="What is the meaning of life?") - - with pytest.raises(NotImplementedError): - for _ in llm.stream([message]): - pass - - -@pytest.mark.parametrize( - ids=[ - "when_jamba1.5_mini_model", - "when_jamba1.5_large_model", - ], - argnames=["model"], - argvalues=[ - (JAMBA_1_5_MINI_CHAT_MODEL_NAME,), - (JAMBA_1_5_LARGE_CHAT_MODEL_NAME,), - ], -) -def test_tool_calls(model: str) -> None: - @tool - def get_weather(location: str, date: str) -> str: - """“Provide the weather for the specified location on the given date.”""" - if location == "New York" and date == "2024-12-05": - return "25 celsius" - return "32 celsius" - - llm = ChatAI21(model=model, temperature=0) # type: ignore[call-arg] - llm_with_tools = llm.bind_tools([convert_to_openai_tool(get_weather)]) - - chat_messages = [ - SystemMessage( - content="You are a helpful assistant. " - "You can use the provided tools " - "to assist with various tasks and provide " - "accurate information" - ), - HumanMessage( - content="What is the forecast for the weather " - "in New York on December 5, 2024?" - ), - ] - - response = llm_with_tools.invoke(chat_messages) - chat_messages.append(response) - assert response.tool_calls is not None # type: ignore[attr-defined] - tool_call = response.tool_calls[0] # type: ignore[attr-defined] - assert tool_call["name"] == "get_weather" - - weather = get_weather.invoke( # type: ignore[attr-defined] - {"location": tool_call["args"]["location"], "date": tool_call["args"]["date"]} - ) - chat_messages.append(ToolMessage(content=weather, tool_call_id=tool_call["id"])) - llm_answer = llm_with_tools.invoke(chat_messages) - content = llm_answer.content.lower() # type: ignore[union-attr] - assert "new york" in content and "25" in content and "celsius" in content diff --git a/libs/partners/ai21/tests/integration_tests/test_compile.py b/libs/partners/ai21/tests/integration_tests/test_compile.py deleted file mode 100644 index 33ecccdfa0f..00000000000 --- a/libs/partners/ai21/tests/integration_tests/test_compile.py +++ /dev/null @@ -1,7 +0,0 @@ -import pytest - - -@pytest.mark.compile -def test_placeholder() -> None: - """Used for compiling integration tests without running any real tests.""" - pass diff --git a/libs/partners/ai21/tests/integration_tests/test_contextual_answers.py b/libs/partners/ai21/tests/integration_tests/test_contextual_answers.py deleted file mode 100644 index 862d8d5d94c..00000000000 --- a/libs/partners/ai21/tests/integration_tests/test_contextual_answers.py +++ /dev/null @@ -1,61 +0,0 @@ -from langchain_core.output_parsers import StrOutputParser -from langchain_core.runnables import Runnable - -from langchain_ai21.contextual_answers import ( - ANSWER_NOT_IN_CONTEXT_RESPONSE, - AI21ContextualAnswers, -) - -context = """ -Albert Einstein German: 14 March 1879 – 18 April 1955) -was a German-born theoretical physicist who is widely held - to be one of the greatest and most influential scientists -""" - - -_GOOD_QUESTION = "When did Albert Einstein born?" -_BAD_QUESTION = "What color is Yoda's light saber?" -_EXPECTED_PARTIAL_RESPONSE = "March 14, 1879" - - -def test_invoke__when_good_question() -> None: - llm = AI21ContextualAnswers() - - response = llm.invoke( - {"context": context, "question": _GOOD_QUESTION}, - config={"metadata": {"name": "I AM A TEST"}}, - ) - - assert response != ANSWER_NOT_IN_CONTEXT_RESPONSE - - -def test_invoke__when_bad_question__should_return_answer_not_in_context() -> None: - llm = AI21ContextualAnswers() - - response = llm.invoke(input={"context": context, "question": _BAD_QUESTION}) - - assert response == ANSWER_NOT_IN_CONTEXT_RESPONSE - - -def test_invoke__when_response_if_no_answer_passed__should_use_it() -> None: - response_if_no_answer_found = "This should be the response" - llm = AI21ContextualAnswers() - - response = llm.invoke( - input={"context": context, "question": _BAD_QUESTION}, - response_if_no_answer_found=response_if_no_answer_found, - ) - - assert response == response_if_no_answer_found - - -def test_invoke_when_used_in_a_simple_chain_with_no_vectorstore() -> None: - tsm = AI21ContextualAnswers() - - chain: Runnable = tsm | StrOutputParser() - - response = chain.invoke( - {"context": context, "question": _GOOD_QUESTION}, - ) - - assert response != ANSWER_NOT_IN_CONTEXT_RESPONSE diff --git a/libs/partners/ai21/tests/integration_tests/test_embeddings.py b/libs/partners/ai21/tests/integration_tests/test_embeddings.py deleted file mode 100644 index 4dac3158af3..00000000000 --- a/libs/partners/ai21/tests/integration_tests/test_embeddings.py +++ /dev/null @@ -1,37 +0,0 @@ -"""Test AI21 embeddings.""" - -from langchain_ai21.embeddings import AI21Embeddings - - -def test_langchain_ai21_embedding_documents() -> None: - """Test AI21 embeddings.""" - documents = ["foo bar"] - embedding = AI21Embeddings() - output = embedding.embed_documents(documents) - assert len(output) == 1 - assert len(output[0]) > 0 - - -def test_langchain_ai21_embedding_query() -> None: - """Test AI21 embeddings.""" - document = "foo bar" - embedding = AI21Embeddings() - output = embedding.embed_query(document) - assert len(output) > 0 - - -def test_langchain_ai21_embedding_documents__with_explicit_chunk_size() -> None: - """Test AI21 embeddings with chunk size passed as an argument.""" - documents = ["foo", "bar"] - embedding = AI21Embeddings() - output = embedding.embed_documents(documents, batch_size=1) - assert len(output) == 2 - assert len(output[0]) > 0 - - -def test_langchain_ai21_embedding_query__with_explicit_chunk_size() -> None: - """Test AI21 embeddings with chunk size passed as an argument.""" - documents = "foo bar" - embedding = AI21Embeddings() - output = embedding.embed_query(documents, batch_size=1) - assert len(output) > 0 diff --git a/libs/partners/ai21/tests/integration_tests/test_llms.py b/libs/partners/ai21/tests/integration_tests/test_llms.py deleted file mode 100644 index 2219f592921..00000000000 --- a/libs/partners/ai21/tests/integration_tests/test_llms.py +++ /dev/null @@ -1,104 +0,0 @@ -"""Test AI21LLM llm.""" - -from langchain_ai21.llms import AI21LLM - -_MODEL_NAME = "j2-mid" - - -def _generate_llm() -> AI21LLM: - """ - Testing AI21LLm using non default parameters with the following parameters - """ - return AI21LLM( - model=_MODEL_NAME, - max_tokens=2, # Use less tokens for a faster response - temperature=0, # for a consistent response - epoch=1, - ) - - -def test_stream() -> None: - """Test streaming tokens from AI21.""" - llm = AI21LLM( - model=_MODEL_NAME, - ) - - for token in llm.stream("I'm Pickle Rick"): - assert isinstance(token, str) - - -async def test_abatch() -> None: - """Test streaming tokens from AI21LLM.""" - llm = AI21LLM( - model=_MODEL_NAME, - ) - - result = await llm.abatch(["I'm Pickle Rick", "I'm not Pickle Rick"]) - for token in result: - assert isinstance(token, str) - - -async def test_abatch_tags() -> None: - """Test batch tokens from AI21LLM.""" - llm = AI21LLM( - model=_MODEL_NAME, - ) - - result = await llm.abatch( - ["I'm Pickle Rick", "I'm not Pickle Rick"], config={"tags": ["foo"]} - ) - for token in result: - assert isinstance(token, str) - - -def test_batch() -> None: - """Test batch tokens from AI21LLM.""" - llm = AI21LLM( - model=_MODEL_NAME, - ) - - result = llm.batch(["I'm Pickle Rick", "I'm not Pickle Rick"]) - for token in result: - assert isinstance(token, str) - - -async def test_ainvoke() -> None: - """Test invoke tokens from AI21LLM.""" - llm = AI21LLM( - model=_MODEL_NAME, - ) - - result = await llm.ainvoke("I'm Pickle Rick", config={"tags": ["foo"]}) - assert isinstance(result, str) - - -def test_invoke() -> None: - """Test invoke tokens from AI21LLM.""" - llm = AI21LLM( - model=_MODEL_NAME, - ) - - result = llm.invoke("I'm Pickle Rick", config=dict(tags=["foo"])) - assert isinstance(result, str) - - -def test__generate() -> None: - llm = _generate_llm() - llm_result = llm.generate( - prompts=["Hey there, my name is Pickle Rick. What is your name?"], - stop=["##"], - ) - - assert len(llm_result.generations) > 0 - assert llm_result.llm_output["token_count"] != 0 # type: ignore - - -async def test__agenerate() -> None: - llm = _generate_llm() - llm_result = await llm.agenerate( - prompts=["Hey there, my name is Pickle Rick. What is your name?"], - stop=["##"], - ) - - assert len(llm_result.generations) > 0 - assert llm_result.llm_output["token_count"] != 0 # type: ignore diff --git a/libs/partners/ai21/tests/integration_tests/test_semantic_text_splitter.py b/libs/partners/ai21/tests/integration_tests/test_semantic_text_splitter.py deleted file mode 100644 index ec3aebd3b10..00000000000 --- a/libs/partners/ai21/tests/integration_tests/test_semantic_text_splitter.py +++ /dev/null @@ -1,130 +0,0 @@ -from ai21 import AI21Client -from langchain_core.documents import Document - -from langchain_ai21 import AI21SemanticTextSplitter - -TEXT = ( - "The original full name of the franchise is Pocket Monsters (ポケットモンスター, " - "Poketto Monsutā), which was abbreviated to " - "Pokemon during development of the original games.\n" - "When the franchise was released internationally, the short form of the title was " - "used, with an acute accent (´) " - "over the e to aid in pronunciation.\n" - "Pokémon refers to both the franchise itself and the creatures within its " - "fictional universe.\n" - "As a noun, it is identical in both the singular and plural, as is every " - "individual species name;[10] it is " - 'grammatically correct to say "one Pokémon" and "many Pokémon", as well ' - 'as "one Pikachu" and "many Pikachu".\n' - "In English, Pokémon may be pronounced either /'powkɛmon/ (poe-keh-mon) or " - "/'powkɪmon/ (poe-key-mon).\n" - "The Pokémon franchise is set in a world in which humans coexist with creatures " - "known as Pokémon.\n" - "Pokémon Red and Blue contain 151 Pokémon species, with new ones being introduced " - "in subsequent games; as of December 2023, 1,025 Pokémon species have been " - "introduced.\n[b] Most Pokémon are inspired by real-world animals;[12] for example," - "Pikachu are a yellow mouse-like species[13] with lightning bolt-shaped tails[14] " - "that possess electrical abilities.[15]\nThe player character takes the role of a " - "Pokémon Trainer.\nThe Trainer has three primary goals: travel and explore the " - "Pokémon world; discover and catch each Pokémon species in order to complete their" - "Pokédex; and train a team of up to six Pokémon at a time and have them engage " - "in battles.\nMost Pokémon can be caught with spherical devices known as Poké " - "Balls.\nOnce the opposing Pokémon is sufficiently weakened, the Trainer throws " - "the Poké Ball against the Pokémon, which is then transformed into a form of " - "energy and transported into the device.\nOnce the catch is successful, " - "the Pokémon is tamed and is under the Trainer's command from then on.\n" - "If the Poké Ball is thrown again, the Pokémon re-materializes into its " - "original state.\nThe Trainer's Pokémon can engage in battles against opposing " - "Pokémon, including those in the wild or owned by other Trainers.\nBecause the " - "franchise is aimed at children, these battles are never presented as overtly " - "violent and contain no blood or gore.[I]\nPokémon never die in battle, instead " - "fainting upon being defeated.[20][21][22]\nAfter a Pokémon wins a battle, it " - "gains experience and becomes stronger.[23] After gaining a certain amount of " - "experience points, its level increases, as well as one or more of its " - "statistics.\nAs its level increases, the Pokémon can learn new offensive " - "and defensive moves to use in battle.[24][25] Furthermore, many species can " - "undergo a form of spontaneous metamorphosis called Pokémon evolution, and " - "transform into stronger forms.[26] Most Pokémon will evolve at a certain level, " - "while others evolve through different means, such as exposure to a certain " - "item.[27]\n" -) - - -def test_split_text_to_document() -> None: - segmentation = AI21SemanticTextSplitter() - segments = segmentation.split_text_to_documents(source=TEXT) - assert len(segments) > 0 - for segment in segments: - assert segment.page_content is not None - assert segment.metadata is not None - - -def test_split_text() -> None: - segmentation = AI21SemanticTextSplitter() - segments = segmentation.split_text(source=TEXT) - assert len(segments) > 0 - - -def test_split_text__when_chunk_size_is_large__should_merge_segments() -> None: - segmentation_no_merge = AI21SemanticTextSplitter() - segments_no_merge = segmentation_no_merge.split_text(source=TEXT) - segmentation_merge = AI21SemanticTextSplitter(chunk_size=1000) - segments_merge = segmentation_merge.split_text(source=TEXT) - # Assert that a merge did happen - assert len(segments_no_merge) > len(segments_merge) - reconstructed_text_merged = "".join(segments_merge) - reconstructed_text_non_merged = "".join(segments_no_merge) - # Assert that the merge did not change the content - assert reconstructed_text_merged == reconstructed_text_non_merged - - -def test_split_text__chunk_size_is_too_small__should_return_non_merged_segments() -> ( - None -): - segmentation_no_merge = AI21SemanticTextSplitter() - segments_no_merge = segmentation_no_merge.split_text(source=TEXT) - segmentation_merge = AI21SemanticTextSplitter(chunk_size=10) - segments_merge = segmentation_merge.split_text(source=TEXT) - # Assert that a merge did happen - assert len(segments_no_merge) == len(segments_merge) - reconstructed_text_merged = "".join(segments_merge) - reconstructed_text_non_merged = "".join(segments_no_merge) - # Assert that the merge did not change the content - assert reconstructed_text_merged == reconstructed_text_non_merged - - -def test_split_text__when_chunk_size_set_with_ai21_tokenizer() -> None: - segmentation_no_merge = AI21SemanticTextSplitter( - length_function=AI21Client().count_tokens - ) - segments_no_merge = segmentation_no_merge.split_text(source=TEXT) - segmentation_merge = AI21SemanticTextSplitter( - chunk_size=1000, length_function=AI21Client().count_tokens - ) - segments_merge = segmentation_merge.split_text(source=TEXT) - # Assert that a merge did happen - assert len(segments_no_merge) > len(segments_merge) - reconstructed_text_merged = "".join(segments_merge) - reconstructed_text_non_merged = "".join(segments_no_merge) - # Assert that the merge did not change the content - assert reconstructed_text_merged == reconstructed_text_non_merged - - -def test_create_documents() -> None: - texts = [TEXT] - segmentation = AI21SemanticTextSplitter() - documents = segmentation.create_documents(texts=texts) - assert len(documents) > 0 - for document in documents: - assert document.page_content is not None - assert document.metadata is not None - - -def test_split_documents() -> None: - documents = [Document(page_content=TEXT, metadata={"foo": "bar"})] - segmentation = AI21SemanticTextSplitter() - segments = segmentation.split_documents(documents=documents) - assert len(segments) > 0 - for segment in segments: - assert segment.page_content is not None - assert segment.metadata is not None diff --git a/libs/partners/ai21/tests/integration_tests/test_standard.py b/libs/partners/ai21/tests/integration_tests/test_standard.py deleted file mode 100644 index 6a038a16257..00000000000 --- a/libs/partners/ai21/tests/integration_tests/test_standard.py +++ /dev/null @@ -1,89 +0,0 @@ -"""Standard LangChain interface tests""" - -import time -from typing import Optional, Type - -import pytest -from langchain_core.language_models import BaseChatModel -from langchain_core.rate_limiters import InMemoryRateLimiter -from langchain_standard_tests.integration_tests import ChatModelIntegrationTests - -from langchain_ai21 import ChatAI21 - -rate_limiter = InMemoryRateLimiter(requests_per_second=0.5) - - -class BaseTestAI21(ChatModelIntegrationTests): - def teardown(self) -> None: - # avoid getting rate limited - time.sleep(1) - - @property - def chat_model_class(self) -> Type[BaseChatModel]: - return ChatAI21 - - @pytest.mark.xfail(reason="Not implemented.") - def test_usage_metadata(self, model: BaseChatModel) -> None: - super().test_usage_metadata(model) - - -class TestAI21J2(BaseTestAI21): - has_tool_calling = False - - @property - def chat_model_params(self) -> dict: - return { - "model": "j2-ultra", - "rate_limiter": rate_limiter, - } - - @pytest.mark.xfail(reason="Streaming is not supported for Jurassic models.") - def test_stream(self, model: BaseChatModel) -> None: - super().test_stream(model) - - @pytest.mark.xfail(reason="Streaming is not supported for Jurassic models.") - async def test_astream(self, model: BaseChatModel) -> None: - await super().test_astream(model) - - @pytest.mark.xfail(reason="Streaming is not supported for Jurassic models.") - def test_usage_metadata_streaming(self, model: BaseChatModel) -> None: - super().test_usage_metadata_streaming(model) - - -class TestAI21Jamba(BaseTestAI21): - has_tool_calling = False - - @property - def chat_model_params(self) -> dict: - return { - "model": "jamba-instruct-preview", - } - - -class TestAI21Jamba1_5(BaseTestAI21): - @property - def tool_choice_value(self) -> Optional[str]: - """Value to use for tool choice when used in tests.""" - return "any" - - @property - def chat_model_params(self) -> dict: - return { - "model": "jamba-1.5-mini", - } - - @pytest.mark.xfail(reason="Prompt doesn't generate tool calls for Jamba 1.5.") - def test_tool_calling(self, model: BaseChatModel) -> None: - super().test_tool_calling(model) - - @pytest.mark.xfail(reason="Prompt doesn't generate tool calls for Jamba 1.5.") - def test_tool_calling_with_no_arguments(self, model: BaseChatModel) -> None: - super().test_tool_calling_with_no_arguments(model) - - @pytest.mark.xfail(reason="Requires tool calling & stream - still WIP") - def test_structured_output(self, model: BaseChatModel) -> None: - super().test_structured_output(model) - - @pytest.mark.xfail(reason="Requires tool calling & stream - still WIP") - def test_structured_output_pydantic_2_v1(self, model: BaseChatModel) -> None: - super().test_structured_output_pydantic_2_v1(model) diff --git a/libs/partners/ai21/tests/unit_tests/__init__.py b/libs/partners/ai21/tests/unit_tests/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libs/partners/ai21/tests/unit_tests/chat/__init__.py b/libs/partners/ai21/tests/unit_tests/chat/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/libs/partners/ai21/tests/unit_tests/chat/conftest.py b/libs/partners/ai21/tests/unit_tests/chat/conftest.py deleted file mode 100644 index 0a44092e31a..00000000000 --- a/libs/partners/ai21/tests/unit_tests/chat/conftest.py +++ /dev/null @@ -1,9 +0,0 @@ -import pytest - -from langchain_ai21.chat.chat_adapter import ChatAdapter -from langchain_ai21.chat.chat_factory import create_chat_adapter - - -@pytest.fixture -def chat_adapter(model: str) -> ChatAdapter: - return create_chat_adapter(model) diff --git a/libs/partners/ai21/tests/unit_tests/chat/test_chat_adapter.py b/libs/partners/ai21/tests/unit_tests/chat/test_chat_adapter.py deleted file mode 100644 index d1abe578ab0..00000000000 --- a/libs/partners/ai21/tests/unit_tests/chat/test_chat_adapter.py +++ /dev/null @@ -1,248 +0,0 @@ -from typing import List - -import pytest -from ai21.models import ChatMessage as J2ChatMessage -from ai21.models import RoleType -from ai21.models.chat import ( - AssistantMessage, - ChatMessage, - UserMessage, -) -from ai21.models.chat import ( - SystemMessage as AI21SystemMessage, -) -from ai21.models.chat import ToolMessage as AI21ToolMessage -from langchain_core.messages import ( - AIMessage, - BaseMessage, - HumanMessage, - SystemMessage, - ToolMessage, -) -from langchain_core.messages import ( - ChatMessage as LangChainChatMessage, -) - -from langchain_ai21.chat.chat_adapter import ChatAdapter - -_J2_MODEL_NAME = "j2-ultra" -_JAMBA_MODEL_NAME = "jamba-instruct-preview" -_JAMBA_1_5_MINI_MODEL_NAME = "jamba-1.5-mini" -_JAMBA_1_5_LARGE_MODEL_NAME = "jamba-1.5-large" - - -@pytest.mark.parametrize( - ids=[ - "when_human_message_j2_model", - "when_ai_message_j2_model", - "when_human_message_jamba_model", - "when_ai_message_jamba_model", - ], - argnames=["model", "message", "expected_ai21_message"], - argvalues=[ - ( - _J2_MODEL_NAME, - HumanMessage(content="Human Message Content"), - J2ChatMessage(role=RoleType.USER, text="Human Message Content"), - ), - ( - _J2_MODEL_NAME, - AIMessage(content="AI Message Content"), - J2ChatMessage(role=RoleType.ASSISTANT, text="AI Message Content"), - ), - ( - _JAMBA_MODEL_NAME, - HumanMessage(content="Human Message Content"), - UserMessage(role="user", content="Human Message Content"), - ), - ( - _JAMBA_MODEL_NAME, - AIMessage(content="AI Message Content"), - AssistantMessage( - role="assistant", content="AI Message Content", tool_calls=[] - ), - ), - ], -) -def test_convert_message_to_ai21_message( - message: BaseMessage, - expected_ai21_message: ChatMessage, - chat_adapter: ChatAdapter, -) -> None: - ai21_message = chat_adapter._convert_message_to_ai21_message(message) - assert ai21_message == expected_ai21_message - - -@pytest.mark.parametrize( - ids=[ - "when_system_message_j2_model", - "when_langchain_chat_message_j2_model", - ], - argnames=["model", "message"], - argvalues=[ - ( - _J2_MODEL_NAME, - AI21SystemMessage(content="System Message Content"), - ), - ( - _J2_MODEL_NAME, - LangChainChatMessage(content="Chat Message Content", role="human"), - ), - ], -) -def test_convert_message_to_ai21_message__when_invalid_role__should_raise_exception( - message: BaseMessage, - chat_adapter: ChatAdapter, -) -> None: - with pytest.raises(ValueError) as e: - chat_adapter._convert_message_to_ai21_message(message) - assert e.value.args[0] == ( - f"Could not resolve role type from message {message}. " - f"Only support {HumanMessage.__name__} and {AIMessage.__name__}." - ) - - -@pytest.mark.parametrize( - ids=[ - "when_all_messages_are_human_messages__should_return_system_none_j2_model", - "when_first_message_is_system__should_return_system_j2_model", - "when_all_messages_are_human_messages__should_return_system_none_jamba_model", - "when_first_message_is_system__should_return_system_jamba_model", - "when_tool_calling_message__should_return_tool_jamba_mini_model", - "when_tool_calling_message__should_return_tool_jamba_large_model", - ], - argnames=["model", "messages", "expected_messages"], - argvalues=[ - ( - _J2_MODEL_NAME, - [ - HumanMessage(content="Human Message Content 1"), - HumanMessage(content="Human Message Content 2"), - ], - { - "system": "", - "messages": [ - J2ChatMessage( - role=RoleType.USER, - text="Human Message Content 1", - ), - J2ChatMessage( - role=RoleType.USER, - text="Human Message Content 2", - ), - ], - }, - ), - ( - _J2_MODEL_NAME, - [ - SystemMessage(content="System Message Content 1"), - HumanMessage(content="Human Message Content 1"), - ], - { - "system": "System Message Content 1", - "messages": [ - J2ChatMessage( - role=RoleType.USER, - text="Human Message Content 1", - ), - ], - }, - ), - ( - _JAMBA_MODEL_NAME, - [ - HumanMessage(content="Human Message Content 1"), - HumanMessage(content="Human Message Content 2"), - ], - { - "messages": [ - UserMessage( - role="user", - content="Human Message Content 1", - ), - UserMessage( - role="user", - content="Human Message Content 2", - ), - ] - }, - ), - ( - _JAMBA_MODEL_NAME, - [ - SystemMessage(content="System Message Content 1"), - HumanMessage(content="Human Message Content 1"), - ], - { - "messages": [ - AI21SystemMessage( - role="system", content="System Message Content 1" - ), - UserMessage(role="user", content="Human Message Content 1"), - ], - }, - ), - ( - _JAMBA_1_5_MINI_MODEL_NAME, - [ - ToolMessage( - content="42", - tool_call_id="call_Jja7J89XsjrOLA5r!MEOW!SL", - ) - ], - { - "messages": [ - AI21ToolMessage( - role="tool", - tool_call_id="call_Jja7J89XsjrOLA5r!MEOW!SL", - content="42", - ), - ], - }, - ), - ( - _JAMBA_1_5_LARGE_MODEL_NAME, - [ - ToolMessage( - content="42", - tool_call_id="call_Jja7J89XsjrOLA5r!MEOW!SL", - ) - ], - { - "messages": [ - AI21ToolMessage( - role="tool", - tool_call_id="call_Jja7J89XsjrOLA5r!MEOW!SL", - content="42", - ), - ], - }, - ), - ], -) -def test_convert_messages( - chat_adapter: ChatAdapter, - messages: List[BaseMessage], - expected_messages: List[ChatMessage], -) -> None: - converted_messages = chat_adapter.convert_messages(messages) - assert converted_messages == expected_messages - - -@pytest.mark.parametrize( - ids=[ - "when_j2_model", - ], - argnames=["model"], - argvalues=[ - (_J2_MODEL_NAME,), - ], -) -def test_convert_messages__when_system_is_not_first(chat_adapter: ChatAdapter) -> None: - messages = [ - HumanMessage(content="Human Message Content 1"), - SystemMessage(content="System Message Content 1"), - ] - with pytest.raises(ValueError): - chat_adapter.convert_messages(messages) diff --git a/libs/partners/ai21/tests/unit_tests/chat/test_chat_adapter_factory.py b/libs/partners/ai21/tests/unit_tests/chat/test_chat_adapter_factory.py deleted file mode 100644 index c782d0a67b5..00000000000 --- a/libs/partners/ai21/tests/unit_tests/chat/test_chat_adapter_factory.py +++ /dev/null @@ -1,34 +0,0 @@ -from typing import Type - -import pytest - -from langchain_ai21.chat.chat_adapter import ( - ChatAdapter, - J2ChatAdapter, - JambaChatCompletionsAdapter, -) -from langchain_ai21.chat.chat_factory import create_chat_adapter -from tests.unit_tests.conftest import J2_CHAT_MODEL_NAME, JAMBA_CHAT_MODEL_NAME - - -@pytest.mark.parametrize( - ids=[ - "when_j2_model", - "when_jamba_model", - ], - argnames=["model", "expected_chat_type"], - argvalues=[ - (J2_CHAT_MODEL_NAME, J2ChatAdapter), - (JAMBA_CHAT_MODEL_NAME, JambaChatCompletionsAdapter), - ], -) -def test_create_chat_adapter_with_supported_models( - model: str, expected_chat_type: Type[ChatAdapter] -) -> None: - adapter = create_chat_adapter(model) - assert isinstance(adapter, expected_chat_type) - - -def test_create_chat_adapter__when_model_not_supported() -> None: - with pytest.raises(ValueError): - create_chat_adapter("unsupported-model") diff --git a/libs/partners/ai21/tests/unit_tests/conftest.py b/libs/partners/ai21/tests/unit_tests/conftest.py deleted file mode 100644 index f70b2cdaa0e..00000000000 --- a/libs/partners/ai21/tests/unit_tests/conftest.py +++ /dev/null @@ -1,207 +0,0 @@ -import os -from contextlib import contextmanager -from typing import Generator -from unittest.mock import Mock - -import pytest -from ai21 import AI21Client -from ai21.models import ( - AnswerResponse, - ChatOutput, - ChatResponse, - Completion, - CompletionData, - CompletionFinishReason, - CompletionsResponse, - FinishReason, - Penalty, - RoleType, - SegmentationResponse, -) -from ai21.models.responses.segmentation_response import Segment -from pytest_mock import MockerFixture - -J2_CHAT_MODEL_NAME = "j2-ultra" -JAMBA_CHAT_MODEL_NAME = "jamba-instruct-preview" -JAMBA_1_5_MINI_CHAT_MODEL_NAME = "jamba-1.5-mini" -JAMBA_1_5_LARGE_CHAT_MODEL_NAME = "jamba-1.5-large" -DUMMY_API_KEY = "test_api_key" - -JAMBA_FAMILY_MODEL_NAMES = [ - JAMBA_CHAT_MODEL_NAME, - JAMBA_1_5_MINI_CHAT_MODEL_NAME, - JAMBA_1_5_LARGE_CHAT_MODEL_NAME, -] - -BASIC_EXAMPLE_LLM_PARAMETERS = { - "num_results": 3, - "max_tokens": 20, - "min_tokens": 10, - "temperature": 0.5, - "top_p": 0.5, - "top_k_return": 0, - "frequency_penalty": Penalty(scale=0.2, apply_to_numbers=True), # type: ignore[call-arg] - "presence_penalty": Penalty(scale=0.2, apply_to_stopwords=True), # type: ignore[call-arg] - "count_penalty": Penalty( # type: ignore[call-arg] - scale=0.2, - apply_to_punctuation=True, - apply_to_emojis=True, - ), -} - -BASIC_EXAMPLE_CHAT_PARAMETERS = { - "num_results": 3, - "max_tokens": 20, - "min_tokens": 10, - "temperature": 0.5, - "top_p": 0.5, - "top_k_return": 0, - "frequency_penalty": Penalty(scale=0.2, apply_to_numbers=True), # type: ignore[call-arg] - "presence_penalty": Penalty(scale=0.2, apply_to_stopwords=True), # type: ignore[call-arg] - "count_penalty": Penalty( # type: ignore[call-arg] - scale=0.2, - apply_to_punctuation=True, - apply_to_emojis=True, - ), - "n": 3, -} - -SEGMENTS = [ - Segment( # type: ignore[call-arg] - segment_type="normal_text", - segment_text=( - "The original full name of the franchise is Pocket Monsters " - "(ポケットモンスター, Poketto Monsutā), which was abbreviated to " - "Pokemon during development of the original games.\n\nWhen the " - "franchise was released internationally, the short form of the " - "title was used, with an acute accent (´) over the e to aid " - "in pronunciation." - ), - ), - Segment( # type: ignore[call-arg] - segment_type="normal_text", - segment_text=( - "Pokémon refers to both the franchise itself and the creatures " - "within its fictional universe.\n\nAs a noun, it is identical in " - "both the singular and plural, as is every individual species " - 'name;[10] it is grammatically correct to say "one Pokémon" ' - 'and "many Pokémon", as well as "one Pikachu" and "many ' - 'Pikachu".\n\nIn English, Pokémon may be pronounced either ' - "/'powkɛmon/ (poe-keh-mon) or /'powkɪmon/ (poe-key-mon)." - ), - ), -] - - -BASIC_EXAMPLE_LLM_PARAMETERS_AS_DICT = { - "num_results": 3, - "max_tokens": 20, - "min_tokens": 10, - "temperature": 0.5, - "top_p": 0.5, - "top_k_return": 0, - "frequency_penalty": Penalty(scale=0.2, apply_to_numbers=True).to_dict(), # type: ignore[call-arg] - "presence_penalty": Penalty(scale=0.2, apply_to_stopwords=True).to_dict(), # type: ignore[call-arg] - "count_penalty": Penalty( # type: ignore[call-arg] - scale=0.2, - apply_to_punctuation=True, - apply_to_emojis=True, - ).to_dict(), -} - -BASIC_EXAMPLE_CHAT_PARAMETERS_AS_DICT = { - "num_results": 3, - "max_tokens": 20, - "min_tokens": 10, - "temperature": 0.5, - "top_p": 0.5, - "top_k_return": 0, - "frequency_penalty": Penalty(scale=0.2, apply_to_numbers=True).to_dict(), # type: ignore[call-arg] - "presence_penalty": Penalty(scale=0.2, apply_to_stopwords=True).to_dict(), # type: ignore[call-arg] - "count_penalty": Penalty( # type: ignore[call-arg] - scale=0.2, - apply_to_punctuation=True, - apply_to_emojis=True, - ).to_dict(), - "n": 3, -} - - -@pytest.fixture -def mocked_completion_response(mocker: MockerFixture) -> Mock: - mocked_response = mocker.MagicMock(spec=CompletionsResponse) - mocked_response.prompt = "this is a test prompt" - mocked_response.completions = [ - Completion( # type: ignore[call-arg] - data=CompletionData(text="test", tokens=[]), - finish_reason=CompletionFinishReason(reason=None, length=None), - ) - ] - return mocked_response - - -@pytest.fixture -def mock_client_with_completion( - mocker: MockerFixture, mocked_completion_response: Mock -) -> Mock: - mock_client = mocker.MagicMock(spec=AI21Client) - mock_client.completion = mocker.MagicMock() - mock_client.completion.create.side_effect = [ - mocked_completion_response, - mocked_completion_response, - ] - mock_client.count_tokens.side_effect = [10, 20] - - return mock_client - - -@pytest.fixture -def mock_client_with_chat(mocker: MockerFixture) -> Mock: - mock_client = mocker.MagicMock(spec=AI21Client) - mock_client.chat = mocker.MagicMock() - - output = ChatOutput( # type: ignore[call-arg] - text="Hello Pickle Rick!", - role=RoleType.ASSISTANT, - finish_reason=FinishReason(reason="testing"), - ) - mock_client.chat.create.return_value = ChatResponse(outputs=[output]) - - return mock_client - - -@contextmanager -def temporarily_unset_api_key() -> Generator: - """ - Unset and set environment key for testing purpose for when an API KEY is not set - """ - api_key = os.environ.pop("AI21_API_KEY", None) - yield - - if api_key is not None: - os.environ["AI21_API_KEY"] = api_key - - -@pytest.fixture -def mock_client_with_contextual_answers(mocker: MockerFixture) -> Mock: - mock_client = mocker.MagicMock(spec=AI21Client) - mock_client.answer = mocker.MagicMock() - mock_client.answer.create.return_value = AnswerResponse( # type: ignore[call-arg] - id="some_id", - answer="some answer", - answer_in_context=False, - ) - - return mock_client - - -@pytest.fixture -def mock_client_with_semantic_text_splitter(mocker: MockerFixture) -> Mock: - mock_client = mocker.MagicMock(spec=AI21Client) - mock_client.segmentation = mocker.MagicMock() - mock_client.segmentation.create.return_value = SegmentationResponse( - id="12345", - segments=SEGMENTS, - ) - - return mock_client diff --git a/libs/partners/ai21/tests/unit_tests/test_chat_models.py b/libs/partners/ai21/tests/unit_tests/test_chat_models.py deleted file mode 100644 index 4ad6b39a3a4..00000000000 --- a/libs/partners/ai21/tests/unit_tests/test_chat_models.py +++ /dev/null @@ -1,174 +0,0 @@ -"""Test chat model integration.""" - -from typing import cast -from unittest.mock import Mock, call - -import pytest -from ai21 import MissingApiKeyError -from ai21.models import ChatMessage, Penalty, RoleType -from langchain_core.messages import ( - AIMessage, - HumanMessage, - SystemMessage, -) -from langchain_core.pydantic_v1 import SecretStr -from pytest import CaptureFixture, MonkeyPatch - -from langchain_ai21.chat_models import ( - ChatAI21, -) -from tests.unit_tests.conftest import ( - BASIC_EXAMPLE_CHAT_PARAMETERS, - BASIC_EXAMPLE_CHAT_PARAMETERS_AS_DICT, - DUMMY_API_KEY, - temporarily_unset_api_key, -) - - -def test_initialization__when_no_api_key__should_raise_exception() -> None: - """Test integration initialization.""" - with temporarily_unset_api_key(): - with pytest.raises(MissingApiKeyError): - ChatAI21(model="j2-ultra") # type: ignore[call-arg] - - -def test_initialization__when_default_parameters_in_init() -> None: - """Test chat model initialization.""" - ChatAI21(api_key=DUMMY_API_KEY, model="j2-ultra") # type: ignore[call-arg, arg-type] - - -def test_initialization__when_custom_parameters_in_init() -> None: - model = "j2-ultra" - num_results = 1 - max_tokens = 10 - min_tokens = 20 - temperature = 0.1 - top_p = 0.1 - top_k_return = 0 - frequency_penalty = Penalty(scale=0.2, apply_to_numbers=True) # type: ignore[call-arg] - presence_penalty = Penalty(scale=0.2, apply_to_stopwords=True) # type: ignore[call-arg] - count_penalty = Penalty(scale=0.2, apply_to_punctuation=True, apply_to_emojis=True) # type: ignore[call-arg] - - llm = ChatAI21( # type: ignore[call-arg] - api_key=DUMMY_API_KEY, # type: ignore[arg-type] - model=model, - num_results=num_results, - max_tokens=max_tokens, - min_tokens=min_tokens, - temperature=temperature, - top_p=top_p, - top_k_return=top_k_return, - frequency_penalty=frequency_penalty, - presence_penalty=presence_penalty, - count_penalty=count_penalty, - ) - assert llm.model == model - assert llm.num_results == num_results - assert llm.max_tokens == max_tokens - assert llm.min_tokens == min_tokens - assert llm.temperature == temperature - assert llm.top_p == top_p - assert llm.top_k_return == top_k_return - assert llm.frequency_penalty == frequency_penalty - assert llm.presence_penalty == presence_penalty - assert count_penalty == count_penalty - - -def test_invoke(mock_client_with_chat: Mock) -> None: - chat_input = "I'm Pickle Rick" - - llm = ChatAI21( - model="j2-ultra", - api_key=DUMMY_API_KEY, # type: ignore[arg-type] - client=mock_client_with_chat, - **BASIC_EXAMPLE_CHAT_PARAMETERS, # type: ignore[arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type] - ) - llm.invoke(input=chat_input, config=dict(tags=["foo"]), stop=["\n"]) - - mock_client_with_chat.chat.create.assert_called_once_with( - model="j2-ultra", - messages=[ChatMessage(role=RoleType.USER, text=chat_input)], - system="", - stop_sequences=["\n"], - **BASIC_EXAMPLE_CHAT_PARAMETERS_AS_DICT, - ) - - -def test_generate(mock_client_with_chat: Mock) -> None: - messages0 = [ - HumanMessage(content="I'm Pickle Rick"), - AIMessage(content="Hello Pickle Rick! I am your AI Assistant"), - HumanMessage(content="Nice to meet you."), - ] - messages1 = [ - SystemMessage(content="system message"), - HumanMessage(content="What is 1 + 1"), - ] - llm = ChatAI21( - model="j2-ultra", - client=mock_client_with_chat, - **BASIC_EXAMPLE_CHAT_PARAMETERS, # type: ignore[arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type] - ) - - llm.generate(messages=[messages0, messages1]) - mock_client_with_chat.chat.create.assert_has_calls( - [ - call( - model="j2-ultra", - messages=[ - ChatMessage( - role=RoleType.USER, - text=str(messages0[0].content), - ), - ChatMessage( - role=RoleType.ASSISTANT, text=str(messages0[1].content) - ), - ChatMessage(role=RoleType.USER, text=str(messages0[2].content)), - ], - system="", - **BASIC_EXAMPLE_CHAT_PARAMETERS_AS_DICT, - ), - call( - model="j2-ultra", - messages=[ - ChatMessage(role=RoleType.USER, text=str(messages1[1].content)), - ], - system="system message", - **BASIC_EXAMPLE_CHAT_PARAMETERS_AS_DICT, - ), - ] - ) - - -def test_api_key_is_secret_string() -> None: - llm = ChatAI21(model="j2-ultra", api_key="secret-api-key") # type: ignore[call-arg, arg-type] - assert isinstance(llm.api_key, SecretStr) - - -def test_api_key_masked_when_passed_from_env( - monkeypatch: MonkeyPatch, capsys: CaptureFixture -) -> None: - """Test initialization with an API key provided via an env variable""" - monkeypatch.setenv("AI21_API_KEY", "secret-api-key") - llm = ChatAI21(model="j2-ultra") # type: ignore[call-arg] - print(llm.api_key, end="") - captured = capsys.readouterr() - - assert captured.out == "**********" - - -def test_api_key_masked_when_passed_via_constructor( - capsys: CaptureFixture, -) -> None: - """Test initialization with an API key provided via the initializer""" - llm = ChatAI21(model="j2-ultra", api_key="secret-api-key") # type: ignore[call-arg, arg-type] - print(llm.api_key, end="") - captured = capsys.readouterr() - - assert captured.out == "**********" - - -def test_uses_actual_secret_value_from_secretstr() -> None: - """Test that actual secret is retrieved using `.get_secret_value()`.""" - llm = ChatAI21(model="j2-ultra", api_key="secret-api-key") # type: ignore[call-arg, arg-type] - assert cast(SecretStr, llm.api_key).get_secret_value() == "secret-api-key" diff --git a/libs/partners/ai21/tests/unit_tests/test_contextual_answers.py b/libs/partners/ai21/tests/unit_tests/test_contextual_answers.py deleted file mode 100644 index 41ba5f32ef5..00000000000 --- a/libs/partners/ai21/tests/unit_tests/test_contextual_answers.py +++ /dev/null @@ -1,109 +0,0 @@ -from unittest.mock import Mock - -import pytest -from langchain_core.documents import Document - -from langchain_ai21 import AI21ContextualAnswers -from langchain_ai21.contextual_answers import ContextualAnswerInput -from tests.unit_tests.conftest import DUMMY_API_KEY - - -@pytest.mark.parametrize( - ids=[ - "when_no_context__should_raise_exception", - "when_no_question__should_raise_exception", - "when_question_is_an_empty_string__should_raise_exception", - "when_context_is_an_empty_string__should_raise_exception", - "when_context_is_an_empty_list", - ], - argnames="input", - argvalues=[ - ({"question": "What is the capital of France?"}), - ({"context": "Paris is the capital of France"}), - ({"question": "", "context": "Paris is the capital of France"}), - ({"context": "", "question": "some question?"}), - ({"context": [], "question": "What is the capital of France?"}), - ], -) -def test_invoke__on_bad_input( - input: ContextualAnswerInput, - mock_client_with_contextual_answers: Mock, -) -> None: - tsm = AI21ContextualAnswers( - api_key=DUMMY_API_KEY, # type: ignore[arg-type] - client=mock_client_with_contextual_answers, # type: ignore[arg-type] - ) - - with pytest.raises(ValueError) as error: - tsm.invoke(input) - - assert ( - error.value.args[0] - == f"Input must contain a 'context' and 'question' fields. Got {input}" - ) - - -@pytest.mark.parametrize( - ids=[ - "when_context_is_not_str_or_list_of_docs_or_str", - ], - argnames="input", - argvalues=[ - ({"context": 1242, "question": "What is the capital of France?"}), - ], -) -def test_invoke__on_context_bad_input( - input: ContextualAnswerInput, mock_client_with_contextual_answers: Mock -) -> None: - tsm = AI21ContextualAnswers( - api_key=DUMMY_API_KEY, # type: ignore[arg-type] - client=mock_client_with_contextual_answers, - ) - - with pytest.raises(ValueError) as error: - tsm.invoke(input) - - assert ( - error.value.args[0] == f"Expected input to be a list of strings or Documents." - f" Received {type(input)}" - ) - - -@pytest.mark.parametrize( - ids=[ - "when_context_is_a_list_of_strings", - "when_context_is_a_list_of_documents", - "when_context_is_a_string", - ], - argnames="input", - argvalues=[ - ( - { - "context": ["Paris is the capital of france"], - "question": "What is the capital of France?", - } - ), - ( - { - "context": [Document(page_content="Paris is the capital of france")], - "question": "What is the capital of France?", - } - ), - ( - { - "context": "Paris is the capital of france", - "question": "What is the capital of France?", - } - ), - ], -) -def test_invoke__on_good_input( - input: ContextualAnswerInput, mock_client_with_contextual_answers: Mock -) -> None: - tsm = AI21ContextualAnswers( - api_key=DUMMY_API_KEY, # type: ignore[arg-type] - client=mock_client_with_contextual_answers, - ) - - response = tsm.invoke(input) - assert isinstance(response, str) diff --git a/libs/partners/ai21/tests/unit_tests/test_embeddings.py b/libs/partners/ai21/tests/unit_tests/test_embeddings.py deleted file mode 100644 index 8c0062ad613..00000000000 --- a/libs/partners/ai21/tests/unit_tests/test_embeddings.py +++ /dev/null @@ -1,102 +0,0 @@ -"""Test embedding model integration.""" - -from typing import List -from unittest.mock import Mock - -import pytest -from ai21 import AI21Client, MissingApiKeyError -from ai21.models import EmbedResponse, EmbedResult, EmbedType -from pytest_mock import MockerFixture - -from langchain_ai21.embeddings import AI21Embeddings -from tests.unit_tests.conftest import DUMMY_API_KEY, temporarily_unset_api_key - -_EXAMPLE_EMBEDDING_0 = [1.0, 2.0, 3.0] -_EXAMPLE_EMBEDDING_1 = [4.0, 5.0, 6.0] -_EXAMPLE_EMBEDDING_2 = [7.0, 8.0, 9.0] - -_EXAMPLE_EMBEDDING_RESPONSE = EmbedResponse( - results=[ - EmbedResult(embedding=_EXAMPLE_EMBEDDING_0), - EmbedResult(embedding=_EXAMPLE_EMBEDDING_1), - EmbedResult(embedding=_EXAMPLE_EMBEDDING_2), - ], - id="test_id", -) - - -def test_initialization__when_no_api_key__should_raise_exception() -> None: - """Test integration initialization.""" - with temporarily_unset_api_key(): - with pytest.raises(MissingApiKeyError): - AI21Embeddings() - - -@pytest.fixture -def mock_client_with_embeddings(mocker: MockerFixture) -> Mock: - mock_client = mocker.MagicMock(spec=AI21Client) - mock_client.embed = mocker.MagicMock() - mock_client.embed.create.return_value = _EXAMPLE_EMBEDDING_RESPONSE - - return mock_client - - -def test_embed_query(mock_client_with_embeddings: Mock) -> None: - llm = AI21Embeddings(client=mock_client_with_embeddings, api_key=DUMMY_API_KEY) # type: ignore[arg-type] - - text = "Hello embeddings world!" - response = llm.embed_query(text=text) - assert response == _EXAMPLE_EMBEDDING_0 - mock_client_with_embeddings.embed.create.assert_called_once_with( - texts=[text], - type=EmbedType.QUERY, - ) - - -def test_embed_documents(mock_client_with_embeddings: Mock) -> None: - llm = AI21Embeddings(client=mock_client_with_embeddings, api_key=DUMMY_API_KEY) # type: ignore[arg-type] - - texts = ["Hello embeddings world!", "Some other text", "Some more text"] - response = llm.embed_documents(texts=texts) - assert response == [ - _EXAMPLE_EMBEDDING_0, - _EXAMPLE_EMBEDDING_1, - _EXAMPLE_EMBEDDING_2, - ] - mock_client_with_embeddings.embed.create.assert_called_once_with( - texts=texts, - type=EmbedType.SEGMENT, - ) - - -@pytest.mark.parametrize( - ids=[ - "empty_texts", - "chunk_size_greater_than_texts_length", - "chunk_size_equal_to_texts_length", - "chunk_size_less_than_texts_length", - "chunk_size_one_with_multiple_texts", - "chunk_size_greater_than_texts_length", - ], - argnames=["texts", "chunk_size", "expected_internal_embeddings_calls"], - argvalues=[ - ([], 3, 0), - (["text1", "text2", "text3"], 5, 1), - (["text1", "text2", "text3"], 3, 1), - (["text1", "text2", "text3", "text4", "text5"], 2, 3), - (["text1", "text2", "text3"], 1, 3), - (["text1", "text2", "text3"], 10, 1), - ], -) -def test_get_len_safe_embeddings( - mock_client_with_embeddings: Mock, - texts: List[str], - chunk_size: int, - expected_internal_embeddings_calls: int, -) -> None: - llm = AI21Embeddings(client=mock_client_with_embeddings, api_key=DUMMY_API_KEY) # type: ignore[arg-type] - llm.embed_documents(texts=texts, batch_size=chunk_size) - assert ( - mock_client_with_embeddings.embed.create.call_count - == expected_internal_embeddings_calls - ) diff --git a/libs/partners/ai21/tests/unit_tests/test_imports.py b/libs/partners/ai21/tests/unit_tests/test_imports.py deleted file mode 100644 index 0130415bbff..00000000000 --- a/libs/partners/ai21/tests/unit_tests/test_imports.py +++ /dev/null @@ -1,13 +0,0 @@ -from langchain_ai21 import __all__ - -EXPECTED_ALL = [ - "AI21LLM", - "ChatAI21", - "AI21Embeddings", - "AI21ContextualAnswers", - "AI21SemanticTextSplitter", -] - - -def test_all_imports() -> None: - assert sorted(EXPECTED_ALL) == sorted(__all__) diff --git a/libs/partners/ai21/tests/unit_tests/test_llms.py b/libs/partners/ai21/tests/unit_tests/test_llms.py deleted file mode 100644 index 648f2ef27d4..00000000000 --- a/libs/partners/ai21/tests/unit_tests/test_llms.py +++ /dev/null @@ -1,146 +0,0 @@ -"""Test AI21 Chat API wrapper.""" - -from typing import cast -from unittest.mock import Mock, call - -import pytest -from ai21 import MissingApiKeyError -from ai21.models import ( - Penalty, -) -from langchain_core.pydantic_v1 import SecretStr -from pytest import CaptureFixture, MonkeyPatch - -from langchain_ai21 import AI21LLM -from tests.unit_tests.conftest import ( - BASIC_EXAMPLE_LLM_PARAMETERS, - BASIC_EXAMPLE_LLM_PARAMETERS_AS_DICT, - DUMMY_API_KEY, - temporarily_unset_api_key, -) - - -def test_initialization__when_no_api_key__should_raise_exception() -> None: - """Test integration initialization.""" - with temporarily_unset_api_key(): - with pytest.raises(MissingApiKeyError): - AI21LLM( - model="j2-ultra", - ) - - -def test_initialization__when_default_parameters() -> None: - """Test integration initialization.""" - AI21LLM( - api_key=DUMMY_API_KEY, # type: ignore[arg-type] - model="j2-ultra", - ) - - -def test_initialization__when_custom_parameters_to_init() -> None: - """Test integration initialization.""" - AI21LLM( # type: ignore[call-arg] - api_key=DUMMY_API_KEY, # type: ignore[arg-type] - model="j2-mid", - num_results=2, - max_tokens=20, - min_tokens=10, - temperature=0.5, - top_p=0.5, - top_k_return=0, - stop_sequences=["\n"], - frequency_penalty=Penalty(scale=0.2, apply_to_numbers=True), # type: ignore[call-arg] - presence_penalty=Penalty(scale=0.2, apply_to_stopwords=True), # type: ignore[call-arg] - count_penalty=Penalty( # type: ignore[call-arg] - scale=0.2, apply_to_punctuation=True, apply_to_emojis=True - ), - custom_model="test_model", - epoch=1, - ) - - -def test_generate(mock_client_with_completion: Mock) -> None: - # Setup test - prompt0 = "Hi, my name is what?" - prompt1 = "My name is who?" - stop = ["\n"] - custom_model = "test_model" - epoch = 1 - - ai21 = AI21LLM( - model="j2-ultra", - api_key=DUMMY_API_KEY, # type: ignore[arg-type] - client=mock_client_with_completion, - custom_model=custom_model, - epoch=epoch, - **BASIC_EXAMPLE_LLM_PARAMETERS, # type: ignore[arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type, arg-type] - ) - - # Make call to testing function - ai21.generate( - [prompt0, prompt1], - stop=stop, - ) - - # Assertions - mock_client_with_completion.count_tokens.assert_has_calls( - [ - call(prompt0), - call(prompt1), - ], - ) - - mock_client_with_completion.completion.create.assert_has_calls( - [ - call( - prompt=prompt0, - model="j2-ultra", - custom_model=custom_model, - stop_sequences=stop, - epoch=epoch, - **BASIC_EXAMPLE_LLM_PARAMETERS_AS_DICT, - ), - call( - prompt=prompt1, - model="j2-ultra", - custom_model=custom_model, - stop_sequences=stop, - epoch=epoch, - **BASIC_EXAMPLE_LLM_PARAMETERS_AS_DICT, - ), - ] - ) - - -def test_api_key_is_secret_string() -> None: - llm = AI21LLM(model="j2-ultra", api_key="secret-api-key") # type: ignore[arg-type] - assert isinstance(llm.api_key, SecretStr) - - -def test_api_key_masked_when_passed_from_env( - monkeypatch: MonkeyPatch, capsys: CaptureFixture -) -> None: - """Test initialization with an API key provided via an env variable""" - monkeypatch.setenv("AI21_API_KEY", "secret-api-key") - llm = AI21LLM(model="j2-ultra") - print(llm.api_key, end="") - captured = capsys.readouterr() - - assert captured.out == "**********" - - -def test_api_key_masked_when_passed_via_constructor( - capsys: CaptureFixture, -) -> None: - """Test initialization with an API key provided via the initializer""" - llm = AI21LLM(model="j2-ultra", api_key="secret-api-key") # type: ignore[arg-type] - print(llm.api_key, end="") - captured = capsys.readouterr() - - assert captured.out == "**********" - - -def test_uses_actual_secret_value_from_secretstr() -> None: - """Test that actual secret is retrieved using `.get_secret_value()`.""" - llm = AI21LLM(model="j2-ultra", api_key="secret-api-key") # type: ignore[arg-type] - assert cast(SecretStr, llm.api_key).get_secret_value() == "secret-api-key" diff --git a/libs/partners/ai21/tests/unit_tests/test_semantic_text_splitter.py b/libs/partners/ai21/tests/unit_tests/test_semantic_text_splitter.py deleted file mode 100644 index 1beb4fba4d8..00000000000 --- a/libs/partners/ai21/tests/unit_tests/test_semantic_text_splitter.py +++ /dev/null @@ -1,129 +0,0 @@ -from unittest.mock import Mock - -import pytest - -from langchain_ai21 import AI21SemanticTextSplitter -from tests.unit_tests.conftest import SEGMENTS - -TEXT = ( - "The original full name of the franchise is Pocket Monsters (ポケットモンスター, " - "Poketto Monsutā), which was abbreviated to " - "Pokemon during development of the original games.\n" - "When the franchise was released internationally, the short form of the title was " - "used, with an acute accent (´) " - "over the e to aid in pronunciation.\n" - "Pokémon refers to both the franchise itself and the creatures within its " - "fictional universe.\n" - "As a noun, it is identical in both the singular and plural, as is every " - "individual species name;[10] it is " - 'grammatically correct to say "one Pokémon" and "many Pokémon", as well ' - 'as "one Pikachu" and "many Pikachu".\n' - "In English, Pokémon may be pronounced either /'powkɛmon/ (poe-keh-mon) or " - "/'powkɪmon/ (poe-key-mon).\n" - "The Pokémon franchise is set in a world in which humans coexist with creatures " - "known as Pokémon.\n" - "Pokémon Red and Blue contain 151 Pokémon species, with new ones being introduced " - "in subsequent games; as of December 2023, 1,025 Pokémon species have been " - "introduced.\n[b] Most Pokémon are inspired by real-world animals;[12] for example," - "Pikachu are a yellow mouse-like species[13] with lightning bolt-shaped tails[14] " - "that possess electrical abilities.[15]" -) - - -@pytest.mark.parametrize( - ids=[ - "when_chunk_size_is_zero", - "when_chunk_size_is_large", - "when_chunk_size_is_small", - ], - argnames=["chunk_size", "expected_segmentation_len"], - argvalues=[ - (0, 2), - (1000, 1), - (10, 2), - ], -) -def test_split_text__on_chunk_size( - chunk_size: int, - expected_segmentation_len: int, - mock_client_with_semantic_text_splitter: Mock, -) -> None: - sts = AI21SemanticTextSplitter( - chunk_size=chunk_size, - client=mock_client_with_semantic_text_splitter, - ) - segments = sts.split_text("This is a test") - assert len(segments) == expected_segmentation_len - - -def test_split_text__on_large_chunk_size__should_merge_chunks( - mock_client_with_semantic_text_splitter: Mock, -) -> None: - sts_no_merge = AI21SemanticTextSplitter( - client=mock_client_with_semantic_text_splitter - ) - sts_merge = AI21SemanticTextSplitter( - client=mock_client_with_semantic_text_splitter, - chunk_size=1000, - ) - segments_no_merge = sts_no_merge.split_text("This is a test") - segments_merge = sts_merge.split_text("This is a test") - assert len(segments_merge) > 0 - assert len(segments_no_merge) > 0 - assert len(segments_no_merge) > len(segments_merge) - - -def test_split_text__on_small_chunk_size__should_not_merge_chunks( - mock_client_with_semantic_text_splitter: Mock, -) -> None: - sts_no_merge = AI21SemanticTextSplitter( - client=mock_client_with_semantic_text_splitter - ) - segments = sts_no_merge.split_text("This is a test") - assert len(segments) == 2 - for index in range(2): - assert segments[index] == SEGMENTS[index].segment_text - - -def test_create_documents__on_start_index__should_should_add_start_index( - mock_client_with_semantic_text_splitter: Mock, -) -> None: - sts = AI21SemanticTextSplitter( - client=mock_client_with_semantic_text_splitter, - add_start_index=True, - ) - - response = sts.create_documents(texts=[TEXT]) - assert len(response) > 0 - for segment in response: - assert segment.page_content is not None - assert segment.metadata is not None - assert "start_index" in segment.metadata - assert segment.metadata["start_index"] > -1 - - -def test_create_documents__when_metadata_from_user__should_add_metadata( - mock_client_with_semantic_text_splitter: Mock, -) -> None: - sts = AI21SemanticTextSplitter(client=mock_client_with_semantic_text_splitter) - metadatas = [{"hello": "world"}] - response = sts.create_documents(texts=[TEXT], metadatas=metadatas) - assert len(response) > 0 - for index in range(len(response)): - assert response[index].page_content == SEGMENTS[index].segment_text - assert len(response[index].metadata) == 2 - assert response[index].metadata["source_type"] == SEGMENTS[index].segment_type - assert response[index].metadata["hello"] == "world" - - -def test_split_text_to_documents__when_metadata_not_passed__should_contain_source_type( - mock_client_with_semantic_text_splitter: Mock, -) -> None: - sts = AI21SemanticTextSplitter(client=mock_client_with_semantic_text_splitter) - response = sts.split_text_to_documents(TEXT) - assert len(response) > 0 - for segment in response: - assert segment.page_content is not None - assert segment.metadata is not None - assert "source_type" in segment.metadata - assert segment.metadata["source_type"] is not None diff --git a/libs/partners/ai21/tests/unit_tests/test_standard.py b/libs/partners/ai21/tests/unit_tests/test_standard.py deleted file mode 100644 index 6ea5ca3b9f0..00000000000 --- a/libs/partners/ai21/tests/unit_tests/test_standard.py +++ /dev/null @@ -1,36 +0,0 @@ -"""Standard LangChain interface tests""" - -from typing import Type - -from langchain_core.language_models import BaseChatModel -from langchain_standard_tests.unit_tests import ( # type: ignore[import-not-found] - ChatModelUnitTests, # type: ignore[import-not-found] -) - -from langchain_ai21 import ChatAI21 - - -class TestAI21J2(ChatModelUnitTests): - @property - def chat_model_class(self) -> Type[BaseChatModel]: - return ChatAI21 - - @property - def chat_model_params(self) -> dict: - return { - "model": "j2-ultra", - "api_key": "test_api_key", - } - - -class TestAI21Jamba(ChatModelUnitTests): - @property - def chat_model_class(self) -> Type[BaseChatModel]: - return ChatAI21 - - @property - def chat_model_params(self) -> dict: - return { - "model": "jamba-instruct", - "api_key": "test_api_key", - } diff --git a/libs/partners/ai21/tests/unit_tests/test_utils.py b/libs/partners/ai21/tests/unit_tests/test_utils.py deleted file mode 100644 index 5a1e676cef8..00000000000 --- a/libs/partners/ai21/tests/unit_tests/test_utils.py +++ /dev/null @@ -1,29 +0,0 @@ -from typing import List - -import pytest - -from langchain_ai21.embeddings import _split_texts_into_batches - - -@pytest.mark.parametrize( - ids=[ - "when_chunk_size_is_2__should_return_3_chunks", - "when_texts_is_empty__should_return_empty_list", - "when_chunk_size_is_1__should_return_10_chunks", - ], - argnames=["input_texts", "chunk_size", "expected_output"], - argvalues=[ - (["a", "b", "c", "d", "e"], 2, [["a", "b"], ["c", "d"], ["e"]]), - ([], 3, []), - ( - ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], - 1, - [["1"], ["2"], ["3"], ["4"], ["5"], ["6"], ["7"], ["8"], ["9"], ["10"]], - ), - ], -) -def test_chunked_text_generator( - input_texts: List[str], chunk_size: int, expected_output: List[List[str]] -) -> None: - result = list(_split_texts_into_batches(input_texts, chunk_size)) - assert result == expected_output diff --git a/libs/partners/upstage/.gitignore b/libs/partners/upstage/.gitignore deleted file mode 100644 index bee8a64b79a..00000000000 --- a/libs/partners/upstage/.gitignore +++ /dev/null @@ -1 +0,0 @@ -__pycache__ diff --git a/libs/partners/upstage/README.md b/libs/partners/upstage/README.md deleted file mode 100644 index c8b61f4859c..00000000000 --- a/libs/partners/upstage/README.md +++ /dev/null @@ -1,3 +0,0 @@ -This package has moved! - -https://github.com/langchain-ai/langchain-upstage/tree/main/libs/upstage \ No newline at end of file