aidial-sdk 0.48.0.dev1__tar.gz → 0.48.0.dev3__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.
Files changed (78) hide show
  1. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/PKG-INFO +1 -1
  2. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/application.py +30 -19
  3. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/chat_completion/response.py +3 -1
  4. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/deployment/from_request_mixin.py +12 -2
  5. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/translators/messages_to_chat_completions/__init__.py +12 -5
  6. aidial_sdk-0.48.0.dev1/aidial_sdk/translators/messages_to_chat_completions/core_client.py → aidial_sdk-0.48.0.dev3/aidial_sdk/translators/messages_to_chat_completions/backend/http.py +29 -1
  7. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/translators/messages_to_chat_completions/chat_completions/app.py +32 -42
  8. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/pyproject.toml +1 -2
  9. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/LICENSE +0 -0
  10. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/README.md +0 -0
  11. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/__init__.py +0 -0
  12. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/_errors.py +0 -0
  13. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/_pydantic/__init__.py +0 -0
  14. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/_pydantic/_compat.py +0 -0
  15. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/_pydantic/_model_config.py +0 -0
  16. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/chat_completion/__init__.py +0 -0
  17. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/chat_completion/_cache.py +0 -0
  18. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/chat_completion/_types.py +0 -0
  19. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/chat_completion/base.py +0 -0
  20. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/chat_completion/choice.py +0 -0
  21. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/chat_completion/choice_base.py +0 -0
  22. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/chat_completion/chunks.py +0 -0
  23. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/chat_completion/enums.py +0 -0
  24. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/chat_completion/form.py +0 -0
  25. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/chat_completion/function_call.py +0 -0
  26. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/chat_completion/function_tool_call.py +0 -0
  27. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/chat_completion/request.py +0 -0
  28. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/chat_completion/stage.py +0 -0
  29. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/deployment/__init__.py +0 -0
  30. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/deployment/_headers.py +0 -0
  31. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/deployment/configuration.py +0 -0
  32. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/deployment/rate.py +0 -0
  33. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/deployment/tokenize.py +0 -0
  34. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/deployment/truncate_prompt.py +0 -0
  35. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/embeddings/__init__.py +0 -0
  36. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/embeddings/base.py +0 -0
  37. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/embeddings/request.py +0 -0
  38. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/embeddings/response.py +0 -0
  39. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/exceptions.py +0 -0
  40. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/header_propagator.py +0 -0
  41. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/py.typed +0 -0
  42. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/pydantic/v2.py +0 -0
  43. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/pydantic_v1/__init__.py +0 -0
  44. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/response_headers.py +0 -0
  45. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/telemetry/__init__.py +0 -0
  46. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/telemetry/_context.py +0 -0
  47. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/telemetry/init.py +0 -0
  48. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/telemetry/types.py +0 -0
  49. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/translators/messages_to_chat_completions/chat_completions/cache_breakpoints.py +0 -0
  50. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/translators/messages_to_chat_completions/chat_completions/dial_extensions.py +0 -0
  51. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/translators/messages_to_chat_completions/chat_completions/from_chat_completions.py +0 -0
  52. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/translators/messages_to_chat_completions/chat_completions/reasoning.py +0 -0
  53. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/translators/messages_to_chat_completions/chat_completions/streaming.py +0 -0
  54. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/translators/messages_to_chat_completions/chat_completions/system_turns.py +0 -0
  55. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/translators/messages_to_chat_completions/chat_completions/to_chat_completions.py +0 -0
  56. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/translators/messages_to_chat_completions/common.py +0 -0
  57. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/translators/messages_to_chat_completions/errors.py +0 -0
  58. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/translators/messages_to_chat_completions/settings.py +0 -0
  59. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/translators/messages_to_chat_completions/sse_stream.py +0 -0
  60. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/translators/messages_to_chat_completions/translation_state.py +0 -0
  61. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/__init__.py +0 -0
  62. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/_attachment.py +0 -0
  63. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/_cancel_scope.py +0 -0
  64. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/_content_stream.py +0 -0
  65. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/_disconnect_middleware.py +0 -0
  66. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/_indexed_list.py +0 -0
  67. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/_interpolation.py +0 -0
  68. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/_json_log_formatter.py +0 -0
  69. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/_logging.py +0 -0
  70. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/_reflection.py +0 -0
  71. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/env.py +0 -0
  72. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/errors.py +0 -0
  73. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/json.py +0 -0
  74. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/log_config.py +0 -0
  75. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/logging.py +0 -0
  76. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/merge_chunks.py +0 -0
  77. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/pydantic.py +0 -0
  78. {aidial_sdk-0.48.0.dev1 → aidial_sdk-0.48.0.dev3}/aidial_sdk/utils/streaming.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aidial-sdk
