aidial-sdk 0.41.0.dev4__tar.gz → 0.42.0.dev1__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_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/PKG-INFO +30 -1
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/README.md +29 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/application.py +107 -36
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/deployment/_headers.py +3 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/deployment/from_request_mixin.py +26 -3
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/pyproject.toml +1 -1
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/LICENSE +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/__init__.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/_errors.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/_pydantic/__init__.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/_pydantic/_compat.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/_pydantic/_model_config.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/chat_completion/__init__.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/chat_completion/_cache.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/chat_completion/_types.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/chat_completion/base.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/chat_completion/choice.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/chat_completion/choice_base.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/chat_completion/chunks.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/chat_completion/enums.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/chat_completion/form.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/chat_completion/function_call.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/chat_completion/function_tool_call.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/chat_completion/request.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/chat_completion/response.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/chat_completion/stage.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/deployment/__init__.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/deployment/configuration.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/deployment/rate.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/deployment/tokenize.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/deployment/truncate_prompt.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/embeddings/__init__.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/embeddings/base.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/embeddings/request.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/embeddings/response.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/exceptions.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/header_propagator.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/py.typed +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/pydantic/v2.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/pydantic_v1/__init__.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/telemetry/__init__.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/telemetry/init.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/telemetry/types.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/__init__.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/_attachment.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/_cancel_scope.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/_content_stream.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/_disconnect_middleware.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/_indexed_list.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/_json_log_formatter.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/_logging.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/_reflection.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/env.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/errors.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/json.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/log_config.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/logging.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/merge_chunks.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/pydantic.py +0 -0
- {aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/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.
|
|
3
|
+
Version: 0.42.0.dev1
|
|
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
|
|
@@ -61,6 +61,7 @@ Description-Content-Type: text/markdown
|
|
|
61
61
|
- [Echo application example](#echo-application-example)
|
|
62
62
|
- [Run](#run)
|
|
63
63
|
- [Check](#check)
|
|
64
|
+
- [Endpoints](#endpoints)
|
|
64
65
|
- [Development](#development)
|
|
65
66
|
- [Development Environment](#development-environment)
|
|
66
67
|
- [Setup](#setup)
|
|
@@ -177,6 +178,34 @@ You will see the JSON response as:
|
|
|
177
178
|
|
|
178
179
|
---
|
|
179
180
|
|
|
181
|
+
### Endpoints
|
|
182
|
+
|
|
183
|
+
Every deployment is exposed under two base paths:
|
|
184
|
+
|
|
185
|
+
|Base path|Description|
|
|
186
|
+
|---|---|
|
|
187
|
+
|`/openai/deployments/{deployment_name}`|The DIAL API path. The deployment name is a part of the path.|
|
|
188
|
+
|`/openai/v1`|The Azure OpenAI v1 API path. The deployment name comes from the request headers.|
|
|
189
|
+
|
|
190
|
+
The following endpoints are served under each of them:
|
|
191
|
+
|
|
192
|
+
- `POST <base path>/chat/completions`
|
|
193
|
+
- `POST <base path>/rate`
|
|
194
|
+
- `POST <base path>/tokenize`
|
|
195
|
+
- `POST <base path>/truncate_prompt`
|
|
196
|
+
- `GET <base path>/configuration`
|
|
197
|
+
- `POST <base path>/embeddings`
|
|
198
|
+
|
|
199
|
+
`request.deployment_id` is resolved from the first of the following sources that is set:
|
|
200
|
+
|
|
201
|
+
1. the `X-DIAL-OVERRIDE-NAME` header,
|
|
202
|
+
2. the deployment name from the path, for the `/openai/deployments/{deployment_name}` requests,
|
|
203
|
+
3. the `X-DIAL-DEPLOYMENT-ID` header, which DIAL Core sets when it calls the `/openai/v1` endpoints.
|
|
204
|
+
|
|
205
|
+
An `/openai/v1` request with none of the headers set fails with `500 Internal Server Error`.
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
180
209
|
## Development
|
|
181
210
|
|
|
182
211
|
### Development Environment
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
- [Echo application example](#echo-application-example)
|
|
23
23
|
- [Run](#run)
|
|
24
24
|
- [Check](#check)
|
|
25
|
+
- [Endpoints](#endpoints)
|
|
25
26
|
- [Development](#development)
|
|
26
27
|
- [Development Environment](#development-environment)
|
|
27
28
|
- [Setup](#setup)
|
|
@@ -138,6 +139,34 @@ You will see the JSON response as:
|
|
|
138
139
|
|
|
139
140
|
---
|
|
140
141
|
|
|
142
|
+
### Endpoints
|
|
143
|
+
|
|
144
|
+
Every deployment is exposed under two base paths:
|
|
145
|
+
|
|
146
|
+
|Base path|Description|
|
|
147
|
+
|---|---|
|
|
148
|
+
|`/openai/deployments/{deployment_name}`|The DIAL API path. The deployment name is a part of the path.|
|
|
149
|
+
|`/openai/v1`|The Azure OpenAI v1 API path. The deployment name comes from the request headers.|
|
|
150
|
+
|
|
151
|
+
The following endpoints are served under each of them:
|
|
152
|
+
|
|
153
|
+
- `POST <base path>/chat/completions`
|
|
154
|
+
- `POST <base path>/rate`
|
|
155
|
+
- `POST <base path>/tokenize`
|
|
156
|
+
- `POST <base path>/truncate_prompt`
|
|
157
|
+
- `GET <base path>/configuration`
|
|
158
|
+
- `POST <base path>/embeddings`
|
|
159
|
+
|
|
160
|
+
`request.deployment_id` is resolved from the first of the following sources that is set:
|
|
161
|
+
|
|
162
|
+
1. the `X-DIAL-OVERRIDE-NAME` header,
|
|
163
|
+
2. the deployment name from the path, for the `/openai/deployments/{deployment_name}` requests,
|
|
164
|
+
3. the `X-DIAL-DEPLOYMENT-ID` header, which DIAL Core sets when it calls the `/openai/v1` endpoints.
|
|
165
|
+
|
|
166
|
+
An `/openai/v1` request with none of the headers set fails with `500 Internal Server Error`.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
141
170
|
## Development
|
|
142
171
|
|
|
143
172
|
### Development Environment
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import re
|
|
3
3
|
import warnings
|
|
4
|
-
from collections.abc import Callable, Coroutine
|
|
4
|
+
from collections.abc import Callable, Coroutine, Iterator
|
|
5
5
|
from typing import Any, Literal, TypeVar
|
|
6
6
|
|
|
7
7
|
from fastapi import FastAPI, HTTPException, Request
|
|
@@ -20,12 +20,16 @@ from aidial_sdk.chat_completion.response import (
|
|
|
20
20
|
Response as ChatCompletionResponse,
|
|
21
21
|
)
|
|
22
22
|
from aidial_sdk.deployment.configuration import ConfigurationRequest
|
|
23
|
-
from aidial_sdk.deployment.from_request_mixin import
|
|
23
|
+
from aidial_sdk.deployment.from_request_mixin import (
|
|
24
|
+
FromRequestMixin,
|
|
25
|
+
resolve_deployment_id,
|
|
26
|
+
)
|
|
24
27
|
from aidial_sdk.deployment.rate import RateRequest
|
|
25
28
|
from aidial_sdk.deployment.tokenize import TokenizeRequest
|
|
26
29
|
from aidial_sdk.deployment.truncate_prompt import TruncatePromptRequest
|
|
27
30
|
from aidial_sdk.embeddings.base import Embeddings
|
|
28
31
|
from aidial_sdk.embeddings.request import Request as EmbeddingsRequest
|
|
32
|
+
from aidial_sdk.exceptions import DeploymentNotFoundError
|
|
29
33
|
from aidial_sdk.exceptions import HTTPException as DIALException
|
|
30
34
|
from aidial_sdk.header_propagator import HeaderPropagator
|
|
31
35
|
from aidial_sdk.telemetry.types import TelemetryConfig
|
|
@@ -45,6 +49,8 @@ configure_sdk_logger()
|
|
|
45
49
|
|
|
46
50
|
RequestType = TypeVar("RequestType", bound=FromRequestMixin)
|
|
47
51
|
|
|
52
|
+
Handler = Callable[[Request], Coroutine[Any, Any, Response]]
|
|
53
|
+
|
|
48
54
|
|
|
49
55
|
def _interpolate_deployment_id(deployment_id: str, path_params: dict) -> str:
|
|
50
56
|
result = deployment_id
|
|
@@ -70,6 +76,7 @@ class PathFilter(logging.Filter):
|
|
|
70
76
|
class DIALApp(FastAPI):
|
|
71
77
|
_allow_extra_request_fields: bool
|
|
72
78
|
_dial_url: str | None
|
|
79
|
+
_v1_handlers: dict[str, dict[str, Handler]]
|
|
73
80
|
|
|
74
81
|
def __init__(
|
|
75
82
|
self,
|
|
@@ -95,6 +102,7 @@ class DIALApp(FastAPI):
|
|
|
95
102
|
|
|
96
103
|
self._allow_extra_request_fields = allow_extra_request_fields
|
|
97
104
|
self._dial_url = dial_url
|
|
105
|
+
self._v1_handlers = {}
|
|
98
106
|
|
|
99
107
|
self.configure_telemetry(telemetry_config)
|
|
100
108
|
|
|
@@ -152,6 +160,13 @@ class DIALApp(FastAPI):
|
|
|
152
160
|
methods=["POST"],
|
|
153
161
|
)
|
|
154
162
|
|
|
163
|
+
self._add_v1_route(
|
|
164
|
+
deployment_name,
|
|
165
|
+
"embeddings",
|
|
166
|
+
self._embeddings(None, impl),
|
|
167
|
+
methods=["POST"],
|
|
168
|
+
)
|
|
169
|
+
|
|
155
170
|
return self
|
|
156
171
|
|
|
157
172
|
def add_chat_completion(
|
|
@@ -161,60 +176,115 @@ class DIALApp(FastAPI):
|
|
|
161
176
|
*,
|
|
162
177
|
heartbeat_interval: float | None = None,
|
|
163
178
|
) -> "DIALApp":
|
|
164
|
-
self.
|
|
165
|
-
|
|
179
|
+
for endpoint, handler, methods in self._chat_completion_handlers(
|
|
180
|
+
deployment_name, impl, heartbeat_interval
|
|
181
|
+
):
|
|
182
|
+
self.add_api_route(
|
|
183
|
+
f"/openai/deployments/{deployment_name}/{endpoint}",
|
|
184
|
+
handler,
|
|
185
|
+
methods=methods,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
for endpoint, handler, methods in self._chat_completion_handlers(
|
|
189
|
+
None, impl, heartbeat_interval
|
|
190
|
+
):
|
|
191
|
+
self._add_v1_route(
|
|
192
|
+
deployment_name, endpoint, handler, methods=methods
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
return self
|
|
196
|
+
|
|
197
|
+
def _chat_completion_handlers(
|
|
198
|
+
self,
|
|
199
|
+
deployment_id: str | None,
|
|
200
|
+
impl: ChatCompletion,
|
|
201
|
+
heartbeat_interval: float | None,
|
|
202
|
+
) -> Iterator[tuple[str, Handler, list[str]]]:
|
|
203
|
+
yield (
|
|
204
|
+
"chat/completions",
|
|
166
205
|
self._chat_completion(
|
|
167
|
-
|
|
168
|
-
impl,
|
|
169
|
-
heartbeat_interval=heartbeat_interval,
|
|
206
|
+
deployment_id, impl, heartbeat_interval=heartbeat_interval
|
|
170
207
|
),
|
|
171
|
-
|
|
208
|
+
["POST"],
|
|
172
209
|
)
|
|
173
210
|
|
|
174
|
-
self.
|
|
175
|
-
f"/openai/deployments/{deployment_name}/rate",
|
|
176
|
-
self._rate_response(deployment_name, impl),
|
|
177
|
-
methods=["POST"],
|
|
178
|
-
)
|
|
211
|
+
yield "rate", self._rate_response(deployment_id, impl), ["POST"]
|
|
179
212
|
|
|
180
213
|
if endpoint_impl := get_method_implementation(impl, "tokenize"):
|
|
181
|
-
|
|
182
|
-
|
|
214
|
+
yield (
|
|
215
|
+
"tokenize",
|
|
183
216
|
self._endpoint_factory(
|
|
184
|
-
|
|
217
|
+
deployment_id, endpoint_impl, "tokenize", TokenizeRequest
|
|
185
218
|
),
|
|
186
|
-
|
|
219
|
+
["POST"],
|
|
187
220
|
)
|
|
188
221
|
|
|
189
222
|
if endpoint_impl := get_method_implementation(impl, "truncate_prompt"):
|
|
190
|
-
|
|
191
|
-
|
|
223
|
+
yield (
|
|
224
|
+
"truncate_prompt",
|
|
192
225
|
self._endpoint_factory(
|
|
193
|
-
|
|
226
|
+
deployment_id,
|
|
194
227
|
endpoint_impl,
|
|
195
228
|
"truncate_prompt",
|
|
196
229
|
TruncatePromptRequest,
|
|
197
230
|
),
|
|
198
|
-
|
|
231
|
+
["POST"],
|
|
199
232
|
)
|
|
200
233
|
|
|
201
234
|
if endpoint_impl := get_method_implementation(impl, "configuration"):
|
|
202
|
-
|
|
203
|
-
|
|
235
|
+
yield (
|
|
236
|
+
"configuration",
|
|
204
237
|
self._endpoint_factory(
|
|
205
|
-
|
|
238
|
+
deployment_id,
|
|
206
239
|
endpoint_impl,
|
|
207
240
|
"configuration",
|
|
208
241
|
ConfigurationRequest,
|
|
209
242
|
),
|
|
210
|
-
|
|
243
|
+
["GET"],
|
|
211
244
|
)
|
|
212
245
|
|
|
213
|
-
|
|
246
|
+
def _add_v1_route(
|
|
247
|
+
self,
|
|
248
|
+
deployment_name: str,
|
|
249
|
+
endpoint: str,
|
|
250
|
+
handler: Handler,
|
|
251
|
+
*,
|
|
252
|
+
methods: list[str],
|
|
253
|
+
) -> None:
|
|
254
|
+
"""The /openai/v1 endpoints are shared by all the deployments of
|
|
255
|
+
the application, so they are dispatched by the deployment id
|
|
256
|
+
resolved from the request headers."""
|
|
257
|
+
|
|
258
|
+
if endpoint not in self._v1_handlers:
|
|
259
|
+
self._v1_handlers[endpoint] = {}
|
|
260
|
+
self.add_api_route(
|
|
261
|
+
f"/openai/v1/{endpoint}",
|
|
262
|
+
self._v1_dispatcher(endpoint),
|
|
263
|
+
methods=methods,
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
self._v1_handlers[endpoint][deployment_name] = handler
|
|
267
|
+
|
|
268
|
+
def _v1_dispatcher(self, endpoint: str) -> Handler:
|
|
269
|
+
async def _handler(original_request: Request) -> Response:
|
|
270
|
+
deployment_id = resolve_deployment_id(
|
|
271
|
+
original_request.headers, None
|
|
272
|
+
)
|
|
273
|
+
set_log_deployment(deployment_id)
|
|
274
|
+
|
|
275
|
+
handler = self._v1_handlers[endpoint].get(deployment_id)
|
|
276
|
+
if handler is None:
|
|
277
|
+
raise DeploymentNotFoundError(
|
|
278
|
+
f"The deployment {deployment_id!r} doesn't provide the {endpoint!r} endpoint"
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
return await handler(original_request)
|
|
282
|
+
|
|
283
|
+
return _handler
|
|
214
284
|
|
|
215
285
|
def _endpoint_factory(
|
|
216
286
|
self,
|
|
217
|
-
deployment_id: str,
|
|
287
|
+
deployment_id: str | None,
|
|
218
288
|
endpoint_impl: Callable[[RequestType], Coroutine[Any, Any, Any]],
|
|
219
289
|
endpoint: Literal["tokenize", "truncate_prompt", "configuration"],
|
|
220
290
|
request_type: type["RequestType"],
|
|
@@ -242,7 +312,7 @@ class DIALApp(FastAPI):
|
|
|
242
312
|
|
|
243
313
|
return _handler
|
|
244
314
|
|
|
245
|
-
def _rate_response(self, deployment_id: str, impl: ChatCompletion):
|
|
315
|
+
def _rate_response(self, deployment_id: str | None, impl: ChatCompletion):
|
|
246
316
|
async def _handler(original_request: Request):
|
|
247
317
|
request = await self._parse_request(
|
|
248
318
|
RateRequest, original_request, deployment_id
|
|
@@ -257,15 +327,16 @@ class DIALApp(FastAPI):
|
|
|
257
327
|
self,
|
|
258
328
|
request: type[RequestType],
|
|
259
329
|
original_request: Request,
|
|
260
|
-
deployment_id: str,
|
|
330
|
+
deployment_id: str | None,
|
|
261
331
|
) -> RequestType:
|
|
262
|
-
|
|
263
|
-
deployment_id
|
|
264
|
-
|
|
265
|
-
|
|
332
|
+
if deployment_id is not None:
|
|
333
|
+
deployment_id = _interpolate_deployment_id(
|
|
334
|
+
deployment_id, original_request.path_params
|
|
335
|
+
)
|
|
336
|
+
set_log_deployment(deployment_id)
|
|
266
337
|
|
|
267
338
|
ret = await request.from_request(
|
|
268
|
-
original_request,
|
|
339
|
+
original_request, deployment_id, self._dial_url
|
|
269
340
|
)
|
|
270
341
|
if not self._allow_extra_request_fields:
|
|
271
342
|
model_validate_extra_fields(ret)
|
|
@@ -273,7 +344,7 @@ class DIALApp(FastAPI):
|
|
|
273
344
|
|
|
274
345
|
def _chat_completion(
|
|
275
346
|
self,
|
|
276
|
-
deployment_id: str,
|
|
347
|
+
deployment_id: str | None,
|
|
277
348
|
impl: ChatCompletion,
|
|
278
349
|
*,
|
|
279
350
|
heartbeat_interval: float | None,
|
|
@@ -316,7 +387,7 @@ class DIALApp(FastAPI):
|
|
|
316
387
|
|
|
317
388
|
return _handler
|
|
318
389
|
|
|
319
|
-
def _embeddings(self, deployment_id: str, impl: Embeddings):
|
|
390
|
+
def _embeddings(self, deployment_id: str | None, impl: Embeddings):
|
|
320
391
|
async def _handler(original_request: Request):
|
|
321
392
|
request = await self._parse_request(
|
|
322
393
|
EmbeddingsRequest, original_request, deployment_id
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
DIAL_CONVERSATION_ID = "X-CONVERSATION-ID"
|
|
2
2
|
DIAL_JOB_TITLE = "X-JOB-TITLE"
|
|
3
3
|
|
|
4
|
+
DIAL_OVERRIDE_NAME = "X-DIAL-OVERRIDE-NAME"
|
|
5
|
+
DIAL_DEPLOYMENT_ID = "X-DIAL-DEPLOYMENT-ID"
|
|
6
|
+
|
|
4
7
|
DIAL_UPSTREAM_ENDPOINT = "X-UPSTREAM-ENDPOINT"
|
|
5
8
|
DIAL_UPSTREAM_KEY = "X-UPSTREAM-KEY"
|
|
6
9
|
DIAL_UPSTREAM_EXTRA_DATA = "X-UPSTREAM-EXTRA-DATA"
|
{aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/deployment/from_request_mixin.py
RENAMED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import warnings
|
|
3
3
|
from abc import ABC, abstractmethod
|
|
4
|
+
from collections.abc import Mapping
|
|
4
5
|
from typing import Any, TypeVar
|
|
5
6
|
from urllib.parse import urljoin
|
|
6
7
|
|
|
@@ -21,7 +22,9 @@ from aidial_sdk.deployment._headers import (
|
|
|
21
22
|
DIAL_CACHE_BREAKPOINT_PATH,
|
|
22
23
|
DIAL_CACHE_EXTRA_METADATA,
|
|
23
24
|
DIAL_CONVERSATION_ID,
|
|
25
|
+
DIAL_DEPLOYMENT_ID,
|
|
24
26
|
DIAL_JOB_TITLE,
|
|
27
|
+
DIAL_OVERRIDE_NAME,
|
|
25
28
|
DIAL_UPSTREAM_ENDPOINT,
|
|
26
29
|
DIAL_UPSTREAM_EXTRA_DATA,
|
|
27
30
|
DIAL_UPSTREAM_KEY,
|
|
@@ -33,13 +36,33 @@ from aidial_sdk.utils.pydantic import ExtraAllowModel
|
|
|
33
36
|
T = TypeVar("T", bound="FromRequestMixin")
|
|
34
37
|
|
|
35
38
|
|
|
39
|
+
def resolve_deployment_id(
|
|
40
|
+
headers: Mapping[str, str], deployment_id: str | None
|
|
41
|
+
) -> str:
|
|
42
|
+
"""The deployment id of a request comes either from the path it was
|
|
43
|
+
sent to or, for the deployment-agnostic paths, from its headers."""
|
|
44
|
+
|
|
45
|
+
effective_deployment_id = (
|
|
46
|
+
headers.get(DIAL_OVERRIDE_NAME)
|
|
47
|
+
or deployment_id
|
|
48
|
+
or headers.get(DIAL_DEPLOYMENT_ID)
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
if effective_deployment_id is None:
|
|
52
|
+
raise InternalServerError(
|
|
53
|
+
f"The request headers are missing {DIAL_DEPLOYMENT_ID} header."
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
return effective_deployment_id
|
|
57
|
+
|
|
58
|
+
|
|
36
59
|
class FromRequestMixin(ABC, ExtraAllowModel):
|
|
37
60
|
@classmethod
|
|
38
61
|
@abstractmethod
|
|
39
62
|
async def from_request(
|
|
40
63
|
cls: type[T],
|
|
41
64
|
request: fastapi.Request,
|
|
42
|
-
deployment_id: str,
|
|
65
|
+
deployment_id: str | None,
|
|
43
66
|
base_url: str | None,
|
|
44
67
|
) -> T:
|
|
45
68
|
pass
|
|
@@ -176,7 +199,7 @@ class FromRequestDeploymentMixin(FromRequestMixin):
|
|
|
176
199
|
async def from_request(
|
|
177
200
|
cls,
|
|
178
201
|
request: fastapi.Request,
|
|
179
|
-
deployment_id: StrictStr,
|
|
202
|
+
deployment_id: StrictStr | None,
|
|
180
203
|
base_url: str | None,
|
|
181
204
|
):
|
|
182
205
|
headers = request.headers.mutablecopy()
|
|
@@ -212,7 +235,7 @@ class FromRequestDeploymentMixin(FromRequestMixin):
|
|
|
212
235
|
bearer_token_secret=(
|
|
213
236
|
SecretStr(bearer_token) if bearer_token else None
|
|
214
237
|
),
|
|
215
|
-
deployment_id=deployment_id,
|
|
238
|
+
deployment_id=resolve_deployment_id(headers, deployment_id),
|
|
216
239
|
api_version=request.query_params.get("api-version"),
|
|
217
240
|
headers=headers,
|
|
218
241
|
original_request=request,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "aidial-sdk"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.42.0.dev1"
|
|
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"
|
|
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
|
{aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/chat_completion/function_call.py
RENAMED
|
File without changes
|
{aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/chat_completion/function_tool_call.py
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aidial_sdk-0.41.0.dev4 → aidial_sdk-0.42.0.dev1}/aidial_sdk/utils/_disconnect_middleware.py
RENAMED
|
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
|