Skip to content

Commit ccae5fa

Browse files
authored
feat: update Chat Completions request/response schemas (#127)
1 parent 653d641 commit ccae5fa

16 files changed

Lines changed: 938 additions & 53 deletions

README.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
- [Make Chat Completions Requests](#make-chat-completions-requests)
2626
- [Without Streaming](#without-streaming)
2727
- [With Streaming](#with-streaming)
28+
- [DIAL-specific and Extended Parameters](#dial-specific-and-extended-parameters)
2829
- [Working with Files](#working-with-files)
2930
- [Working with URLs](#working-with-urls)
3031
- [Uploading Files](#uploading-files)
@@ -464,6 +465,115 @@ ChatCompletionChunk(
464465
)
465466
```
466467

468+
#### DIAL-specific and Extended Parameters
469+
470+
Along with the standard OpenAI parameters, `chat.completions.create` accepts
471+
the DIAL extensions and the newer OpenAI parameters:
472+
473+
```python
474+
completion = client.chat.completions.create(
475+
deployment_name="gpt-4o",
476+
stream=False,
477+
messages=[
478+
# Messages support multi-modal content parts,
479+
# the "developer" role and per-message cache breakpoints
480+
{
481+
"role": "developer",
482+
"content": "Be brief",
483+
"custom_fields": {"cache_breakpoint": {"expire_at": "1h"}},
484+
},
485+
{
486+
"role": "user",
487+
"content": [
488+
{"type": "text", "text": "What is on the picture?"},
489+
{
490+
"type": "image_url",
491+
"image_url": {"url": "https://example.com/image.png"},
492+
},
493+
],
494+
# DIAL attachments, stages and forms
495+
"custom_content": {
496+
"attachments": [
497+
{"type": "image/png", "url": "files/bucket/image.png"}
498+
]
499+
},
500+
},
501+
],
502+
tools=[
503+
{
504+
"type": "function",
505+
"function": {"name": "get_weather", "parameters": {}, "strict": True},
506+
"custom_fields": {"cache_breakpoint": {}},
507+
},
508+
# DIAL static tools, resolved by DIAL Core itself
509+
{
510+
"type": "static_function",
511+
"static_function": {"name": "search", "configuration": {}},
512+
},
513+
],
514+
tool_choice="required",
515+
parallel_tool_calls=False,
516+
reasoning_effort="high",
517+
max_completion_tokens=1000,
518+
response_format={
519+
"type": "json_schema",
520+
"json_schema": {"name": "answer", "schema": {"type": "object"}},
521+
},
522+
stream_options={"include_usage": True},
523+
# DIAL-specific parameters
524+
max_prompt_tokens=8000,
525+
custom_fields={
526+
"configuration": {},
527+
"cache_breakpoint": {"expire_at": "5m"},
528+
},
529+
)
530+
```
531+
532+
The response models cover the DIAL extensions as well:
533+
534+
```pycon
535+
>>> completion.choices[0].message.custom_content
536+
CustomContent(
537+
stages=[
538+
Stage(
539+
index=None,
540+
name='Thinking',
541+
status='completed',
542+
content='...',
543+
attachments=None
544+
)
545+
],
546+
attachments=None,
547+
state=None,
548+
form_value=None,
549+
form_schema=None
550+
)
551+
>>> completion.usage
552+
CompletionUsage(
553+
prompt_tokens=11,
554+
completion_tokens=1,
555+
total_tokens=12,
556+
prompt_tokens_details=PromptTokensDetails(
557+
cached_tokens=8,
558+
cache_write_tokens=3
559+
),
560+
completion_tokens_details=CompletionTokensDetails(reasoning_tokens=1)
561+
)
562+
>>> completion.statistics
563+
Statistics(
564+
usage_per_model=[
565+
UsagePerModel(
566+
index=0,
567+
model='gpt-4o',
568+
prompt_tokens=11,
569+
completion_tokens=1,
570+
total_tokens=12
571+
)
572+
],
573+
discarded_messages=[0, 1]
574+
)
575+
```
576+
467577
### Working with Files
468578

469579
#### Working with URLs

aidial_client/resources/chat/completions.py

Lines changed: 92 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
FunctionCallSpecParam,
2929
FunctionParam,
3030
Message,
31+
ReasoningEffort,
32+
ResponseFormat,
33+
StaticToolParam,
34+
StreamOptions,
3135
ToolCallSpecParam,
3236
ToolParam,
3337
)
@@ -51,19 +55,26 @@ def create(
5155
function_call: Literal["none", "auto"]
5256
| FunctionCallSpecParam
5357
| None = None,
54-
tools: list[ToolParam] | None = None,
55-
tool_choice: Literal["none", "auto"] | ToolCallSpecParam | None = None,
58+
tools: list[ToolParam | StaticToolParam] | None = None,
59+
tool_choice: Literal["none", "auto", "required"]
60+
| ToolCallSpecParam
61+
| None = None,
62+
parallel_tool_calls: bool | None = None,
5663
temperature: float | None = None,
5764
top_p: float | None = None,
5865
n: int | None = None,
5966
stop: str | list[str] | None = None,
6067
max_tokens: int | None = None,
68+
max_completion_tokens: int | None = None,
6169
max_prompt_tokens: Literal["infinity"] | int | None = None,
6270
presence_penalty: float | None = None,
6371
frequency_penalty: float | None = None,
6472
logit_bias: dict | None = None,
6573
seed: int | None = None,
6674
user: str | None = None,
75+
reasoning_effort: ReasoningEffort | None = None,
76+
response_format: ResponseFormat | None = None,
77+
stream_options: StreamOptions | None = None,
6778
custom_fields: ChatCompletionRequestCustomFields | None = None,
6879
logprobs: bool | None = None,
6980
top_logprobs: int | None = None,
@@ -86,19 +97,26 @@ def create(
8697
function_call: Literal["none", "auto"]
8798
| FunctionCallSpecParam
8899
| None = None,
89-
tools: list[ToolParam] | None = None,
90-
tool_choice: Literal["none", "auto"] | ToolCallSpecParam | None = None,
100+
tools: list[ToolParam | StaticToolParam] | None = None,
101+
tool_choice: Literal["none", "auto", "required"]
102+
| ToolCallSpecParam
103+
| None = None,
104+
parallel_tool_calls: bool | None = None,
91105
temperature: float | None = None,
92106
top_p: float | None = None,
93107
n: int | None = None,
94108
stop: str | list[str] | None = None,
95109
max_tokens: int | None = None,
110+
max_completion_tokens: int | None = None,
96111
max_prompt_tokens: Literal["infinity"] | int | None = None,
97112
presence_penalty: float | None = None,
98113
frequency_penalty: float | None = None,
99114
logit_bias: dict | None = None,
100115
seed: int | None = None,
101116
user: str | None = None,
117+
reasoning_effort: ReasoningEffort | None = None,
118+
response_format: ResponseFormat | None = None,
119+
stream_options: StreamOptions | None = None,
102120
custom_fields: ChatCompletionRequestCustomFields | None = None,
103121
logprobs: bool | None = None,
104122
top_logprobs: int | None = None,
@@ -120,19 +138,26 @@ def create(
120138
function_call: Literal["none", "auto"]
121139
| FunctionCallSpecParam
122140
| None = None,
123-
tools: list[ToolParam] | None = None,
124-
tool_choice: Literal["none", "auto"] | ToolCallSpecParam | None = None,
141+
tools: list[ToolParam | StaticToolParam] | None = None,
142+
tool_choice: Literal["none", "auto", "required"]
143+
| ToolCallSpecParam
144+
| None = None,
145+
parallel_tool_calls: bool | None = None,
125146
temperature: float | None = None,
126147
top_p: float | None = None,
127148
n: int | None = None,
128149
stop: str | list[str] | None = None,
129150
max_tokens: int | None = None,
151+
max_completion_tokens: int | None = None,
130152
max_prompt_tokens: Literal["infinity"] | int | None = None,
131153
presence_penalty: float | None = None,
132154
frequency_penalty: float | None = None,
133155
logit_bias: dict | None = None,
134156
seed: int | None = None,
135157
user: str | None = None,
158+
reasoning_effort: ReasoningEffort | None = None,
159+
response_format: ResponseFormat | None = None,
160+
stream_options: StreamOptions | None = None,
136161
custom_fields: ChatCompletionRequestCustomFields | None = None,
137162
logprobs: bool | None = None,
138163
top_logprobs: int | None = None,
@@ -165,11 +190,24 @@ def create(
165190
"tools": tools,
166191
"top_p": top_p,
167192
"user": user,
168-
"max_prompt_tokens": max_prompt_tokens,
169-
"custom_fields": custom_fields,
170193
"logprobs": logprobs,
171194
"top_logprobs": top_logprobs,
172-
"extra_body": extra_body,
195+
# DIAL-specific parameters and the ones which aren't supported
196+
# by every openai version are sent in the request body directly
197+
"extra_body": {
198+
**remove_none(
199+
{
200+
"max_prompt_tokens": max_prompt_tokens,
201+
"custom_fields": custom_fields,
202+
"max_completion_tokens": max_completion_tokens,
203+
"parallel_tool_calls": parallel_tool_calls,
204+
"reasoning_effort": reasoning_effort,
205+
"response_format": response_format,
206+
"stream_options": stream_options,
207+
}
208+
),
209+
**extra_body,
210+
},
173211
"extra_query": {
174212
"api-version": (
175213
api_version or self.default_api_version or Omit()
@@ -217,20 +255,29 @@ async def create(
217255
function_call: Literal["none", "auto"]
218256
| FunctionCallSpecParam
219257
| None = None,
220-
tools: list[ToolParam] | None = None,
221-
tool_choice: Literal["none", "auto"] | ToolCallSpecParam | None = None,
258+
tools: list[ToolParam | StaticToolParam] | None = None,
259+
tool_choice: Literal["none", "auto", "required"]
260+
| ToolCallSpecParam
261+
| None = None,
262+
parallel_tool_calls: bool | None = None,
222263
temperature: float | None = None,
223264
top_p: float | None = None,
224265
n: int | None = None,
225266
stop: str | list[str] | None = None,
226267
max_tokens: int | None = None,
268+
max_completion_tokens: int | None = None,
227269
max_prompt_tokens: Literal["infinity"] | int | None = None,
228270
presence_penalty: float | None = None,
229271
frequency_penalty: float | None = None,
230272
logit_bias: dict | None = None,
231273
seed: int | None = None,
232274
user: str | None = None,
275+
reasoning_effort: ReasoningEffort | None = None,
276+
response_format: ResponseFormat | None = None,
277+
stream_options: StreamOptions | None = None,
233278
custom_fields: ChatCompletionRequestCustomFields | None = None,
279+
logprobs: bool | None = None,
280+
top_logprobs: int | None = None,
234281
# Extra params
235282
extra_body: dict[str, Any] | None = None,
236283
extra_headers: Mapping[StrictStr, StrictStr] | None = None,
@@ -250,19 +297,26 @@ async def create(
250297
function_call: Literal["none", "auto"]
251298
| FunctionCallSpecParam
252299
| None = None,
253-
tools: list[ToolParam] | None = None,
254-
tool_choice: Literal["none", "auto"] | ToolCallSpecParam | None = None,
300+
tools: list[ToolParam | StaticToolParam] | None = None,
301+
tool_choice: Literal["none", "auto", "required"]
302+
| ToolCallSpecParam
303+
| None = None,
304+
parallel_tool_calls: bool | None = None,
255305
temperature: float | None = None,
256306
top_p: float | None = None,
257307
n: int | None = None,
258308
stop: str | list[str] | None = None,
259309
max_tokens: int | None = None,
310+
max_completion_tokens: int | None = None,
260311
max_prompt_tokens: Literal["infinity"] | int | None = None,
261312
presence_penalty: float | None = None,
262313
frequency_penalty: float | None = None,
263314
logit_bias: dict | None = None,
264315
seed: int | None = None,
265316
user: str | None = None,
317+
reasoning_effort: ReasoningEffort | None = None,
318+
response_format: ResponseFormat | None = None,
319+
stream_options: StreamOptions | None = None,
266320
custom_fields: ChatCompletionRequestCustomFields | None = None,
267321
logprobs: bool | None = None,
268322
top_logprobs: int | None = None,
@@ -284,19 +338,26 @@ async def create(
284338
function_call: Literal["none", "auto"]
285339
| FunctionCallSpecParam
286340
| None = None,
287-
tools: list[ToolParam] | None = None,
288-
tool_choice: Literal["none", "auto"] | ToolCallSpecParam | None = None,
341+
tools: list[ToolParam | StaticToolParam] | None = None,
342+
tool_choice: Literal["none", "auto", "required"]
343+
| ToolCallSpecParam
344+
| None = None,
345+
parallel_tool_calls: bool | None = None,
289346
temperature: float | None = None,
290347
top_p: float | None = None,
291348
n: int | None = None,
292349
stop: str | list[str] | None = None,
293350
max_tokens: int | None = None,
351+
max_completion_tokens: int | None = None,
294352
max_prompt_tokens: Literal["infinity"] | int | None = None,
295353
presence_penalty: float | None = None,
296354
frequency_penalty: float | None = None,
297355
logit_bias: dict | None = None,
298356
seed: int | None = None,
299357
user: str | None = None,
358+
reasoning_effort: ReasoningEffort | None = None,
359+
response_format: ResponseFormat | None = None,
360+
stream_options: StreamOptions | None = None,
300361
custom_fields: ChatCompletionRequestCustomFields | None = None,
301362
logprobs: bool | None = None,
302363
top_logprobs: int | None = None,
@@ -329,11 +390,24 @@ async def create(
329390
"tools": tools,
330391
"top_p": top_p,
331392
"user": user,
332-
"max_prompt_tokens": max_prompt_tokens,
333-
"custom_fields": custom_fields,
334393
"logprobs": logprobs,
335394
"top_logprobs": top_logprobs,
336-
"extra_body": extra_body,
395+
# DIAL-specific parameters and the ones which aren't supported
396+
# by every openai version are sent in the request body directly
397+
"extra_body": {
398+
**remove_none(
399+
{
400+
"max_prompt_tokens": max_prompt_tokens,
401+
"custom_fields": custom_fields,
402+
"max_completion_tokens": max_completion_tokens,
403+
"parallel_tool_calls": parallel_tool_calls,
404+
"reasoning_effort": reasoning_effort,
405+
"response_format": response_format,
406+
"stream_options": stream_options,
407+
}
408+
),
409+
**extra_body,
410+
},
337411
"extra_query": {
338412
"api-version": (
339413
api_version or self.default_api_version or Omit()

0 commit comments

Comments
 (0)