3
- Version: 0.48.0.dev1
3
+ Version: 0.48.0.dev3
4
4
  Summary: Framework to create applications and model adapters for AI DIAL
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE
@@ -77,7 +77,20 @@ class PathFilter(logging.Filter):
77
77
  class DIALApp(FastAPI):
78
78
  _allow_extra_request_fields: bool
79
79
  _dial_url: str | None
80
- _v1_handlers: dict[str, dict[str, Handler]]
80
+
81
+ _generic_handlers: dict[str, dict[str, Handler]]
82
+ """
83
+ Request handlers for endpoints that do not allow to distinguish deployments in the path.
84
+ A dictionary from such a deployment-id-less endpoint to the handlers for each deployment:
85
+
86
+ /openai/v1/chat/completions:
87
+ gpt-5.4: handler1
88
+ gpt-5.5: handler2
89
+ /openai/v1/embeddings:
90
+ ada-embeddings-2024-10-10: handler3
91
+ ...
92
+ """
93
+
81
94
  _reset_otel_context: Callable[[], AbstractContextManager[None]]
82
95
 
83
96
  def __init__(
@@ -104,7 +117,7 @@ class DIALApp(FastAPI):
104
117
 
105
118
  self._allow_extra_request_fields = allow_extra_request_fields
106
119
  self._dial_url = dial_url
107
- self._v1_handlers = {}
120
+ self._generic_handlers = {}
108
121
  self._reset_otel_context = nullcontext
109
122
 
110
123
  self.configure_telemetry(telemetry_config)
@@ -175,9 +188,9 @@ class DIALApp(FastAPI):
175
188
  methods=["POST"],
176
189
  )
177
190
 
