aidial-adapter-anthropic 0.1.0__tar.gz → 0.2.0rc0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/PKG-INFO +2 -2
- aidial_adapter_anthropic-0.2.0rc0/aidial_adapter_anthropic/__init__.py +5 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/_utils/json.py +1 -1
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_base.py +1 -4
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_claude/adapter.py +1 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_claude/config.py +4 -2
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_claude/state.py +2 -2
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_decorator/base.py +2 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_decorator/preprocess.py +2 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_decorator/replicator.py +1 -1
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_truncate_prompt.py +5 -2
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/dial/_attachments.py +5 -6
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/dial/consumer.py +1 -1
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/dial/request.py +2 -5
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/dial/resource.py +12 -12
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/dial/storage.py +2 -1
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/pyproject.toml +11 -3
- aidial_adapter_anthropic-0.1.0/aidial_adapter_anthropic/_utils/pydantic.py +0 -6
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/LICENSE +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/README.md +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/_utils/list.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/_utils/resource.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/_utils/text.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/__init__.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_claude/blocks.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_claude/citations.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_claude/converters.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_claude/params.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_claude/tokenizer/__init__.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_claude/tokenizer/anthropic.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_claude/tokenizer/approximate.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_claude/tokenizer/base.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_claude/tools.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_errors.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/_tokenize.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/adapter/claude.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/dial/_lazy_stage.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/dial/_message.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/dial/token_usage.py +0 -0
- {aidial_adapter_anthropic-0.1.0 → aidial_adapter_anthropic-0.2.0rc0}/aidial_adapter_anthropic/dial/tools.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: aidial-adapter-anthropic
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0rc0
|
|
4
4
|
Summary: Package implementing adapter from DIAL Chat Completions API to Anthropic API
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Keywords: ai
|
|
@@ -12,7 +12,7 @@ Requires-Dist: aidial-sdk (>=0.28.0,<1)
|
|
|
12
12
|
Requires-Dist: aiohttp (>=3.13.3,<4)
|
|
13
13
|
Requires-Dist: anthropic (>=0.75.0,<1)
|
|
14
14
|
Requires-Dist: pillow (>=10.4.0,<11)
|
|
15
|
-
Requires-Dist: pydantic (>=
|
|
15
|
+
Requires-Dist: pydantic (>=2.8.2,<3)
|
|
16
16
|
Project-URL: Documentation, https://epam-rail.com/dial_api
|
|
17
17
|
Project-URL: Homepage, https://epam-rail.com
|
|
18
18
|
Project-URL: Repository, https://github.com/epam/ai-dial-adapter-anthropic/
|
|
@@ -2,9 +2,11 @@ from typing import List, Literal
|
|
|
2
2
|
|
|
3
3
|
from anthropic.types.anthropic_beta_param import AnthropicBetaParam
|
|
4
4
|
from anthropic.types.beta import BetaThinkingConfigParam as ThinkingConfigParam
|
|
5
|
-
from pydantic import Field
|
|
5
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
class ExtraForbidModel(BaseModel):
|
|
9
|
+
model_config = ConfigDict(extra="forbid")
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
class ThinkingConfigEnabled(ExtraForbidModel):
|
|
@@ -21,7 +21,7 @@ class MessageState(BaseModel):
|
|
|
21
21
|
claude_message_content: List[ParsedContentBlock] | List[ContentBlock]
|
|
22
22
|
|
|
23
23
|
def to_dict(self) -> dict:
|
|
24
|
-
return self.
|
|
24
|
+
return self.model_dump(
|
|
25
25
|
# FIXME: a hack to exclude the private __json_buf field
|
|
26
26
|
exclude={"claude_message_content": {"__all__": {"__json_buf"}}},
|
|
27
27
|
# Excluding `citations: null`, since they could not be even parsed
|
|
@@ -35,7 +35,7 @@ def get_message_content_from_state(
|
|
|
35
35
|
) -> List[ContentBlockParam] | None:
|
|
36
36
|
if (cc := message.custom_content) and (state_dict := cc.state):
|
|
37
37
|
try:
|
|
38
|
-
state = MessageState.
|
|
38
|
+
state = MessageState.model_validate(state_dict)
|
|
39
39
|
return [block.to_dict() for block in state.claude_message_content] # type: ignore
|
|
40
40
|
except pydantic.ValidationError as e:
|
|
41
41
|
_log.error(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
1
2
|
from typing import Callable, List
|
|
2
3
|
|
|
3
4
|
from aidial_sdk.chat_completion import Message
|
|
@@ -9,6 +10,7 @@ from aidial_adapter_anthropic.dial.consumer import Consumer
|
|
|
9
10
|
from aidial_adapter_anthropic.dial.request import ModelParameters
|
|
10
11
|
|
|
11
12
|
|
|
13
|
+
@dataclass
|
|
12
14
|
class ChatCompletionDecorator(ChatCompletionAdapter):
|
|
13
15
|
adapter: ChatCompletionAdapter
|
|
14
16
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
1
2
|
from typing import Callable, List
|
|
2
3
|
|
|
3
4
|
from aidial_sdk.chat_completion import Message
|
|
@@ -20,6 +21,7 @@ def preprocess_messages_decorator(
|
|
|
20
21
|
)
|
|
21
22
|
|
|
22
23
|
|
|
24
|
+
@dataclass
|
|
23
25
|
class PreprocessMessagesDecorator(ChatCompletionDecorator):
|
|
24
26
|
on_messages: Callable[[List[Message]], ListProjection[Message]]
|
|
25
27
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
|
+
from dataclasses import dataclass
|
|
2
3
|
from typing import Awaitable, Callable, List, Optional, Set, Tuple, TypeVar
|
|
3
4
|
|
|
4
5
|
from aidial_sdk.exceptions import ContextLengthExceededError
|
|
@@ -7,7 +8,6 @@ from aidial_sdk.exceptions import (
|
|
|
7
8
|
InvalidRequestError,
|
|
8
9
|
TruncatePromptSystemAndLastUserError,
|
|
9
10
|
)
|
|
10
|
-
from pydantic import BaseModel
|
|
11
11
|
|
|
12
12
|
from aidial_adapter_anthropic._utils.list import (
|
|
13
13
|
omit_by_indices,
|
|
@@ -15,7 +15,7 @@ from aidial_adapter_anthropic._utils.list import (
|
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
class TruncatePromptError(ABC
|
|
18
|
+
class TruncatePromptError(ABC):
|
|
19
19
|
@abstractmethod
|
|
20
20
|
def to_dial_exception(self) -> DialException:
|
|
21
21
|
pass
|
|
@@ -24,6 +24,7 @@ class TruncatePromptError(ABC, BaseModel):
|
|
|
24
24
|
return self.to_dial_exception().message
|
|
25
25
|
|
|
26
26
|
|
|
27
|
+
@dataclass
|
|
27
28
|
class InconsistentLimitsError(TruncatePromptError):
|
|
28
29
|
user_limit: int
|
|
29
30
|
model_limit: int
|
|
@@ -35,6 +36,7 @@ class InconsistentLimitsError(TruncatePromptError):
|
|
|
35
36
|
)
|
|
36
37
|
|
|
37
38
|
|
|
39
|
+
@dataclass
|
|
38
40
|
class ModelLimitOverflow(TruncatePromptError):
|
|
39
41
|
model_limit: int
|
|
40
42
|
token_count: int
|
|
@@ -43,6 +45,7 @@ class ModelLimitOverflow(TruncatePromptError):
|
|
|
43
45
|
return ContextLengthExceededError(self.model_limit, self.token_count)
|
|
44
46
|
|
|
45
47
|
|
|
48
|
+
@dataclass
|
|
46
49
|
class UserLimitOverflow(TruncatePromptError):
|
|
47
50
|
user_limit: int
|
|
48
51
|
token_count: int
|
|
@@ -50,10 +50,8 @@ class HandlerWithConfig(Protocol, Generic[_T, _Config]):
|
|
|
50
50
|
def __call__(self, resource: Resource, config: _Config | None) -> _T: ...
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
arbitrary_types_allowed = True
|
|
56
|
-
|
|
53
|
+
@dataclass
|
|
54
|
+
class AttachmentProcessor(Generic[_T, _Config]):
|
|
57
55
|
supported_types: Dict[str, Set[str]]
|
|
58
56
|
"""MIME type to file extensions mapping"""
|
|
59
57
|
|
|
@@ -89,11 +87,12 @@ class WithResources(Generic[_T]):
|
|
|
89
87
|
return WithResources(payload=payload, resources=resources)
|
|
90
88
|
|
|
91
89
|
|
|
92
|
-
|
|
93
|
-
|
|
90
|
+
@dataclass
|
|
91
|
+
class AttachmentProcessors(Generic[_Txt, _T, _Config]):
|
|
94
92
|
attachment_processors: Sequence[AttachmentProcessor[_T, _Config]]
|
|
95
93
|
text_handler: Callable[[str], _Txt]
|
|
96
94
|
file_storage: FileStorage | None
|
|
95
|
+
config: _Config | None = field(default=None)
|
|
97
96
|
|
|
98
97
|
@property
|
|
99
98
|
def supported_types(self) -> Dict[str, Set[str]]:
|
|
@@ -179,7 +179,7 @@ class ChoiceConsumer(Consumer):
|
|
|
179
179
|
self._citations[document_id] = (display_index, document)
|
|
180
180
|
|
|
181
181
|
if document:
|
|
182
|
-
document = document.
|
|
182
|
+
document = document.model_copy()
|
|
183
183
|
document.title = f"[{display_index}] {document.title or ''}".strip()
|
|
184
184
|
document.reference_type = document.reference_type or document.type
|
|
185
185
|
document.reference_url = document.reference_url or document.url
|
|
@@ -20,7 +20,7 @@ from aidial_sdk.chat_completion.request import (
|
|
|
20
20
|
)
|
|
21
21
|
from aidial_sdk.exceptions import RequestValidationError
|
|
22
22
|
from pydantic import BaseModel
|
|
23
|
-
from pydantic
|
|
23
|
+
from pydantic import ValidationError as PydanticValidationError
|
|
24
24
|
|
|
25
25
|
from aidial_adapter_anthropic.adapter._errors import ValidationError
|
|
26
26
|
from aidial_adapter_anthropic.dial.tools import (
|
|
@@ -82,9 +82,6 @@ class ModelParameters(BaseModel):
|
|
|
82
82
|
configuration=configuration,
|
|
83
83
|
)
|
|
84
84
|
|
|
85
|
-
def add_stop_sequences(self, stop: List[str]) -> "ModelParameters":
|
|
86
|
-
return self.copy(update={"stop": [*self.stop, *stop]})
|
|
87
|
-
|
|
88
85
|
@property
|
|
89
86
|
def tools_mode(self) -> ToolsMode | None:
|
|
90
87
|
if self.tool_config is not None:
|
|
@@ -93,7 +90,7 @@ class ModelParameters(BaseModel):
|
|
|
93
90
|
|
|
94
91
|
def parse_configuration(self, cls: Type[_Model]) -> _Model:
|
|
95
92
|
try:
|
|
96
|
-
return cls.
|
|
93
|
+
return cls.model_validate(self.configuration or {})
|
|
97
94
|
except PydanticValidationError as e:
|
|
98
95
|
if self.configuration is None:
|
|
99
96
|
msg = "The configuration at path 'custom_fields.configuration' is missing."
|
|
@@ -4,7 +4,7 @@ from abc import ABC, abstractmethod
|
|
|
4
4
|
from typing import List
|
|
5
5
|
|
|
6
6
|
from aidial_sdk.chat_completion import Attachment
|
|
7
|
-
from pydantic import BaseModel, Field,
|
|
7
|
+
from pydantic import BaseModel, Field, field_validator, model_validator
|
|
8
8
|
|
|
9
9
|
from aidial_adapter_anthropic._utils.resource import Resource
|
|
10
10
|
from aidial_adapter_anthropic._utils.text import truncate_string
|
|
@@ -34,7 +34,7 @@ class UnsupportedContentType(ValidationError):
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
class DialResource(ABC, BaseModel):
|
|
37
|
-
entity_name: str =
|
|
37
|
+
entity_name: str | None = None
|
|
38
38
|
supported_types: List[str] | None = Field(default=None)
|
|
39
39
|
|
|
40
40
|
@abstractmethod
|
|
@@ -77,10 +77,10 @@ class URLResource(DialResource):
|
|
|
77
77
|
def to_attachment(self) -> Attachment:
|
|
78
78
|
return Attachment(type=self.content_type, url=self.url)
|
|
79
79
|
|
|
80
|
-
@
|
|
81
|
-
def
|
|
82
|
-
|
|
83
|
-
return
|
|
80
|
+
@model_validator(mode="after")
|
|
81
|
+
def default_entity_name(self):
|
|
82
|
+
self.entity_name = self.entity_name or "URL"
|
|
83
|
+
return self
|
|
84
84
|
|
|
85
85
|
async def download(self, storage: FileStorage | None) -> Resource:
|
|
86
86
|
type = await self.get_content_type()
|
|
@@ -114,10 +114,10 @@ class AttachmentResource(DialResource):
|
|
|
114
114
|
def to_attachment(self) -> Attachment:
|
|
115
115
|
return self.attachment
|
|
116
116
|
|
|
117
|
-
@
|
|
117
|
+
@field_validator("attachment", mode="before")
|
|
118
118
|
def parse_attachment(cls, value):
|
|
119
119
|
if isinstance(value, dict):
|
|
120
|
-
attachment = Attachment.
|
|
120
|
+
attachment = Attachment.model_validate(value)
|
|
121
121
|
# Working around the issue of defaulting missing type to a markdown:
|
|
122
122
|
# https://github.com/epam/ai-dial-sdk/blob/2835107e950c89645a2b619fecba2518fa2d7bb1/aidial_sdk/chat_completion/request.py#L22
|
|
123
123
|
if "type" not in value:
|
|
@@ -125,10 +125,10 @@ class AttachmentResource(DialResource):
|
|
|
125
125
|
return attachment
|
|
126
126
|
return value
|
|
127
127
|
|
|
128
|
-
@
|
|
129
|
-
def
|
|
130
|
-
|
|
131
|
-
return
|
|
128
|
+
@model_validator(mode="after")
|
|
129
|
+
def default_entity_name(self):
|
|
130
|
+
self.entity_name = self.entity_name or "attachment"
|
|
131
|
+
return self
|
|
132
132
|
|
|
133
133
|
async def download(self, storage: FileStorage | None) -> Resource:
|
|
134
134
|
type = await self.get_content_type()
|
|
@@ -3,11 +3,12 @@ import hashlib
|
|
|
3
3
|
import io
|
|
4
4
|
import logging
|
|
5
5
|
import mimetypes
|
|
6
|
-
from typing import Mapping, Optional
|
|
6
|
+
from typing import Mapping, Optional
|
|
7
7
|
from urllib.parse import unquote, urljoin
|
|
8
8
|
|
|
9
9
|
import aiohttp
|
|
10
10
|
from pydantic import BaseModel
|
|
11
|
+
from typing_extensions import TypedDict
|
|
11
12
|
|
|
12
13
|
_log = logging.getLogger(__name__)
|
|
13
14
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "aidial-adapter-anthropic"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.2.0rc"
|
|
4
4
|
description = "Package implementing adapter from DIAL Chat Completions API to Anthropic API"
|
|
5
5
|
authors = [{ name = "EPAM RAIL", email = "SpecialEPM-DIALDevTeam@epam.com" }]
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -11,7 +11,7 @@ requires-python = ">=3.11,<4.0"
|
|
|
11
11
|
dependencies = [
|
|
12
12
|
"aidial-sdk (>=0.28.0,<1)",
|
|
13
13
|
"anthropic (>=0.75.0,<1)",
|
|
14
|
-
"pydantic (>=
|
|
14
|
+
"pydantic (>=2.8.2,<3)",
|
|
15
15
|
"pillow (>=10.4.0,<11)",
|
|
16
16
|
"aiohttp (>=3.13.3,<4)",
|
|
17
17
|
]
|
|
@@ -47,7 +47,15 @@ addopts = "-n=auto --asyncio-mode=auto --self-contained-html --html=pytest.html
|
|
|
47
47
|
generate_report_on_test = true
|
|
48
48
|
env_override_existing_values = 1
|
|
49
49
|
testpaths = ["tests"]
|
|
50
|
-
filterwarnings = [
|
|
50
|
+
filterwarnings = [
|
|
51
|
+
"error",
|
|
52
|
+
# "ignore::pydantic.warnings.PydanticDeprecatedSince20",
|
|
53
|
+
# "ignore::pytest.PytestUnraisableExceptionWarning",
|
|
54
|
+
# muting warnings coming from opentelemetry and pkg_resources packages
|
|
55
|
+
# "ignore::DeprecationWarning:opentelemetry.instrumentation.dependencies",
|
|
56
|
+
# "ignore::DeprecationWarning:pkg_resources",
|
|
57
|
+
|
|
58
|
+
]
|
|
51
59
|
|
|
52
60
|
[tool.pyright]
|
|
53
61
|
typeCheckingMode = "basic"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|