From a231a6276fd0e4297ddc2e623dabf15bada90c99 Mon Sep 17 00:00:00 2001 From: Frank Colson Date: Sun, 4 Aug 2024 15:41:19 -0700 Subject: [PATCH 1/2] Lay down beginnings --- docprompt/tasks/base.py | 172 +++++++++++++++++- .../classification/{anthropic.py => image.py} | 10 +- docprompt/tasks/factory.py | 6 +- .../markerize/{anthropic.py => image.py} | 0 docprompt/tasks/result.py | 3 +- docprompt/tasks/table_extraction/base.py | 10 +- .../{anthropic.py => image_xml.py} | 6 +- tests/tasks/classification/test_anthropic.py | 2 +- tests/tasks/markerize/test_anthropic.py | 2 +- .../tasks/table_extraction/test_anthropic.py | 6 +- 10 files changed, 193 insertions(+), 24 deletions(-) rename docprompt/tasks/classification/{anthropic.py => image.py} (92%) rename docprompt/tasks/markerize/{anthropic.py => image.py} (100%) rename docprompt/tasks/table_extraction/{anthropic.py => image_xml.py} (95%) diff --git a/docprompt/tasks/base.py b/docprompt/tasks/base.py index ec34ac8..9d46eea 100644 --- a/docprompt/tasks/base.py +++ b/docprompt/tasks/base.py @@ -1,7 +1,10 @@ +from abc import abstractmethod from typing import ( TYPE_CHECKING, Any, + Callable, ClassVar, + Coroutine, Dict, Generic, Iterable, @@ -10,6 +13,7 @@ TypeVar, Union, ) +from typing_extensions import ParamSpecKwargs from pydantic import BaseModel, PrivateAttr, ValidationInfo, model_validator from typing_extensions import Self @@ -21,7 +25,7 @@ from .util import _init_context_var, init_context if TYPE_CHECKING: - from docprompt.schema.pipeline import DocumentNode + from docprompt.schema.pipeline import DocumentNode, PageNode TTaskInput = TypeVar("TTaskInput") # What invoke requires @@ -168,6 +172,172 @@ async def aprocess_document_node( raise NotImplementedError +@flexible_methods( + ("get_openai_messages", "aget_openai_messages"), +) +class SupportsOpenAIMessages(Generic[TTaskInput]): + """ + Mixin for task providers that support OpenAI. + """ + + def get_openai_messages(self, input: TTaskInput, **kwargs) -> List[Dict[str, Any]]: + raise NotImplementedError + + async def aget_openai_messages(self, input: TTaskInput, **kwargs) -> Coroutine[None, None, Dict[str, Any]]: + raise NotImplementedError + + + +@flexible_methods( + ("parse", "aparse"), +) +class SupportsParsing(Generic[TTaskResult]): + """ + Mixin for task providers that support parsing. + """ + + def parse(self, response: str, **kwargs) -> TTaskResult: + raise NotImplementedError + + async def aparse(self, response: str, **kwargs) -> TTaskResult: + raise NotImplementedError + + +@flexible_methods( + ("process_page_node", "aprocess_page_node"), +) +class SupportsPageNode(Generic[TTaskConfig, TPageResult]): + """ + Mixin for task providers that support page processing. + """ + + def process_page_node( + self, + page_node: "PageNode", + task_config: Optional[TTaskConfig] = None, + **kwargs, + ) -> TPageResult: + raise NotImplementedError + + async def aprocess_page_node( + self, + page_node: "PageNode", + task_config: Optional[TTaskConfig] = None, + **kwargs, + ) -> TPageResult: + raise NotImplementedError + + +@flexible_methods( + ("invoke", "ainvoke") +) +class SupportsDirectInvocation(Generic[TTaskConfig, TTaskResult]): + """ + Mixin for task providers that support direct invocation on + non-node based items.s + """ + + def invoke( + self, + input: TTaskInput, + task_config: Optional[TTaskConfig] = None, + **kwargs, + ) -> TTaskResult: + raise NotImplementedError + + async def ainvoke( + self, + input: TTaskInput, + task_config: Optional[TTaskConfig] = None, + **kwargs, + ) -> TTaskResult: + raise NotImplementedError + + +@flexible_methods( + ("process_document_node", "aprocess_document_node"), +) +class SupportsDocumentNode(Generic[TTaskInput, TDocumentResult]): + """ + Mixin for task providers that support document processing. + """ + + def process_document_node( + self, + document_node: "DocumentNode", + task_config: Optional[TTaskConfig] = None, + **kwargs, + ) -> TDocumentResult: + raise NotImplementedError + + async def aprocess_document_node( + self, + document_node: "DocumentNode", + task_config: Optional[TTaskConfig] = None, + **kwargs, + ) -> TDocumentResult: + raise NotImplementedError + +@flexible_methods( + ("process_image", "aprocess_image"), +) +class SupportsImage(Generic[TTaskInput, TTaskResult]): + """ + Mixin for task providers that support image processing. + """ + + def process_image(self, input: TTaskInput, **kwargs) -> TTaskResult: + raise NotImplementedError + + async def aprocess_image(self, input: TTaskInput, **kwargs) -> TTaskResult: + raise NotImplementedError + + + +SyncOAICallable = Callable[[List[Dict[str, Any]]], Dict[str, Any]] +AsyncOAICallable = Coroutine[List[Dict[str, Any]], Dict[str, Any]] + +class ProviderAgnosticOAI: + def __init__(self, *args, sync_callable: SyncOAICallable = None, async_callable: AsyncOAICallable = None, **kwargs): + super().__init__(*args, **kwargs) + + self.sync_callable = sync_callable + self.async_callable = async_callable + + if not self.sync_callable and not self.async_callable: + raise ValueError(f"{self.__class__.__name__} must be initialized with either `sync_callable` and/or `async_callable`") + + +@flexible_methods( + ("process_webpage", "aprocess_webpage"), +) +class SupportsWebPage(Generic[TTaskInput, TPageResult]): + """ + Mixin for task providers that support webpage processing. + """ + + def process_webpage(self, input: TTaskInput, **kwargs) -> TPageResult: + raise NotImplementedError + + async def aprocess_webpage(self, input: TTaskInput, **kwargs) -> TPageResult: + raise NotImplementedError + + +class SupportsTaskConfig(Generic[TTaskConfig]): + def __init__(self, *args, task_config: TTaskConfig = None, **kwargs): + super().__init__(*args, **kwargs) + + self.task_config = task_config + + if not self.task_config: + raise ValueError(f"{self.__class__.__name__} must be initialized with `task_config`") + +class BaseLLMTask(SupportsOpenAIMessages, SupportsTaskConfig, ProviderAgnosticOAI, SupportsParsing, SupportsDirectInvocation, Generic[TTaskInput, TTaskConfig, TTaskResult]): + """ + Base class for LLM related tasks + """ + name: ClassVar[str] + class AbstractPageTaskProvider(AbstractTaskProvider): """ A page task provider performs a specific, repeatable task on a page. diff --git a/docprompt/tasks/classification/anthropic.py b/docprompt/tasks/classification/image.py similarity index 92% rename from docprompt/tasks/classification/anthropic.py rename to docprompt/tasks/classification/image.py index d93007f..816271c 100644 --- a/docprompt/tasks/classification/anthropic.py +++ b/docprompt/tasks/classification/image.py @@ -64,7 +64,7 @@ ) -class AnthropicPageClassificationOutputParser(BasePageClassificationOutputParser): +class ImagePageClassificationOutputParser(BasePageClassificationOutputParser): """The output parser for the page classification system.""" def parse(self, text: str) -> ClassificationOutput: @@ -122,20 +122,18 @@ def _prepare_messages( class AnthropicClassificationProvider(BaseClassificationProvider): """The Anthropic implementation of unscored page classification.""" - name = "anthropic" - - anthropic_model_name: str = Field("claude-3-haiku-20240307") + name = "image" async def _ainvoke( self, input: Iterable[bytes], config: ClassificationConfig = None, **kwargs ) -> List[ClassificationOutput]: messages = _prepare_messages(input, config) - parser = AnthropicPageClassificationOutputParser.from_task_input( + parser = ImagePageClassificationOutputParser.from_task_input( config, provider_name=self.name ) - model_name = kwargs.pop("model_name", self.anthropic_model_name) + model_name = kwargs.pop("model_name") completions = await inference.run_batch_inference_anthropic( model_name, messages, **kwargs ) diff --git a/docprompt/tasks/factory.py b/docprompt/tasks/factory.py index 4fff171..1e222d4 100644 --- a/docprompt/tasks/factory.py +++ b/docprompt/tasks/factory.py @@ -168,7 +168,7 @@ def _validate_provider(self, info: ValidationInfo) -> Self: def get_page_classification_provider(self, **kwargs) -> TTaskProvider: """Get the page classification provider.""" - from docprompt.tasks.classification.anthropic import ( + from docprompt.tasks.classification.image import ( AnthropicClassificationProvider, ) @@ -176,7 +176,7 @@ def get_page_classification_provider(self, **kwargs) -> TTaskProvider: def get_page_table_extraction_provider(self, **kwargs) -> TTaskProvider: """Get the page table extraction provider.""" - from docprompt.tasks.table_extraction.anthropic import ( + from docprompt.tasks.table_extraction.image_xml import ( AnthropicTableExtractionProvider, ) @@ -186,7 +186,7 @@ def get_page_table_extraction_provider(self, **kwargs) -> TTaskProvider: def get_page_markerization_provider(self, **kwargs) -> TTaskProvider: """Get the page markerization provider.""" - from docprompt.tasks.markerize.anthropic import AnthropicMarkerizeProvider + from docprompt.tasks.markerize.image import AnthropicMarkerizeProvider return AnthropicMarkerizeProvider( invoke_kwargs=self._credentials.kwargs, **kwargs diff --git a/docprompt/tasks/markerize/anthropic.py b/docprompt/tasks/markerize/image.py similarity index 100% rename from docprompt/tasks/markerize/anthropic.py rename to docprompt/tasks/markerize/image.py diff --git a/docprompt/tasks/result.py b/docprompt/tasks/result.py index 32151c8..d401f48 100644 --- a/docprompt/tasks/result.py +++ b/docprompt/tasks/result.py @@ -23,7 +23,6 @@ class BaseResult(BaseModel): def task_key(self): return f"{self.provider_name}_{self.task_name}" - @abstractmethod def contribute_to_document_node( self, document_node: "DocumentNode", **kwargs ) -> None: @@ -50,7 +49,7 @@ def contribute_to_document_node( page_number is not None ), "Page number must be provided for page level results" assert ( - 0 < page_number <= len(document_node) + 0 < page_number <= len(docume Bnt_node) ), "Page number must be less than or equal to the number of pages in the document" page_node = document_node.page_nodes[page_number - 1] diff --git a/docprompt/tasks/table_extraction/base.py b/docprompt/tasks/table_extraction/base.py index 8917173..811ff28 100644 --- a/docprompt/tasks/table_extraction/base.py +++ b/docprompt/tasks/table_extraction/base.py @@ -1,14 +1,17 @@ from typing import Optional from docprompt import DocumentNode -from docprompt.tasks.base import AbstractPageTaskProvider +from docprompt.tasks.base import AbstractPageTaskProvider, BaseLLMTask, SupportsDocumentNode, SupportsImage, SupportsPageNode from docprompt.tasks.capabilities import PageLevelCapabilities from .schema import TableExtractionPageResult class BaseTableExtractionProvider( - AbstractPageTaskProvider[bytes, None, TableExtractionPageResult] + SupportsDocumentNode, + SupportsPageNode, + SupportsImage, + BaseLLMTask[bytes, None, TableExtractionPageResult], ): capabilities = [ PageLevelCapabilities.PAGE_TABLE_EXTRACTION, @@ -17,6 +20,7 @@ class BaseTableExtractionProvider( class Meta: abstract = True + def process_document_node( self, @@ -35,7 +39,7 @@ def process_document_node( raster_bytes.append(image_bytes) # This will be a list of extracted tables?? - results = self._invoke(raster_bytes, config=task_config, **kwargs) + results = self.invoke(raster_bytes, config=task_config, **kwargs) return { i: res diff --git a/docprompt/tasks/table_extraction/anthropic.py b/docprompt/tasks/table_extraction/image_xml.py similarity index 95% rename from docprompt/tasks/table_extraction/anthropic.py rename to docprompt/tasks/table_extraction/image_xml.py index 0a33998..b1b4c99 100644 --- a/docprompt/tasks/table_extraction/anthropic.py +++ b/docprompt/tasks/table_extraction/image_xml.py @@ -125,10 +125,8 @@ def _prepare_messages( return messages -class AnthropicTableExtractionProvider(BaseTableExtractionProvider): - name = "anthropic" - - anthropic_model_name: str = Field("claude-3-haiku-20240307") +class ImageXmlTableExtractionProvider(BaseTableExtractionProvider): + name = "image_xml" async def _ainvoke( self, input: Iterable[bytes], config: Optional[None] = None, **kwargs diff --git a/tests/tasks/classification/test_anthropic.py b/tests/tasks/classification/test_anthropic.py index a1663d2..293bded 100644 --- a/tests/tasks/classification/test_anthropic.py +++ b/tests/tasks/classification/test_anthropic.py @@ -2,7 +2,7 @@ import pytest -from docprompt.tasks.classification.anthropic import ( +from docprompt.tasks.classification.image import ( AnthropicClassificationProvider, AnthropicPageClassificationOutputParser, _prepare_messages, diff --git a/tests/tasks/markerize/test_anthropic.py b/tests/tasks/markerize/test_anthropic.py index 38cb0e0..ec25286 100644 --- a/tests/tasks/markerize/test_anthropic.py +++ b/tests/tasks/markerize/test_anthropic.py @@ -6,7 +6,7 @@ import pytest -from docprompt.tasks.markerize.anthropic import ( +from docprompt.tasks.markerize.image import ( AnthropicMarkerizeProvider, _parse_result, _prepare_messages, diff --git a/tests/tasks/table_extraction/test_anthropic.py b/tests/tasks/table_extraction/test_anthropic.py index ecbbf22..a435859 100644 --- a/tests/tasks/table_extraction/test_anthropic.py +++ b/tests/tasks/table_extraction/test_anthropic.py @@ -8,7 +8,7 @@ from bs4 import BeautifulSoup from docprompt.tasks.message import OpenAIComplexContent, OpenAIImageURL, OpenAIMessage -from docprompt.tasks.table_extraction.anthropic import ( +from docprompt.tasks.table_extraction.image_xml import ( AnthropicTableExtractionProvider, _headers_from_tree, _prepare_messages, @@ -161,7 +161,7 @@ def test_rows_from_tree(): ], ) def test_find_start_indices(input_str, sub_str, expected): - from docprompt.tasks.table_extraction.anthropic import _find_start_indices + from docprompt.tasks.table_extraction.image_xml import _find_start_indices assert _find_start_indices(input_str, sub_str) == expected @@ -175,6 +175,6 @@ def test_find_start_indices(input_str, sub_str, expected): ], ) def test_find_end_indices(input_str, sub_str, expected): - from docprompt.tasks.table_extraction.anthropic import _find_end_indices + from docprompt.tasks.table_extraction.image_xml import _find_end_indices assert _find_end_indices(input_str, sub_str) == expected From 97b514f03194b24de2d6b694536f32f1d8861fd1 Mon Sep 17 00:00:00 2001 From: Frank Colson Date: Sat, 5 Oct 2024 12:44:54 -0600 Subject: [PATCH 2/2] Work on task refactor further --- docprompt/contrib/litellm.py | 33 +++ docprompt/contrib/parser_bot/__init__.py | 0 docprompt/tasks/base.py | 136 +++++----- docprompt/tasks/markerize/base.py | 53 ++-- docprompt/tasks/markerize/image.py | 96 +++++-- docprompt/tasks/result.py | 3 +- pdm.lock | 328 +++++++++++++++++++---- pyproject.toml | 3 + 8 files changed, 487 insertions(+), 165 deletions(-) create mode 100644 docprompt/contrib/litellm.py delete mode 100644 docprompt/contrib/parser_bot/__init__.py diff --git a/docprompt/contrib/litellm.py b/docprompt/contrib/litellm.py new file mode 100644 index 0000000..2735cee --- /dev/null +++ b/docprompt/contrib/litellm.py @@ -0,0 +1,33 @@ +from typing import Any, Dict, List + +try: + import litellm +except ImportError: + print( + "litellm is required for this function. Install with `pip install docprompt[litellm]`" + ) + raise + + +def get_sync_litellm_callable(model: str, /, **kwargs): + if "messages" in kwargs: + raise ValueError("messages should only be passed at runtime") + + def wrapper(messages: List[Dict[str, Any]]): + response = litellm.completion(model=model, messages=messages, **kwargs) + + return response.to_dict() + + return wrapper + + +def get_async_litellm_callable(model: str, /, **kwargs): + if "messages" in kwargs: + raise ValueError("messages should only be passed at runtime") + + async def wrapper(messages: List[Dict[str, Any]]): + response = await litellm.acompletion(model=model, messages=messages, **kwargs) + + return response.to_dict() + + return wrapper diff --git a/docprompt/contrib/parser_bot/__init__.py b/docprompt/contrib/parser_bot/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/docprompt/tasks/base.py b/docprompt/tasks/base.py index 9d46eea..f9bbaed 100644 --- a/docprompt/tasks/base.py +++ b/docprompt/tasks/base.py @@ -1,4 +1,3 @@ -from abc import abstractmethod from typing import ( TYPE_CHECKING, Any, @@ -10,13 +9,22 @@ Iterable, List, Optional, + Type, + TypedDict, TypeVar, Union, ) -from typing_extensions import ParamSpecKwargs -from pydantic import BaseModel, PrivateAttr, ValidationInfo, model_validator -from typing_extensions import Self +from pydantic import ( + BaseModel, + Field, + GetCoreSchemaHandler, + PrivateAttr, + ValidationInfo, + model_validator, +) +from pydantic_core import core_schema +from typing_extensions import Annotated, Self from docprompt._decorators import flexible_methods @@ -39,6 +47,16 @@ ) +class NullSchema: + def __get_pydantic_core_schema__( + self, source: Type[Any], handler: GetCoreSchemaHandler + ): + def noop_validate(value: Any) -> Any: + return value + + return core_schema.no_info_plain_validator_function(noop_validate) + + @flexible_methods( ("process_document_node", "aprocess_document_node"), ("_invoke", "_ainvoke"), @@ -172,26 +190,21 @@ async def aprocess_document_node( raise NotImplementedError -@flexible_methods( - ("get_openai_messages", "aget_openai_messages"), -) -class SupportsOpenAIMessages(Generic[TTaskInput]): +class SupportsOpenAIMessages(BaseModel, Generic[TTaskInput]): """ Mixin for task providers that support OpenAI. """ def get_openai_messages(self, input: TTaskInput, **kwargs) -> List[Dict[str, Any]]: raise NotImplementedError - - async def aget_openai_messages(self, input: TTaskInput, **kwargs) -> Coroutine[None, None, Dict[str, Any]]: - raise NotImplementedError + async def aget_openai_messages( + self, input: TTaskInput, **kwargs + ) -> Coroutine[None, None, Dict[str, Any]]: + raise NotImplementedError -@flexible_methods( - ("parse", "aparse"), -) -class SupportsParsing(Generic[TTaskResult]): +class SupportsParsing(BaseModel, Generic[TTaskResult]): """ Mixin for task providers that support parsing. """ @@ -201,12 +214,9 @@ def parse(self, response: str, **kwargs) -> TTaskResult: async def aparse(self, response: str, **kwargs) -> TTaskResult: raise NotImplementedError - -@flexible_methods( - ("process_page_node", "aprocess_page_node"), -) -class SupportsPageNode(Generic[TTaskConfig, TPageResult]): + +class SupportsPageNode(BaseModel, Generic[TTaskConfig, TPageResult]): """ Mixin for task providers that support page processing. """ @@ -226,38 +236,28 @@ async def aprocess_page_node( **kwargs, ) -> TPageResult: raise NotImplementedError - -@flexible_methods( - ("invoke", "ainvoke") -) -class SupportsDirectInvocation(Generic[TTaskConfig, TTaskResult]): + +class SupportsDirectInvocation( + BaseModel, Generic[TTaskInput, TTaskConfig, TTaskResult] +): """ Mixin for task providers that support direct invocation on non-node based items.s """ def invoke( - self, - input: TTaskInput, - task_config: Optional[TTaskConfig] = None, - **kwargs, + self, input: TTaskInput, config: Optional[TTaskConfig] = None, **kwargs ) -> TTaskResult: raise NotImplementedError async def ainvoke( - self, - input: TTaskInput, - task_config: Optional[TTaskConfig] = None, - **kwargs, + self, input: TTaskInput, config: Optional[TTaskConfig] = None, **kwargs ) -> TTaskResult: raise NotImplementedError - -@flexible_methods( - ("process_document_node", "aprocess_document_node"), -) -class SupportsDocumentNode(Generic[TTaskInput, TDocumentResult]): + +class SupportsDocumentNode(BaseModel, Generic[TTaskInput, TDocumentResult]): """ Mixin for task providers that support document processing. """ @@ -278,10 +278,11 @@ async def aprocess_document_node( ) -> TDocumentResult: raise NotImplementedError + @flexible_methods( ("process_image", "aprocess_image"), ) -class SupportsImage(Generic[TTaskInput, TTaskResult]): +class SupportsImage(BaseModel, Generic[TTaskInput, TTaskResult]): """ Mixin for task providers that support image processing. """ @@ -291,27 +292,48 @@ def process_image(self, input: TTaskInput, **kwargs) -> TTaskResult: async def aprocess_image(self, input: TTaskInput, **kwargs) -> TTaskResult: raise NotImplementedError - -SyncOAICallable = Callable[[List[Dict[str, Any]]], Dict[str, Any]] -AsyncOAICallable = Coroutine[List[Dict[str, Any]], Dict[str, Any]] +class OpenAIMessageItem(TypedDict): + content: str + + +class OpenAiChoiceItem(TypedDict): + finish_reason: str + index: int + message: OpenAIMessageItem + + +class OpenAICompletionResponse(TypedDict): + choices: List[OpenAiChoiceItem] -class ProviderAgnosticOAI: - def __init__(self, *args, sync_callable: SyncOAICallable = None, async_callable: AsyncOAICallable = None, **kwargs): - super().__init__(*args, **kwargs) - self.sync_callable = sync_callable - self.async_callable = async_callable +SyncOAICallable = Callable[[List[Dict[str, Any]]], OpenAICompletionResponse] +AsyncOAICallable = Coroutine[List[Dict[str, Any]], None, OpenAICompletionResponse] + +class ProviderAgnosticOAI(BaseModel): + sync_callable: Annotated[SyncOAICallable, NullSchema()] = Field( + default=None, exclude=True + ) + async_callable: Annotated[AsyncOAICallable, NullSchema()] = Field( + default=None, exclude=True + ) + + @model_validator(mode="after") + def validate_callable(self): if not self.sync_callable and not self.async_callable: - raise ValueError(f"{self.__class__.__name__} must be initialized with either `sync_callable` and/or `async_callable`") + raise ValueError( + f"{self.__class__.__name__} must be initialized with either `sync_callable` and/or `async_callable`" + ) + + return self @flexible_methods( ("process_webpage", "aprocess_webpage"), ) -class SupportsWebPage(Generic[TTaskInput, TPageResult]): +class SupportsWebPage(BaseModel, Generic[TTaskInput, TPageResult]): """ Mixin for task providers that support webpage processing. """ @@ -323,20 +345,12 @@ async def aprocess_webpage(self, input: TTaskInput, **kwargs) -> TPageResult: raise NotImplementedError -class SupportsTaskConfig(Generic[TTaskConfig]): - def __init__(self, *args, task_config: TTaskConfig = None, **kwargs): - super().__init__(*args, **kwargs) - - self.task_config = task_config +class SupportsTaskConfig(BaseModel, Generic[TTaskConfig]): + task_config: TTaskConfig = None - if not self.task_config: - raise ValueError(f"{self.__class__.__name__} must be initialized with `task_config`") + def get_config(self) -> TTaskConfig: + return self.task_config -class BaseLLMTask(SupportsOpenAIMessages, SupportsTaskConfig, ProviderAgnosticOAI, SupportsParsing, SupportsDirectInvocation, Generic[TTaskInput, TTaskConfig, TTaskResult]): - """ - Base class for LLM related tasks - """ - name: ClassVar[str] class AbstractPageTaskProvider(AbstractTaskProvider): """ diff --git a/docprompt/tasks/markerize/base.py b/docprompt/tasks/markerize/base.py index 5d007f4..294c0e1 100644 --- a/docprompt/tasks/markerize/base.py +++ b/docprompt/tasks/markerize/base.py @@ -1,9 +1,15 @@ from typing import Optional -from docprompt.schema.pipeline.node.document import DocumentNode -from docprompt.tasks.base import AbstractPageTaskProvider, BasePageResult +from pydantic import BaseModel -from ..capabilities import PageLevelCapabilities +from docprompt.tasks.base import ( + BasePageResult, + ProviderAgnosticOAI, + SupportsDirectInvocation, + SupportsOpenAIMessages, + SupportsParsing, + SupportsTaskConfig, +) class MarkerizeResult(BasePageResult): @@ -11,36 +17,17 @@ class MarkerizeResult(BasePageResult): raw_markdown: str -class BaseMarkerizeProvider(AbstractPageTaskProvider[bytes, None, MarkerizeResult]): - capabilities = [PageLevelCapabilities.PAGE_MARKERIZATION] +class MarkerizeConfig(BaseModel): + system_prompt: Optional[str] = None + human_prompt: Optional[str] = None + +class BaseLLMMarkerizeProvider( + ProviderAgnosticOAI, + SupportsTaskConfig[MarkerizeConfig], + SupportsOpenAIMessages[bytes], + SupportsDirectInvocation[bytes, MarkerizeConfig, MarkerizeResult], + SupportsParsing[MarkerizeResult], +): class Meta: abstract = True - - def process_document_node( - self, - document_node: "DocumentNode", - task_config: Optional[None] = None, - start: Optional[int] = None, - stop: Optional[int] = None, - contribute_to_document: bool = True, - **kwargs, - ): - raster_bytes = [] - for page_number in range(start or 1, (stop or len(document_node)) + 1): - image_bytes = document_node.page_nodes[ - page_number - 1 - ].rasterizer.rasterize("default") - raster_bytes.append(image_bytes) - - # TODO: This is a somewhat dangerous way of requiring these kwargs to be drilled - # through, potentially a decorator solution to be had here - kwargs = {**self._default_invoke_kwargs, **kwargs} - results = self._invoke(raster_bytes, config=task_config, **kwargs) - - return { - i: res - for i, res in zip( - range(start or 1, (stop or len(document_node)) + 1), results - ) - } diff --git a/docprompt/tasks/markerize/image.py b/docprompt/tasks/markerize/image.py index c6a25b1..9931a58 100644 --- a/docprompt/tasks/markerize/image.py +++ b/docprompt/tasks/markerize/image.py @@ -1,12 +1,12 @@ -from typing import Iterable, List, Optional +import asyncio +import base64 +from typing import ClassVar, Iterable, List, Optional from bs4 import BeautifulSoup -from pydantic import Field from docprompt.tasks.message import OpenAIComplexContent, OpenAIImageURL, OpenAIMessage -from docprompt.utils import inference -from .base import BaseMarkerizeProvider, MarkerizeResult +from .base import BaseLLMMarkerizeProvider, MarkerizeConfig, MarkerizeResult _HUMAN_MESSAGE_PROMPT = """ Convert the image into markdown, preserving the overall layout and style of the page. \ @@ -35,13 +35,19 @@ def _parse_result(raw_markdown: str) -> Optional[str]: return md.text.strip() if md else "" # TODO Fix bad extractions +def _image_bytes_to_url(image_bytes: bytes) -> str: + encoded = base64.b64encode(image_bytes).decode("utf-8") + return f"data:image/jpeg;base64,{encoded}" + + def _prepare_messages( document_images: Iterable[bytes], - start: Optional[int] = None, - stop: Optional[int] = None, + config: MarkerizeConfig, ): messages = [] + human_message = config.human_prompt or _HUMAN_MESSAGE_PROMPT + for image_bytes in document_images: messages.append( [ @@ -50,33 +56,79 @@ def _prepare_messages( content=[ OpenAIComplexContent( type="image_url", - image_url=OpenAIImageURL(url=image_bytes), + image_url=OpenAIImageURL( + url=_image_bytes_to_url(image_bytes) + ), ), - OpenAIComplexContent(type="text", text=_HUMAN_MESSAGE_PROMPT), + OpenAIComplexContent(type="text", text=human_message), ], - ), + ).model_dump() ] ) return messages -class AnthropicMarkerizeProvider(BaseMarkerizeProvider): - name = "anthropic" +class GenericMarkerizeProvider(BaseLLMMarkerizeProvider): + name: ClassVar[str] = "markerize" + + def model_post_init(self, __context): + self.task_config = self.task_config or self._get_default_markerize_config() + + if not self.async_callable: + + async def async_callable(messages): + result = await asyncio.to_thread(self.sync_callable, messages) + + return result + + self.async_callable = async_callable + + def _get_default_markerize_config(self): + return MarkerizeConfig( + human_prompt=_HUMAN_MESSAGE_PROMPT, + ) + + async def ainvoke( + self, input: Iterable[bytes], config: Optional[MarkerizeConfig] = None, **kwargs + ) -> List[MarkerizeResult]: + config = config or self._get_default_markerize_config() + + messages = self.get_openai_messages(input, config=config) + + coroutines = [self.async_callable(x) for x in messages] + + result = await asyncio.gather(*coroutines) + + final = [] + + for x in result: + text = x["choices"][0]["message"]["content"] + parsed = self.parse(text) + final.append(parsed) - anthropic_model_name: str = Field("claude-3-haiku-20240307") + return final - async def _ainvoke( - self, input: Iterable[bytes], config: Optional[None] = None, **kwargs + def invoke( + self, input: Iterable[bytes], config: Optional[MarkerizeConfig] = None, **kwargs ) -> List[MarkerizeResult]: - messages = _prepare_messages(input) + config = config or self._get_default_markerize_config() + + result = asyncio.run(self.ainvoke(input, config, **kwargs)) + + return result + + def get_openai_messages( + self, input: Iterable[bytes], config: Optional[MarkerizeConfig] = None, **kwargs + ): + return _prepare_messages( + input, config or self.task_config or self._get_default_markerize_config() + ) - model_name = kwargs.pop("model_name", self.anthropic_model_name) - completions = await inference.run_batch_inference_anthropic( - model_name, messages, **kwargs + def parse(self, response: str): + return MarkerizeResult( + raw_markdown=_parse_result(response), provider_name=self.name ) - return [ - MarkerizeResult(raw_markdown=_parse_result(x), provider_name=self.name) - for x in completions - ] + async def aparse(self, response: str, **kwargs) -> MarkerizeResult: + return self.parse(response) diff --git a/docprompt/tasks/result.py b/docprompt/tasks/result.py index d401f48..568653d 100644 --- a/docprompt/tasks/result.py +++ b/docprompt/tasks/result.py @@ -1,4 +1,3 @@ -from abc import abstractmethod from collections.abc import MutableMapping from datetime import datetime from typing import TYPE_CHECKING, ClassVar, Dict, Generic, Optional, TypeVar @@ -49,7 +48,7 @@ def contribute_to_document_node( page_number is not None ), "Page number must be provided for page level results" assert ( - 0 < page_number <= len(docume Bnt_node) + 0 < page_number <= len(document_node) ), "Page number must be less than or equal to the number of pages in the document" page_node = document_node.page_nodes[page_number - 1] diff --git a/pdm.lock b/pdm.lock index 8fd8e3a..88f0a9c 100644 --- a/pdm.lock +++ b/pdm.lock @@ -2,10 +2,10 @@ # It is not intended for manual editing. [metadata] -groups = ["default", "anthropic", "aws", "azure", "dev", "docs", "google", "openai", "search", "test"] +groups = ["default", "anthropic", "aws", "azure", "dev", "docs", "google", "litellm", "openai", "search", "test"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:4cc474c5e361c27591cf6a9fe401fc6802e917f4033d30bd846d3eeb118d336f" +content_hash = "sha256:4a2307e64ec72b1c52f5a17cacd7494a2058de28beba1532335b510a98730091" [[metadata.targets]] requires_python = ">=3.8.6,<3.13" @@ -74,7 +74,7 @@ name = "aiohttp" version = "3.9.5" requires_python = ">=3.8" summary = "Async http client/server framework (asyncio)" -groups = ["aws"] +groups = ["aws", "litellm"] dependencies = [ "aiosignal>=1.1.2", "async-timeout<5.0,>=4.0; python_version < \"3.11\"", @@ -181,7 +181,7 @@ name = "aiosignal" version = "1.3.1" requires_python = ">=3.7" summary = "aiosignal: a list of registered asynchronous callbacks" -groups = ["aws"] +groups = ["aws", "litellm"] dependencies = [ "frozenlist>=1.1.0", ] @@ -195,7 +195,7 @@ name = "annotated-types" version = "0.7.0" requires_python = ">=3.8" summary = "Reusable constraint types to use with typing.Annotated" -groups = ["default", "anthropic", "openai"] +groups = ["default", "anthropic", "litellm", "openai"] dependencies = [ "typing-extensions>=4.0.0; python_version < \"3.9\"", ] @@ -231,7 +231,7 @@ name = "anyio" version = "4.4.0" requires_python = ">=3.8" summary = "High level compatibility layer for multiple asynchronous event loop implementations" -groups = ["anthropic", "openai"] +groups = ["anthropic", "litellm", "openai"] dependencies = [ "exceptiongroup>=1.0.2; python_version < \"3.11\"", "idna>=2.8", @@ -289,7 +289,7 @@ name = "async-timeout" version = "4.0.3" requires_python = ">=3.7" summary = "Timeout context manager for asyncio programs" -groups = ["aws"] +groups = ["aws", "litellm"] marker = "python_version < \"3.11\"" dependencies = [ "typing-extensions>=3.6.5; python_version < \"3.8\"", @@ -304,7 +304,7 @@ name = "attrs" version = "23.2.0" requires_python = ">=3.7" summary = "Classes Without Boilerplate" -groups = ["aws"] +groups = ["aws", "litellm"] dependencies = [ "importlib-metadata; python_version < \"3.8\"", ] @@ -481,7 +481,7 @@ name = "certifi" version = "2024.7.4" requires_python = ">=3.6" summary = "Python package for providing Mozilla's CA Bundle." -groups = ["anthropic", "azure", "dev", "docs", "google", "openai"] +groups = ["anthropic", "azure", "dev", "docs", "google", "litellm", "openai"] files = [ {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, @@ -568,7 +568,7 @@ name = "charset-normalizer" version = "3.3.2" requires_python = ">=3.7.0" summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -groups = ["anthropic", "azure", "dev", "docs", "google"] +groups = ["anthropic", "azure", "dev", "docs", "google", "litellm"] 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"}, @@ -654,7 +654,7 @@ name = "click" version = "8.1.7" requires_python = ">=3.7" summary = "Composable command line interface toolkit" -groups = ["docs"] +groups = ["docs", "litellm"] dependencies = [ "colorama; platform_system == \"Windows\"", "importlib-metadata; python_version < \"3.8\"", @@ -669,7 +669,7 @@ name = "colorama" version = "0.4.6" requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" summary = "Cross-platform colored terminal text." -groups = ["default", "anthropic", "dev", "docs", "openai", "test"] +groups = ["default", "anthropic", "dev", "docs", "litellm", "openai", "test"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -913,7 +913,7 @@ name = "distro" version = "1.9.0" requires_python = ">=3.6" summary = "Distro - an OS platform information API" -groups = ["anthropic", "openai"] +groups = ["anthropic", "litellm", "openai"] files = [ {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, @@ -935,7 +935,7 @@ name = "exceptiongroup" version = "1.2.2" requires_python = ">=3.7" summary = "Backport of PEP 654 (exception groups)" -groups = ["anthropic", "dev", "openai", "test"] +groups = ["anthropic", "dev", "litellm", "openai", "test"] marker = "python_version < \"3.11\"" files = [ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, @@ -958,7 +958,7 @@ name = "filelock" version = "3.15.4" requires_python = ">=3.8" summary = "A platform independent file lock." -groups = ["anthropic", "dev"] +groups = ["anthropic", "dev", "litellm"] files = [ {file = "filelock-3.15.4-py3-none-any.whl", hash = "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7"}, {file = "filelock-3.15.4.tar.gz", hash = "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb"}, @@ -1010,7 +1010,7 @@ name = "frozenlist" version = "1.4.1" requires_python = ">=3.8" summary = "A list-like structure which implements collections.abc.MutableSequence" -groups = ["aws"] +groups = ["aws", "litellm"] files = [ {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, @@ -1096,7 +1096,7 @@ name = "fsspec" version = "2024.6.1" requires_python = ">=3.8" summary = "File-system specification" -groups = ["default", "anthropic"] +groups = ["default", "anthropic", "litellm"] files = [ {file = "fsspec-2024.6.1-py3-none-any.whl", hash = "sha256:3cb443f8bcd2efb31295a5b9fdb02aee81d8452c80d28f97a6d0959e6cee101e"}, {file = "fsspec-2024.6.1.tar.gz", hash = "sha256:fad7d7e209dd4c1208e3bbfda706620e0da5142bebbd9c384afb95b07e798e49"}, @@ -1291,7 +1291,7 @@ name = "h11" version = "0.14.0" requires_python = ">=3.7" summary = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -groups = ["anthropic", "openai"] +groups = ["anthropic", "litellm", "openai"] dependencies = [ "typing-extensions; python_version < \"3.8\"", ] @@ -1305,7 +1305,7 @@ name = "httpcore" version = "1.0.5" requires_python = ">=3.8" summary = "A minimal low-level HTTP client." -groups = ["anthropic", "openai"] +groups = ["anthropic", "litellm", "openai"] dependencies = [ "certifi", "h11<0.15,>=0.13", @@ -1320,7 +1320,7 @@ name = "httpx" version = "0.27.0" requires_python = ">=3.8" summary = "The next generation HTTP client." -groups = ["anthropic", "openai"] +groups = ["anthropic", "litellm", "openai"] dependencies = [ "anyio", "certifi", @@ -1338,7 +1338,7 @@ name = "huggingface-hub" version = "0.24.3" requires_python = ">=3.8.0" summary = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" -groups = ["anthropic"] +groups = ["anthropic", "litellm"] dependencies = [ "filelock", "fsspec>=2023.5.0", @@ -1369,7 +1369,7 @@ name = "idna" version = "3.7" requires_python = ">=3.5" summary = "Internationalized Domain Names in Applications (IDNA)" -groups = ["anthropic", "aws", "azure", "dev", "docs", "google", "openai"] +groups = ["anthropic", "aws", "azure", "dev", "docs", "google", "litellm", "openai"] files = [ {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, @@ -1380,7 +1380,7 @@ name = "importlib-metadata" version = "8.2.0" requires_python = ">=3.8" summary = "Read metadata from Python packages" -groups = ["dev", "docs"] +groups = ["dev", "docs", "litellm"] dependencies = [ "typing-extensions>=3.6.4; python_version < \"3.8\"", "zipp>=0.5", @@ -1395,7 +1395,7 @@ name = "importlib-resources" version = "6.4.0" requires_python = ">=3.8" summary = "Read resources from Python packages" -groups = ["dev"] +groups = ["dev", "litellm"] marker = "python_version < \"3.9\"" dependencies = [ "zipp>=3.1.0; python_version < \"3.10\"", @@ -1565,7 +1565,7 @@ name = "jinja2" version = "3.1.4" requires_python = ">=3.7" summary = "A very fast and expressive template engine." -groups = ["docs"] +groups = ["docs", "litellm"] dependencies = [ "MarkupSafe>=2.0", ] @@ -1579,7 +1579,7 @@ name = "jiter" version = "0.5.0" requires_python = ">=3.8" summary = "Fast iterable JSON parser." -groups = ["anthropic"] +groups = ["anthropic", "litellm", "openai"] files = [ {file = "jiter-0.5.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b599f4e89b3def9a94091e6ee52e1d7ad7bc33e238ebb9c4c63f211d74822c3f"}, {file = "jiter-0.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a063f71c4b06225543dddadbe09d203dc0c95ba352d8b85f1221173480a71d5"}, @@ -1655,6 +1655,40 @@ files = [ {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, ] +[[package]] +name = "jsonschema" +version = "4.23.0" +requires_python = ">=3.8" +summary = "An implementation of JSON Schema validation for Python" +groups = ["litellm"] +dependencies = [ + "attrs>=22.2.0", + "importlib-resources>=1.4.0; python_version < \"3.9\"", + "jsonschema-specifications>=2023.03.6", + "pkgutil-resolve-name>=1.3.10; python_version < \"3.9\"", + "referencing>=0.28.4", + "rpds-py>=0.7.1", +] +files = [ + {file = "jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"}, + {file = "jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4"}, +] + +[[package]] +name = "jsonschema-specifications" +version = "2023.12.1" +requires_python = ">=3.8" +summary = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +groups = ["litellm"] +dependencies = [ + "importlib-resources>=1.4.0; python_version < \"3.9\"", + "referencing>=0.31.0", +] +files = [ + {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, + {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, +] + [[package]] name = "jupyter-client" version = "8.6.2" @@ -1711,6 +1745,30 @@ files = [ {file = "keyring-25.2.1.tar.gz", hash = "sha256:daaffd42dbda25ddafb1ad5fec4024e5bbcfe424597ca1ca452b299861e49f1b"}, ] +[[package]] +name = "litellm" +version = "1.48.14" +requires_python = "!=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,!=3.7.*,>=3.8" +summary = "Library to easily interface with LLM API providers" +groups = ["litellm"] +dependencies = [ + "aiohttp", + "click", + "importlib-metadata>=6.8.0", + "jinja2<4.0.0,>=3.1.2", + "jsonschema<5.0.0,>=4.22.0", + "openai>=1.51.0", + "pydantic<3.0.0,>=2.0.0", + "python-dotenv>=0.2.0", + "requests<3.0.0,>=2.31.0", + "tiktoken>=0.7.0", + "tokenizers", +] +files = [ + {file = "litellm-1.48.14-py3-none-any.whl", hash = "sha256:d5f86cd7c06d6657151d09b032a1107ca57b9207d796e497a7e0ac001a8fbe6c"}, + {file = "litellm-1.48.14.tar.gz", hash = "sha256:eed3e1b3b9de8784e88a71318f6ac1157aa15664e70c0936380d90b0c7ec6629"}, +] + [[package]] name = "markdown" version = "3.6" @@ -1730,7 +1788,7 @@ name = "markupsafe" version = "2.1.5" requires_python = ">=3.7" summary = "Safely add untrusted strings to HTML/XML markup." -groups = ["docs"] +groups = ["docs", "litellm"] files = [ {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, @@ -2041,7 +2099,7 @@ name = "multidict" version = "6.0.5" requires_python = ">=3.7" summary = "multidict implementation" -groups = ["aws"] +groups = ["aws", "litellm"] files = [ {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, @@ -2244,23 +2302,24 @@ files = [ [[package]] name = "openai" -version = "1.37.1" +version = "1.51.0" requires_python = ">=3.7.1" summary = "The official Python library for the openai API" -groups = ["openai"] +groups = ["litellm", "openai"] dependencies = [ "anyio<5,>=3.5.0", "cached-property; python_version < \"3.8\"", "distro<2,>=1.7.0", "httpx<1,>=0.23.0", + "jiter<1,>=0.4.0", "pydantic<3,>=1.9.0", "sniffio", "tqdm>4", - "typing-extensions<5,>=4.7", + "typing-extensions<5,>=4.11", ] files = [ - {file = "openai-1.37.1-py3-none-any.whl", hash = "sha256:9a6adda0d6ae8fce02d235c5671c399cfa40d6a281b3628914c7ebf244888ee3"}, - {file = "openai-1.37.1.tar.gz", hash = "sha256:faf87206785a6b5d9e34555d6a3242482a6852bc802e453e2a891f68ee04ce55"}, + {file = "openai-1.51.0-py3-none-any.whl", hash = "sha256:d9affafb7e51e5a27dce78589d4964ce4d6f6d560307265933a94b2e3f3c5d2c"}, + {file = "openai-1.51.0.tar.gz", hash = "sha256:8dc4f9d75ccdd5466fc8c99a952186eddceb9fd6ba694044773f3736a847149d"}, ] [[package]] @@ -2268,7 +2327,7 @@ name = "packaging" version = "24.1" requires_python = ">=3.8" summary = "Core utilities for Python packages" -groups = ["anthropic", "dev", "docs", "test"] +groups = ["anthropic", "dev", "docs", "litellm", "test"] files = [ {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, @@ -2432,6 +2491,18 @@ files = [ {file = "pkginfo-1.11.1.tar.gz", hash = "sha256:2e0dca1cf4c8e39644eed32408ea9966ee15e0d324c62ba899a393b3c6b467aa"}, ] +[[package]] +name = "pkgutil-resolve-name" +version = "1.3.10" +requires_python = ">=3.6" +summary = "Resolve a name to an object." +groups = ["litellm"] +marker = "python_version < \"3.9\"" +files = [ + {file = "pkgutil_resolve_name-1.3.10-py3-none-any.whl", hash = "sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e"}, + {file = "pkgutil_resolve_name-1.3.10.tar.gz", hash = "sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174"}, +] + [[package]] name = "platformdirs" version = "4.2.2" @@ -2622,7 +2693,7 @@ name = "pydantic" version = "2.8.2" requires_python = ">=3.8" summary = "Data validation using Python type hints" -groups = ["default", "anthropic", "openai"] +groups = ["default", "anthropic", "litellm", "openai"] dependencies = [ "annotated-types>=0.4.0", "pydantic-core==2.20.1", @@ -2639,7 +2710,7 @@ name = "pydantic-core" version = "2.20.1" requires_python = ">=3.8" summary = "Core functionality for Pydantic validation and serialization" -groups = ["default", "anthropic", "openai"] +groups = ["default", "anthropic", "litellm", "openai"] dependencies = [ "typing-extensions!=4.7.0,>=4.6.0", ] @@ -2880,7 +2951,7 @@ name = "python-dotenv" version = "1.0.1" requires_python = ">=3.8" summary = "Read key-value pairs from a .env file and set them as environment variables" -groups = ["dev"] +groups = ["dev", "litellm"] files = [ {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, @@ -2935,7 +3006,7 @@ name = "pyyaml" version = "6.0.1" requires_python = ">=3.6" summary = "YAML parser and emitter for Python" -groups = ["anthropic", "dev", "docs"] +groups = ["anthropic", "dev", "docs", "litellm"] files = [ {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, @@ -3196,12 +3267,27 @@ files = [ {file = "readme_renderer-43.0.tar.gz", hash = "sha256:1818dd28140813509eeed8d62687f7cd4f7bad90d4db586001c5dc09d4fde311"}, ] +[[package]] +name = "referencing" +version = "0.35.1" +requires_python = ">=3.8" +summary = "JSON Referencing + Python" +groups = ["litellm"] +dependencies = [ + "attrs>=22.2.0", + "rpds-py>=0.7.0", +] +files = [ + {file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"}, + {file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"}, +] + [[package]] name = "regex" version = "2024.7.24" requires_python = ">=3.8" summary = "Alternative regular expression module, to replace re." -groups = ["docs"] +groups = ["docs", "litellm"] files = [ {file = "regex-2024.7.24-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b0d3f567fafa0633aee87f08b9276c7062da9616931382993c03808bb68ce"}, {file = "regex-2024.7.24-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3426de3b91d1bc73249042742f45c2148803c111d1175b283270177fdf669024"}, @@ -3289,7 +3375,7 @@ name = "requests" version = "2.32.3" requires_python = ">=3.8" summary = "Python HTTP for Humans." -groups = ["anthropic", "azure", "dev", "docs", "google"] +groups = ["anthropic", "azure", "dev", "docs", "google", "litellm"] dependencies = [ "certifi>=2017.4.17", "charset-normalizer<4,>=2", @@ -3341,6 +3427,105 @@ files = [ {file = "rfc3986-2.0.0.tar.gz", hash = "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c"}, ] +[[package]] +name = "rpds-py" +version = "0.20.0" +requires_python = ">=3.8" +summary = "Python bindings to Rust's persistent data structures (rpds)" +groups = ["litellm"] +files = [ + {file = "rpds_py-0.20.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3ad0fda1635f8439cde85c700f964b23ed5fc2d28016b32b9ee5fe30da5c84e2"}, + {file = "rpds_py-0.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9bb4a0d90fdb03437c109a17eade42dfbf6190408f29b2744114d11586611d6f"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6377e647bbfd0a0b159fe557f2c6c602c159fc752fa316572f012fc0bf67150"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb851b7df9dda52dc1415ebee12362047ce771fc36914586b2e9fcbd7d293b3e"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e0f80b739e5a8f54837be5d5c924483996b603d5502bfff79bf33da06164ee2"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a8c94dad2e45324fc74dce25e1645d4d14df9a4e54a30fa0ae8bad9a63928e3"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8e604fe73ba048c06085beaf51147eaec7df856824bfe7b98657cf436623daf"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:df3de6b7726b52966edf29663e57306b23ef775faf0ac01a3e9f4012a24a4140"}, + {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf258ede5bc22a45c8e726b29835b9303c285ab46fc7c3a4cc770736b5304c9f"}, + {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:55fea87029cded5df854ca7e192ec7bdb7ecd1d9a3f63d5c4eb09148acf4a7ce"}, + {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ae94bd0b2f02c28e199e9bc51485d0c5601f58780636185660f86bf80c89af94"}, + {file = "rpds_py-0.20.0-cp310-none-win32.whl", hash = "sha256:28527c685f237c05445efec62426d285e47a58fb05ba0090a4340b73ecda6dee"}, + {file = "rpds_py-0.20.0-cp310-none-win_amd64.whl", hash = "sha256:238a2d5b1cad28cdc6ed15faf93a998336eb041c4e440dd7f902528b8891b399"}, + {file = "rpds_py-0.20.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ac2f4f7a98934c2ed6505aead07b979e6f999389f16b714448fb39bbaa86a489"}, + {file = "rpds_py-0.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:220002c1b846db9afd83371d08d239fdc865e8f8c5795bbaec20916a76db3318"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d7919548df3f25374a1f5d01fbcd38dacab338ef5f33e044744b5c36729c8db"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:758406267907b3781beee0f0edfe4a179fbd97c0be2e9b1154d7f0a1279cf8e5"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3d61339e9f84a3f0767b1995adfb171a0d00a1185192718a17af6e124728e0f5"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1259c7b3705ac0a0bd38197565a5d603218591d3f6cee6e614e380b6ba61c6f6"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c1dc0f53856b9cc9a0ccca0a7cc61d3d20a7088201c0937f3f4048c1718a209"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7e60cb630f674a31f0368ed32b2a6b4331b8350d67de53c0359992444b116dd3"}, + {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dbe982f38565bb50cb7fb061ebf762c2f254ca3d8c20d4006878766e84266272"}, + {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:514b3293b64187172bc77c8fb0cdae26981618021053b30d8371c3a902d4d5ad"}, + {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d0a26ffe9d4dd35e4dfdd1e71f46401cff0181c75ac174711ccff0459135fa58"}, + {file = "rpds_py-0.20.0-cp311-none-win32.whl", hash = "sha256:89c19a494bf3ad08c1da49445cc5d13d8fefc265f48ee7e7556839acdacf69d0"}, + {file = "rpds_py-0.20.0-cp311-none-win_amd64.whl", hash = "sha256:c638144ce971df84650d3ed0096e2ae7af8e62ecbbb7b201c8935c370df00a2c"}, + {file = "rpds_py-0.20.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a84ab91cbe7aab97f7446652d0ed37d35b68a465aeef8fc41932a9d7eee2c1a6"}, + {file = "rpds_py-0.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:56e27147a5a4c2c21633ff8475d185734c0e4befd1c989b5b95a5d0db699b21b"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2580b0c34583b85efec8c5c5ec9edf2dfe817330cc882ee972ae650e7b5ef739"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b80d4a7900cf6b66bb9cee5c352b2d708e29e5a37fe9bf784fa97fc11504bf6c"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50eccbf054e62a7b2209b28dc7a22d6254860209d6753e6b78cfaeb0075d7bee"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:49a8063ea4296b3a7e81a5dfb8f7b2d73f0b1c20c2af401fb0cdf22e14711a96"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea438162a9fcbee3ecf36c23e6c68237479f89f962f82dae83dc15feeceb37e4"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18d7585c463087bddcfa74c2ba267339f14f2515158ac4db30b1f9cbdb62c8ef"}, + {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d4c7d1a051eeb39f5c9547e82ea27cbcc28338482242e3e0b7768033cb083821"}, + {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e4df1e3b3bec320790f699890d41c59d250f6beda159ea3c44c3f5bac1976940"}, + {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2cf126d33a91ee6eedc7f3197b53e87a2acdac63602c0f03a02dd69e4b138174"}, + {file = "rpds_py-0.20.0-cp312-none-win32.whl", hash = "sha256:8bc7690f7caee50b04a79bf017a8d020c1f48c2a1077ffe172abec59870f1139"}, + {file = "rpds_py-0.20.0-cp312-none-win_amd64.whl", hash = "sha256:0e13e6952ef264c40587d510ad676a988df19adea20444c2b295e536457bc585"}, + {file = "rpds_py-0.20.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:f2fbf7db2012d4876fb0d66b5b9ba6591197b0f165db8d99371d976546472a24"}, + {file = "rpds_py-0.20.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1e5f3cd7397c8f86c8cc72d5a791071431c108edd79872cdd96e00abd8497d29"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce9845054c13696f7af7f2b353e6b4f676dab1b4b215d7fe5e05c6f8bb06f965"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c3e130fd0ec56cb76eb49ef52faead8ff09d13f4527e9b0c400307ff72b408e1"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b16aa0107ecb512b568244ef461f27697164d9a68d8b35090e9b0c1c8b27752"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7f429242aae2947246587d2964fad750b79e8c233a2367f71b554e9447949c"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af0fc424a5842a11e28956e69395fbbeab2c97c42253169d87e90aac2886d751"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b8c00a3b1e70c1d3891f0db1b05292747f0dbcfb49c43f9244d04c70fbc40eb8"}, + {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:40ce74fc86ee4645d0a225498d091d8bc61f39b709ebef8204cb8b5a464d3c0e"}, + {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:4fe84294c7019456e56d93e8ababdad5a329cd25975be749c3f5f558abb48253"}, + {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:338ca4539aad4ce70a656e5187a3a31c5204f261aef9f6ab50e50bcdffaf050a"}, + {file = "rpds_py-0.20.0-cp38-none-win32.whl", hash = "sha256:54b43a2b07db18314669092bb2de584524d1ef414588780261e31e85846c26a5"}, + {file = "rpds_py-0.20.0-cp38-none-win_amd64.whl", hash = "sha256:a1862d2d7ce1674cffa6d186d53ca95c6e17ed2b06b3f4c476173565c862d232"}, + {file = "rpds_py-0.20.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3fde368e9140312b6e8b6c09fb9f8c8c2f00999d1823403ae90cc00480221b22"}, + {file = "rpds_py-0.20.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9824fb430c9cf9af743cf7aaf6707bf14323fb51ee74425c380f4c846ea70789"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11ef6ce74616342888b69878d45e9f779b95d4bd48b382a229fe624a409b72c5"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c52d3f2f82b763a24ef52f5d24358553e8403ce05f893b5347098014f2d9eff2"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d35cef91e59ebbeaa45214861874bc6f19eb35de96db73e467a8358d701a96c"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d72278a30111e5b5525c1dd96120d9e958464316f55adb030433ea905866f4de"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4c29cbbba378759ac5786730d1c3cb4ec6f8ababf5c42a9ce303dc4b3d08cda"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6632f2d04f15d1bd6fe0eedd3b86d9061b836ddca4c03d5cf5c7e9e6b7c14580"}, + {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d0b67d87bb45ed1cd020e8fbf2307d449b68abc45402fe1a4ac9e46c3c8b192b"}, + {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ec31a99ca63bf3cd7f1a5ac9fe95c5e2d060d3c768a09bc1d16e235840861420"}, + {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22e6c9976e38f4d8c4a63bd8a8edac5307dffd3ee7e6026d97f3cc3a2dc02a0b"}, + {file = "rpds_py-0.20.0-cp39-none-win32.whl", hash = "sha256:569b3ea770c2717b730b61998b6c54996adee3cef69fc28d444f3e7920313cf7"}, + {file = "rpds_py-0.20.0-cp39-none-win_amd64.whl", hash = "sha256:e6900ecdd50ce0facf703f7a00df12374b74bbc8ad9fe0f6559947fb20f82364"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:617c7357272c67696fd052811e352ac54ed1d9b49ab370261a80d3b6ce385045"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9426133526f69fcaba6e42146b4e12d6bc6c839b8b555097020e2b78ce908dcc"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deb62214c42a261cb3eb04d474f7155279c1a8a8c30ac89b7dcb1721d92c3c02"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcaeb7b57f1a1e071ebd748984359fef83ecb026325b9d4ca847c95bc7311c92"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d454b8749b4bd70dd0a79f428731ee263fa6995f83ccb8bada706e8d1d3ff89d"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d807dc2051abe041b6649681dce568f8e10668e3c1c6543ebae58f2d7e617855"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3c20f0ddeb6e29126d45f89206b8291352b8c5b44384e78a6499d68b52ae511"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b7f19250ceef892adf27f0399b9e5afad019288e9be756d6919cb58892129f51"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4f1ed4749a08379555cebf4650453f14452eaa9c43d0a95c49db50c18b7da075"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:dcedf0b42bcb4cfff4101d7771a10532415a6106062f005ab97d1d0ab5681c60"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:39ed0d010457a78f54090fafb5d108501b5aa5604cc22408fc1c0c77eac14344"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:bb273176be34a746bdac0b0d7e4e2c467323d13640b736c4c477881a3220a989"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f918a1a130a6dfe1d7fe0f105064141342e7dd1611f2e6a21cd2f5c8cb1cfb3e"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f60012a73aa396be721558caa3a6fd49b3dd0033d1675c6d59c4502e870fcf0c"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d2b1ad682a3dfda2a4e8ad8572f3100f95fad98cb99faf37ff0ddfe9cbf9d03"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:614fdafe9f5f19c63ea02817fa4861c606a59a604a77c8cdef5aa01d28b97921"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa518bcd7600c584bf42e6617ee8132869e877db2f76bcdc281ec6a4113a53ab"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0475242f447cc6cb8a9dd486d68b2ef7fbee84427124c232bff5f63b1fe11e5"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90a4cd061914a60bd51c68bcb4357086991bd0bb93d8aa66a6da7701370708f"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:def7400461c3a3f26e49078302e1c1b38f6752342c77e3cf72ce91ca69fb1bc1"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:65794e4048ee837494aea3c21a28ad5fc080994dfba5b036cf84de37f7ad5074"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:faefcc78f53a88f3076b7f8be0a8f8d35133a3ecf7f3770895c25f8813460f08"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:5b4f105deeffa28bbcdff6c49b34e74903139afa690e35d2d9e3c2c2fba18cec"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fdfc3a892927458d98f3d55428ae46b921d1f7543b89382fdb483f5640daaec8"}, + {file = "rpds_py-0.20.0.tar.gz", hash = "sha256:d72a210824facfdaf8768cf2d7ca25a042c30320b3020de2fa04640920d4e121"}, +] + [[package]] name = "rsa" version = "4.9" @@ -3447,7 +3632,7 @@ name = "sniffio" version = "1.3.1" requires_python = ">=3.7" summary = "Sniff out which async library your code is running under" -groups = ["anthropic", "openai"] +groups = ["anthropic", "litellm", "openai"] files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -3535,12 +3720,61 @@ files = [ {file = "tenacity-9.0.0.tar.gz", hash = "sha256:807f37ca97d62aa361264d497b0e31e92b8027044942bfa756160d908320d73b"}, ] +[[package]] +name = "tiktoken" +version = "0.7.0" +requires_python = ">=3.8" +summary = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" +groups = ["litellm"] +dependencies = [ + "regex>=2022.1.18", + "requests>=2.26.0", +] +files = [ + {file = "tiktoken-0.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485f3cc6aba7c6b6ce388ba634fbba656d9ee27f766216f45146beb4ac18b25f"}, + {file = "tiktoken-0.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e54be9a2cd2f6d6ffa3517b064983fb695c9a9d8aa7d574d1ef3c3f931a99225"}, + {file = "tiktoken-0.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79383a6e2c654c6040e5f8506f3750db9ddd71b550c724e673203b4f6b4b4590"}, + {file = "tiktoken-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d4511c52caacf3c4981d1ae2df85908bd31853f33d30b345c8b6830763f769c"}, + {file = "tiktoken-0.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:13c94efacdd3de9aff824a788353aa5749c0faee1fbe3816df365ea450b82311"}, + {file = "tiktoken-0.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8e58c7eb29d2ab35a7a8929cbeea60216a4ccdf42efa8974d8e176d50c9a3df5"}, + {file = "tiktoken-0.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:21a20c3bd1dd3e55b91c1331bf25f4af522c525e771691adbc9a69336fa7f702"}, + {file = "tiktoken-0.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:10c7674f81e6e350fcbed7c09a65bca9356eaab27fb2dac65a1e440f2bcfe30f"}, + {file = "tiktoken-0.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:084cec29713bc9d4189a937f8a35dbdfa785bd1235a34c1124fe2323821ee93f"}, + {file = "tiktoken-0.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:811229fde1652fedcca7c6dfe76724d0908775b353556d8a71ed74d866f73f7b"}, + {file = "tiktoken-0.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86b6e7dc2e7ad1b3757e8a24597415bafcfb454cebf9a33a01f2e6ba2e663992"}, + {file = "tiktoken-0.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1063c5748be36344c7e18c7913c53e2cca116764c2080177e57d62c7ad4576d1"}, + {file = "tiktoken-0.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:20295d21419bfcca092644f7e2f2138ff947a6eb8cfc732c09cc7d76988d4a89"}, + {file = "tiktoken-0.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:959d993749b083acc57a317cbc643fb85c014d055b2119b739487288f4e5d1cb"}, + {file = "tiktoken-0.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:71c55d066388c55a9c00f61d2c456a6086673ab7dec22dd739c23f77195b1908"}, + {file = "tiktoken-0.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:09ed925bccaa8043e34c519fbb2f99110bd07c6fd67714793c21ac298e449410"}, + {file = "tiktoken-0.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03c6c40ff1db0f48a7b4d2dafeae73a5607aacb472fa11f125e7baf9dce73704"}, + {file = "tiktoken-0.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d20b5c6af30e621b4aca094ee61777a44118f52d886dbe4f02b70dfe05c15350"}, + {file = "tiktoken-0.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d427614c3e074004efa2f2411e16c826f9df427d3c70a54725cae860f09e4bf4"}, + {file = "tiktoken-0.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8c46d7af7b8c6987fac9b9f61041b452afe92eb087d29c9ce54951280f899a97"}, + {file = "tiktoken-0.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:0bc603c30b9e371e7c4c7935aba02af5994a909fc3c0fe66e7004070858d3f8f"}, + {file = "tiktoken-0.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2398fecd38c921bcd68418675a6d155fad5f5e14c2e92fcf5fe566fa5485a858"}, + {file = "tiktoken-0.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f5f6afb52fb8a7ea1c811e435e4188f2bef81b5e0f7a8635cc79b0eef0193d6"}, + {file = "tiktoken-0.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:861f9ee616766d736be4147abac500732b505bf7013cfaf019b85892637f235e"}, + {file = "tiktoken-0.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54031f95c6939f6b78122c0aa03a93273a96365103793a22e1793ee86da31685"}, + {file = "tiktoken-0.7.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fffdcb319b614cf14f04d02a52e26b1d1ae14a570f90e9b55461a72672f7b13d"}, + {file = "tiktoken-0.7.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c72baaeaefa03ff9ba9688624143c858d1f6b755bb85d456d59e529e17234769"}, + {file = "tiktoken-0.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:131b8aeb043a8f112aad9f46011dced25d62629091e51d9dc1adbf4a1cc6aa98"}, + {file = "tiktoken-0.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cabc6dc77460df44ec5b879e68692c63551ae4fae7460dd4ff17181df75f1db7"}, + {file = "tiktoken-0.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8d57f29171255f74c0aeacd0651e29aa47dff6f070cb9f35ebc14c82278f3b25"}, + {file = "tiktoken-0.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ee92776fdbb3efa02a83f968c19d4997a55c8e9ce7be821ceee04a1d1ee149c"}, + {file = "tiktoken-0.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e215292e99cb41fbc96988ef62ea63bb0ce1e15f2c147a61acc319f8b4cbe5bf"}, + {file = "tiktoken-0.7.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8a81bac94769cab437dd3ab0b8a4bc4e0f9cf6835bcaa88de71f39af1791727a"}, + {file = "tiktoken-0.7.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d6d73ea93e91d5ca771256dfc9d1d29f5a554b83821a1dc0891987636e0ae226"}, + {file = "tiktoken-0.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:2bcb28ddf79ffa424f171dfeef9a4daff61a94c631ca6813f43967cb263b83b9"}, + {file = "tiktoken-0.7.0.tar.gz", hash = "sha256:1077266e949c24e0291f6c350433c6f0971365ece2b173a23bc3b9f9defef6b6"}, +] + [[package]] name = "tokenizers" version = "0.19.1" requires_python = ">=3.7" summary = "" -groups = ["anthropic"] +groups = ["anthropic", "litellm"] dependencies = [ "huggingface-hub<1.0,>=0.16.4", ] @@ -3700,7 +3934,7 @@ name = "tqdm" version = "4.66.4" requires_python = ">=3.7" summary = "Fast, Extensible Progress Meter" -groups = ["default", "anthropic", "dev", "openai"] +groups = ["default", "anthropic", "dev", "litellm", "openai"] dependencies = [ "colorama; platform_system == \"Windows\"", ] @@ -3748,7 +3982,7 @@ name = "typing-extensions" version = "4.12.2" requires_python = ">=3.8" summary = "Backported and Experimental Type Hints for Python 3.8+" -groups = ["default", "anthropic", "aws", "azure", "dev", "docs", "openai", "test"] +groups = ["default", "anthropic", "aws", "azure", "dev", "docs", "litellm", "openai", "test"] 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"}, @@ -3759,7 +3993,7 @@ name = "urllib3" version = "1.26.19" requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" summary = "HTTP library with thread-safe connection pooling, file post, and more." -groups = ["anthropic", "aws", "azure", "dev", "docs", "google"] +groups = ["anthropic", "aws", "azure", "dev", "docs", "google", "litellm"] files = [ {file = "urllib3-1.26.19-py2.py3-none-any.whl", hash = "sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3"}, {file = "urllib3-1.26.19.tar.gz", hash = "sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429"}, @@ -3914,7 +4148,7 @@ name = "yarl" version = "1.9.4" requires_python = ">=3.7" summary = "Yet another URL library" -groups = ["aws"] +groups = ["aws", "litellm"] dependencies = [ "idna>=2.0", "multidict>=4.0", @@ -4005,7 +4239,7 @@ name = "zipp" version = "3.19.2" requires_python = ">=3.8" summary = "Backport of pathlib-compatible object wrapper for zip files" -groups = ["dev", "docs"] +groups = ["dev", "docs", "litellm"] files = [ {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"}, {file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"}, diff --git a/pyproject.toml b/pyproject.toml index 8593e0e..edf16a1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,6 +44,9 @@ aws = [ "aioboto3>=13.1.0", "boto3>=1.18.0" ] +litellm = [ + "litellm>=1.48.14" +] [project.scripts] docprompt = "docprompt.cli:main"