178
- self._add_v1_route(
191
+ self._add_generic_route(
179
192
  deployment_name,
180
- "embeddings",
193
+ "/openai/v1/embeddings",
181
194
  self._embeddings(None, impl),
182
195
  methods=["POST"],
183
196
  )
@@ -203,8 +216,11 @@ class DIALApp(FastAPI):
203
216
  for endpoint, handler, methods in self._chat_completion_handlers(
204
217
  None, impl, heartbeat_interval
205
218
  ):
206
- self._add_v1_route(
207
- deployment_name, endpoint, handler, methods=methods
219
+ self._add_generic_route(
220
+ deployment_name,
221
+ f"/openai/v1/{endpoint}",
222
+ handler,
223
+ methods=methods,
208
224
  )
209
225
 
210
226
  return self
@@ -258,7 +274,7 @@ class DIALApp(FastAPI):
258
274
  ["GET"],
259
275
  )
260
276
 
261
- def _add_v1_route(
277
+ def _add_generic_route(
262
278
  self,
263
279
  deployment_name: str,
264
280
  endpoint: str,
@@ -266,21 +282,16 @@ class DIALApp(FastAPI):
266
282
  *,
267
283
  methods: list[str],
268
284
  ) -> None:
269
- """The /openai/v1 endpoints are shared by all the deployments of
270
- the application, so they are dispatched by the deployment id
271
- resolved from the request headers."""
272
-
273
- if endpoint not in self._v1_handlers:
274
- self._v1_handlers[endpoint] = {}
285
+ if endpoint not in self._generic_handlers:
286
+ self._generic_handlers[endpoint] = {}
275
287
  self.add_api_route(
276
- f"/openai/v1/{endpoint}",
277
- self._v1_dispatcher(endpoint),
288
+ endpoint,
289
+ self._generic_dispatcher(endpoint),
278
290
  methods=methods,
279
291
  )
292
+ self._generic_handlers[endpoint][deployment_name] = handler
280
293
 
281
- self._v1_handlers[endpoint][deployment_name] = handler
282
-
283
- def _v1_dispatcher(self, endpoint: str) -> Handler:
294
+ def _generic_dispatcher(self, endpoint: str) -> Handler:
284
295
  async def _handler(original_request: Request) -> Response:
285
296
  deployment_id = get_upstream_deployment_id(
286
297
  original_request.headers, None
@@ -302,7 +313,7 @@ class DIALApp(FastAPI):
302
313
  def _get_handler(
303
314
  self, endpoint: str, deployment_id: str, request: Request
304
315
  ) -> Handler | None:
305
- handlers = self._v1_handlers[endpoint]
316
+ handlers = self._generic_handlers[endpoint]
306
317
 
307
318
  if (handler := handlers.get(deployment_id)) is not None:
308
319
  return handler
@@ -70,7 +70,9 @@ class Response:
70
70
  if self.request.stream
71
71
  else "chat.completion"
72
72
  ),
73
- model=get_client_deployment_id(request.headers),
73
+ model=get_client_deployment_id(
74
+ request.headers, request.deployment_id
75
+ ),
74
76
  )
75
77
 
76
78
  self._headers = []
@@ -44,14 +44,24 @@ def get_upstream_deployment_id(
44
44
  return (
45
45
  headers.get(DIAL_OVERRIDE_NAME)
46
46
  or deployment_id
47
- or get_client_deployment_id(headers)
47
+ or _get_dial_deployment_id(headers)
48
48
  )
49
49
 
50
50
 
51
- def get_client_deployment_id(headers: Mapping[str, str]) -> str:
51
+ def get_client_deployment_id(
52
+ headers: Mapping[str, str], deployment_id: str | None
53
+ ) -> str:
52
54
  """The client-facing deployment id that a DIAL application is expected
53
55
  to return as a model parameter in the response."""
54
56
 
57
+ # NOTE: Once https://github.com/epam/ai-dial-core/issues/2243 is fixed,
58
+ # this could be replaced with just _get_dial_deployment_id.
59
+ return headers.get(DIAL_DEPLOYMENT_ID) or get_upstream_deployment_id(
60
+ headers, deployment_id
61
+ )
62
+
63
+
64
+ def _get_dial_deployment_id(headers: Mapping[str, str]) -> str:
55
65
  if (deployment_id := headers.get(DIAL_DEPLOYMENT_ID)) is None:
56
66
  raise InternalServerError(
57
67
  f"The request headers are missing {DIAL_DEPLOYMENT_ID} header."
@@ -1,4 +1,3 @@
1
- import httpx
2
1
  from fastapi import FastAPI
3
2
 
4
3
  from aidial_sdk._pydantic import PYDANTIC_V2
@@ -9,10 +8,18 @@ if not PYDANTIC_V2:
9
8
  "install pydantic>=2 and set PYDANTIC_V2=True"
10
9
  )
11
10
 
12
- from aidial_sdk.translators.messages_to_chat_completions.chat_completions.app import ( # noqa: E402
13
- ClientFactory,
14
- create_anthropic_api_app,
15
- )
11
+ try:
12
+ import httpx
13
+
14
+ from aidial_sdk.translators.messages_to_chat_completions.chat_completions.app import (
15
+ ClientFactory,
16
+ create_anthropic_api_app,
17
+ )
18
+ except ModuleNotFoundError as e:
19
+ raise ImportError(
20
+ "The Anthropic Messages API translator requires the translators extra: "
21
+ 'pip install "aidial-sdk[translators]"'
22
+ ) from e
16
23
 
17
24
  __all__ = ["ClientFactory", "create_anthropic_api_app", "mount_translator"]
18
25
 
@@ -1,8 +1,10 @@
1
+ from dataclasses import dataclass
1
2
  from urllib.parse import quote
2
3
 
3
4
  import httpx
4
5
  from fastapi import Request
5
- from openai import AsyncOpenAI, Omit, omit
6
+ from openai import AsyncOpenAI, AsyncStream, Omit, omit
7
+ from openai.types.chat import ChatCompletion, ChatCompletionChunk
6
8
 
7
9
  from aidial_sdk.translators.messages_to_chat_completions.settings import (
8
10
  get_dial_api_version,
@@ -62,3 +64,29 @@ def core_headers(request: Request) -> dict[str, str | Omit]:
62
64
  }
63
65
  )
64
66
  return headers
67
+
68
+
69
+ @dataclass
70
+ class ChatClientHttp:
71
+ client: AsyncOpenAI
72
+ core_headers: dict[str, str | Omit]
73
+
74
+ async def create_stream(
75
+ self, body: dict
76
+ ) -> AsyncStream[ChatCompletionChunk]:
77
+ return await self.client.post(
78
+ "/chat/completions",
79
+ cast_to=ChatCompletion,
80
+ body=body,
81
+ options={"headers": self.core_headers},
82
+ stream=True,
83
+ stream_cls=AsyncStream[ChatCompletionChunk],
84
+ )
85
+
86
+ async def create_block(self, body: dict) -> ChatCompletion:
87
+ return await self.client.post(
88
+ "/chat/completions",
89
+ cast_to=ChatCompletion,
90
+ body=body,
91
+ options={"headers": self.core_headers},
92
+ )
@@ -7,9 +7,14 @@ import httpx
7
7
  from anthropic.types.beta.message_create_params import MessageCreateParams
8
8
  from fastapi import FastAPI, Request
9
9
  from fastapi.responses import JSONResponse, Response, StreamingResponse
10
- from openai import AsyncStream
11
- from openai.types.chat import ChatCompletion, ChatCompletionChunk
12
10
 
11
+ from aidial_sdk.deployment.from_request_mixin import get_client_deployment_id
12
+ from aidial_sdk.translators.messages_to_chat_completions.backend.http import (
13
+ ChatClientHttp,
14
+ core_headers,
15
+ core_legacy_client,
16
+ core_v1_client,
17
+ )
13
18
  from aidial_sdk.translators.messages_to_chat_completions.chat_completions.from_chat_completions import (
14
19
  to_anthropic_response,
15
20
  )
@@ -23,11 +28,6 @@ from aidial_sdk.translators.messages_to_chat_completions.common import (
23
28
  not_found,
24
29
  with_debug_logging,
25
30
  )
26
- from aidial_sdk.translators.messages_to_chat_completions.core_client import (
27
- core_headers,
28
- core_legacy_client,
29
- core_v1_client,
30
- )
31
31
  from aidial_sdk.translators.messages_to_chat_completions.errors import (
32
32
  AnthropicErrorType,
33
33
  AnthropicHTTPError,
@@ -45,13 +45,10 @@ ClientT = TypeVar("ClientT")
45
45
  ClientFactory = Callable[[Request], Awaitable[ClientT]] | ClientT
46
46
 
47
47
 
48
- async def _handle_messages(
49
- request: Request,
50
- get_client: ClientFactory[httpx.AsyncClient],
51
- legacy: bool,
48
+ async def handle_anthropic_messages(
49
+ request: Request, client: ChatClientHttp
52
50
  ) -> Response:
53
- dial_url = get_dial_url()
54
- translation_state = TranslationState()
51
+ deployment = get_client_deployment_id(request.headers, None)
55
52
 
56
53
  try:
57
54
  req: MessageCreateParams = await request.json()
@@ -61,7 +58,7 @@ async def _handle_messages(
61
58
  f"Request body is not valid JSON: {e}",
62
59
  ) from e
63
60
 
64
- deployment = request.headers.get("x-dial-deployment-id") or req["model"]
61
+ translation_state = TranslationState()
65
62
  chat_request = to_chat_completions_request(
66
63
  req, deployment, translation_state
67
64
  )
@@ -70,38 +67,14 @@ async def _handle_messages(
70
67
  if log.isEnabledFor(logging.DEBUG):
71
68
  log.debug(f"Translated request to Core: {json.dumps(body)}")
72
69
 
73
- http_client = (
74
- get_client
75
- if isinstance(get_client, httpx.AsyncClient)
76
- else await get_client(request)
77
- )
78
- client = (
79
- core_legacy_client(dial_url, deployment, http_client)
80
- if legacy
81
- else core_v1_client(dial_url, http_client)
82
- )
83
- headers = core_headers(request)
84
-
85
70
  if chat_request.stream:
86
- events = await client.post(
87
- "/chat/completions",
88
- cast_to=ChatCompletion,
89
- body=body,
90
- options={"headers": headers},
91
- stream=True,
92
- stream_cls=AsyncStream[ChatCompletionChunk],
93
- )
71
+ events = await client.create_stream(body)
94
72
  return StreamingResponse(
95
73
  translate_stream(events, deployment, translation_state),
96
74
  media_type="text/event-stream",
97
75
  )
98
76
 
99
- response = await client.post(
100
- "/chat/completions",
101
- cast_to=ChatCompletion,
102
- body=body,
103
- options={"headers": headers},
104
- )
77
+ response = await client.create_block(body)
105
78
  message = to_anthropic_response(response, deployment, translation_state)
106
79
  return JSONResponse(
107
80
  content=message.model_dump(mode="json", exclude_unset=True)
@@ -113,17 +86,34 @@ def create_anthropic_api_app(
113
86
  ) -> FastAPI:
114
87
  app = FastAPI()
115
88
 
89
+ async def _chat_client(request: Request, *, legacy: bool) -> ChatClientHttp:
90
+ http_client = (
91
+ await get_client(request) if callable(get_client) else get_client
92
+ )
93
+ dial_url = get_dial_url()
94
+ if legacy:
95
+ deployment_id = get_client_deployment_id(request.headers, None)
96
+ client = core_legacy_client(dial_url, deployment_id, http_client)
97
+ else:
98
+ client = core_v1_client(dial_url, http_client)
99
+
100
+ return ChatClientHttp(client, core_headers(request))
101
+
116
102
  @app.post("/anthropic/v1/messages")
117
103
  @with_debug_logging
118
104
  @translator_error_handler
119
105
  async def _handle_v1_messages(request: Request) -> Response:
120
- return await _handle_messages(request, get_client, legacy=False)
106
+ return await handle_anthropic_messages(
107
+ request, await _chat_client(request, legacy=False)
108
+ )
121
109
 
122
110
  @app.post("/legacy/anthropic/v1/messages")
123
111
  @with_debug_logging
124
112
  @translator_error_handler
125
113
  async def _handle_legacy_messages(request: Request) -> Response:
126
- return await _handle_messages(request, get_client, legacy=True)
114
+ return await handle_anthropic_messages(
115
+ request, await _chat_client(request, legacy=True)
116
+ )
127
117
 
128
118
  app.add_api_route(
129
119
  "/{full_path:path}",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "aidial-sdk"
3
- version = "0.48.0.dev1"
3
+ version = "0.48.0.dev3"
4
4
  description = "Framework to create applications and model adapters for AI DIAL"
5
5
  authors = [{ name = "EPAM RAIL", email = "SpecialEPM-DIALDevTeam@epam.com" }]
6
6
  license = "Apache-2.0"
@@ -52,7 +52,6 @@ aiointercept = "^0.1.7"
52
52
  requests = "^2.33"
53
53
  responses = "^0.25.3"
54
54
  httpx2 = "^2.12.0" # required for Starlette.TestClient
55
- openai = "^2.46.0" # third-party logger for log-takeover tests
56
55
 
57
56
  [tool.poetry.group.lint.dependencies]
58
57
  pyright = "1.1.385"