unique_toolkit 2026.36.0.dev5__py3-none-any.whl → 2026.36.0.dev7__py3-none-any.whl
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.
- unique_toolkit/experimental/integrations/openai/streaming/event_routing/_model_params.py +133 -0
- unique_toolkit/experimental/integrations/openai/streaming/event_routing/chat_completions/complete_with_references.py +7 -4
- unique_toolkit/experimental/integrations/openai/streaming/event_routing/responses/complete_with_references.py +12 -8
- {unique_toolkit-2026.36.0.dev5.dist-info → unique_toolkit-2026.36.0.dev7.dist-info}/METADATA +2 -2
- {unique_toolkit-2026.36.0.dev5.dist-info → unique_toolkit-2026.36.0.dev7.dist-info}/RECORD +6 -5
- {unique_toolkit-2026.36.0.dev5.dist-info → unique_toolkit-2026.36.0.dev7.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""Apply LanguageModelInfo constraints to experimental streaming requests."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from collections.abc import Mapping, Sequence
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from openai.types.shared_params import Reasoning
|
|
10
|
+
|
|
11
|
+
from unique_toolkit.chat.responses_api import _attempt_extract_reasoning_from_options
|
|
12
|
+
from unique_toolkit.language_model.infos import LanguageModelInfo, LanguageModelName
|
|
13
|
+
from unique_toolkit.language_model.schemas import reasoning_effort_to_openai
|
|
14
|
+
|
|
15
|
+
_LOGGER = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
_REASONING_OPTION_KEYS = ("reasoning", "reasoning_effort", "reasoningEffort")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def prepare_chat_completions_model_params(
|
|
21
|
+
model_name: LanguageModelName | str,
|
|
22
|
+
temperature: float,
|
|
23
|
+
other_options: dict[str, Any] | None,
|
|
24
|
+
) -> dict[str, Any]:
|
|
25
|
+
"""Prepare Chat Completions create() options including clamped temperature.
|
|
26
|
+
|
|
27
|
+
Copies ``other_options`` so the caller dict is not mutated, applies
|
|
28
|
+
``LanguageModelInfo`` temperature/reasoning rules, and writes the clamped
|
|
29
|
+
temperature onto the returned options dict.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
model_name (LanguageModelName | str): Model identifier from the caller.
|
|
33
|
+
temperature (float): Requested sampling temperature.
|
|
34
|
+
other_options (dict[str, Any] | None): Extra OpenAI create() kwargs.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
dict[str, Any]: Sanitized create() options including ``temperature``.
|
|
38
|
+
"""
|
|
39
|
+
options = dict(other_options) if other_options else {}
|
|
40
|
+
requested_effort = options.get("reasoning_effort")
|
|
41
|
+
temperature, resolved_effort = LanguageModelInfo.from_name(
|
|
42
|
+
model_name
|
|
43
|
+
).resolve_temp_and_reasoning(temperature, requested_effort)
|
|
44
|
+
if resolved_effort is not None:
|
|
45
|
+
options["reasoning_effort"] = resolved_effort
|
|
46
|
+
else:
|
|
47
|
+
options.pop("reasoning_effort", None)
|
|
48
|
+
options["temperature"] = temperature
|
|
49
|
+
return options
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def prepare_responses_model_params(
|
|
53
|
+
model_name: LanguageModelName | str,
|
|
54
|
+
temperature: float,
|
|
55
|
+
reasoning: Reasoning | None,
|
|
56
|
+
other_options: dict[str, Any] | None,
|
|
57
|
+
tools: Sequence[Mapping[str, Any]] | None = None,
|
|
58
|
+
) -> dict[str, Any]:
|
|
59
|
+
"""Prepare Responses API create() options including clamped temperature.
|
|
60
|
+
|
|
61
|
+
Extracts reasoning from ``other_options`` when the explicit argument is
|
|
62
|
+
missing (UniqueAI passes ``reasoning`` that way), applies
|
|
63
|
+
``LanguageModelInfo`` bounds, and bumps ``minimal`` effort to ``low`` when
|
|
64
|
+
a code-interpreter tool is present. Clamped temperature and resolved
|
|
65
|
+
reasoning are written onto the returned options dict.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
model_name (LanguageModelName | str): Model identifier from the caller.
|
|
69
|
+
temperature (float): Requested sampling temperature.
|
|
70
|
+
reasoning (Reasoning | None): Explicit Responses ``reasoning`` payload.
|
|
71
|
+
other_options (dict[str, Any] | None): Extra OpenAI create() kwargs.
|
|
72
|
+
tools (Sequence[Mapping[str, Any]] | None): Converted Responses tools.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
dict[str, Any]: Sanitized create() options including ``temperature``.
|
|
76
|
+
"""
|
|
77
|
+
options = dict(other_options) if other_options else {}
|
|
78
|
+
if reasoning is None:
|
|
79
|
+
reasoning = _attempt_extract_reasoning_from_options(options)
|
|
80
|
+
for key in _REASONING_OPTION_KEYS:
|
|
81
|
+
options.pop(key, None)
|
|
82
|
+
|
|
83
|
+
requested_effort = reasoning.get("effort") if reasoning is not None else None
|
|
84
|
+
temperature, resolved_effort = LanguageModelInfo.from_name(
|
|
85
|
+
model_name
|
|
86
|
+
).resolve_temp_and_reasoning(temperature, requested_effort)
|
|
87
|
+
reasoning = _bump_code_interpreter_effort(
|
|
88
|
+
_apply_resolved_reasoning(reasoning, resolved_effort),
|
|
89
|
+
tools,
|
|
90
|
+
)
|
|
91
|
+
options["temperature"] = temperature
|
|
92
|
+
if reasoning is not None:
|
|
93
|
+
options["reasoning"] = reasoning
|
|
94
|
+
return options
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _apply_resolved_reasoning(
|
|
98
|
+
reasoning: Reasoning | None,
|
|
99
|
+
resolved_effort: str | None,
|
|
100
|
+
) -> Reasoning | None:
|
|
101
|
+
"""Write the resolved effort into a new Responses ``reasoning`` payload."""
|
|
102
|
+
if resolved_effort is not None:
|
|
103
|
+
reasoning = Reasoning(**(reasoning or {}))
|
|
104
|
+
reasoning["effort"] = reasoning_effort_to_openai(resolved_effort)
|
|
105
|
+
return reasoning
|
|
106
|
+
if reasoning is None or "effort" not in reasoning:
|
|
107
|
+
return reasoning
|
|
108
|
+
reasoning = Reasoning(**reasoning)
|
|
109
|
+
del reasoning["effort"]
|
|
110
|
+
if not reasoning:
|
|
111
|
+
return None
|
|
112
|
+
return reasoning
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _bump_code_interpreter_effort(
|
|
116
|
+
reasoning: Reasoning | None,
|
|
117
|
+
tools: Sequence[Mapping[str, Any]] | None,
|
|
118
|
+
) -> Reasoning | None:
|
|
119
|
+
"""Code interpreter cannot run at ``minimal`` effort; bump to ``low``."""
|
|
120
|
+
if (
|
|
121
|
+
reasoning is None
|
|
122
|
+
or tools is None
|
|
123
|
+
or not any(tool["type"] == "code_interpreter" for tool in tools)
|
|
124
|
+
or reasoning.get("effort") != "minimal"
|
|
125
|
+
):
|
|
126
|
+
return reasoning
|
|
127
|
+
|
|
128
|
+
_LOGGER.warning(
|
|
129
|
+
"Code interpreter cannot be used with `minimal` effort. Switching to `low`."
|
|
130
|
+
)
|
|
131
|
+
reasoning = Reasoning(**reasoning)
|
|
132
|
+
reasoning["effort"] = "low"
|
|
133
|
+
return reasoning
|
|
@@ -44,6 +44,7 @@ from unique_toolkit.language_model.schemas import (
|
|
|
44
44
|
from unique_toolkit.protocols.support import SupportCompleteWithReferences
|
|
45
45
|
|
|
46
46
|
from .._async_bridge import run_async_from_sync
|
|
47
|
+
from .._model_params import prepare_chat_completions_model_params
|
|
47
48
|
from ..events import (
|
|
48
49
|
StreamEnded,
|
|
49
50
|
StreamEventBus,
|
|
@@ -378,6 +379,10 @@ class ChatCompletionsCompleteWithReferences(SupportCompleteWithReferences):
|
|
|
378
379
|
message_id = chat.last_assistant_message_id
|
|
379
380
|
chat_id = chat.chat_id
|
|
380
381
|
|
|
382
|
+
other_options = prepare_chat_completions_model_params(
|
|
383
|
+
model_name, temperature, other_options
|
|
384
|
+
)
|
|
385
|
+
|
|
381
386
|
gpt_messages = (
|
|
382
387
|
messages.to_openai(mode="completions")
|
|
383
388
|
if isinstance(messages, LanguageModelMessages)
|
|
@@ -389,9 +394,8 @@ class ChatCompletionsCompleteWithReferences(SupportCompleteWithReferences):
|
|
|
389
394
|
optional_create_kwargs["tools"] = converted_tools
|
|
390
395
|
if tool_choice is not None:
|
|
391
396
|
optional_create_kwargs["tool_choice"] = tool_choice
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
optional_create_kwargs.setdefault(k, v)
|
|
397
|
+
for k, v in other_options.items():
|
|
398
|
+
optional_create_kwargs.setdefault(k, v)
|
|
395
399
|
|
|
396
400
|
gpt_request: list[dict[str, Any]] = [
|
|
397
401
|
dict(cast("Mapping[str, Any]", message)) for message in gpt_messages
|
|
@@ -444,7 +448,6 @@ class ChatCompletionsCompleteWithReferences(SupportCompleteWithReferences):
|
|
|
444
448
|
messages=gpt_messages,
|
|
445
449
|
stream=True,
|
|
446
450
|
stream_options=stream_options,
|
|
447
|
-
temperature=temperature,
|
|
448
451
|
**optional_create_kwargs,
|
|
449
452
|
)
|
|
450
453
|
|
|
@@ -39,6 +39,7 @@ from unique_toolkit.language_model.schemas import (
|
|
|
39
39
|
from unique_toolkit.protocols.support import ResponsesSupportCompleteWithReferences
|
|
40
40
|
|
|
41
41
|
from .._async_bridge import run_async_from_sync
|
|
42
|
+
from .._model_params import prepare_responses_model_params
|
|
42
43
|
from ..events import (
|
|
43
44
|
ActivityProgress,
|
|
44
45
|
StreamEnded,
|
|
@@ -512,8 +513,16 @@ class ResponsesCompleteWithReferences(ResponsesSupportCompleteWithReferences):
|
|
|
512
513
|
)
|
|
513
514
|
|
|
514
515
|
converted_messages = input_messages(messages)
|
|
515
|
-
|
|
516
516
|
converted_tools = _convert_tools(tools)
|
|
517
|
+
|
|
518
|
+
other_options = prepare_responses_model_params(
|
|
519
|
+
model_name,
|
|
520
|
+
temperature,
|
|
521
|
+
reasoning,
|
|
522
|
+
other_options,
|
|
523
|
+
converted_tools,
|
|
524
|
+
)
|
|
525
|
+
|
|
517
526
|
create_kwargs: dict[str, Any] = {}
|
|
518
527
|
if converted_tools:
|
|
519
528
|
create_kwargs["tools"] = converted_tools
|
|
@@ -533,16 +542,12 @@ class ResponsesCompleteWithReferences(ResponsesSupportCompleteWithReferences):
|
|
|
533
542
|
create_kwargs["tool_choice"] = tool_choice
|
|
534
543
|
if top_p is not None:
|
|
535
544
|
create_kwargs["top_p"] = top_p
|
|
536
|
-
|
|
537
|
-
create_kwargs
|
|
538
|
-
if other_options:
|
|
539
|
-
for k, v in other_options.items():
|
|
540
|
-
create_kwargs.setdefault(k, v)
|
|
545
|
+
for k, v in other_options.items():
|
|
546
|
+
create_kwargs.setdefault(k, v)
|
|
541
547
|
gpt_request: dict[str, Any] = {
|
|
542
548
|
"model": model,
|
|
543
549
|
"input": converted_messages,
|
|
544
550
|
"stream": True,
|
|
545
|
-
"temperature": temperature,
|
|
546
551
|
**create_kwargs,
|
|
547
552
|
}
|
|
548
553
|
|
|
@@ -580,7 +585,6 @@ class ResponsesCompleteWithReferences(ResponsesSupportCompleteWithReferences):
|
|
|
580
585
|
model=model,
|
|
581
586
|
input=converted_messages,
|
|
582
587
|
stream=True,
|
|
583
|
-
temperature=temperature,
|
|
584
588
|
**create_kwargs,
|
|
585
589
|
)
|
|
586
590
|
async with stream:
|
{unique_toolkit-2026.36.0.dev5.dist-info → unique_toolkit-2026.36.0.dev7.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: unique-toolkit
|
|
3
|
-
Version: 2026.36.0.
|
|
3
|
+
Version: 2026.36.0.dev7
|
|
4
4
|
Summary:
|
|
5
5
|
Author: Cedric Klinkert, Martin Fadler, Sadique Sheik, Fabian Schläpfer, Pascal Hauri, Ejiroghene Oki-Peter, Rami Azouz, Ricardo Visini, Sanzio Monti
|
|
6
6
|
Author-email: Cedric Klinkert <cedric.klinkert@unique.ch>, Martin Fadler <martin.fadler@unique.ch>, Sadique Sheik <sadique@unique.ch>, Fabian Schläpfer <fabian@unique.ch>, Pascal Hauri <pascal@unique.ch>, Ejiroghene Oki-Peter <oki-peter.ejiroghene@unique.ai>, Rami Azouz <rami.ext@unique.ch>, Ricardo Visini <ricardo.visini@unique.ch>, Sanzio Monti <sanzio.monti@unique.ai>
|
|
@@ -16,7 +16,7 @@ Requires-Dist: sseclient>=0.0.27,<0.0.28
|
|
|
16
16
|
Requires-Dist: openai>=1.105.0,<3
|
|
17
17
|
Requires-Dist: platformdirs>=4.0.0,<5
|
|
18
18
|
Requires-Dist: pillow>=12.1.1
|
|
19
|
-
Requires-Dist: unique-sdk>=2026.36.0.
|
|
19
|
+
Requires-Dist: unique-sdk>=2026.36.0.dev1,<2026.36.0rc0
|
|
20
20
|
Requires-Dist: jambo>=0.1.2,<0.2
|
|
21
21
|
Requires-Dist: jinja2>=3.1.6,<4
|
|
22
22
|
Requires-Dist: docxtpl>=0.20.1,<0.21
|
|
@@ -331,8 +331,9 @@ unique_toolkit/experimental/integrations/openai/__init__.py,sha256=1vh39WXdUMQXS
|
|
|
331
331
|
unique_toolkit/experimental/integrations/openai/streaming/__init__.py,sha256=JhsXd_NZaCDY5XAT-qY0kumpmpYJ-Nws0ZWo6MGj2sI,47
|
|
332
332
|
unique_toolkit/experimental/integrations/openai/streaming/event_routing/__init__.py,sha256=-_SsMgmlySX1ae5XSKcoNjiJ1FRgepooJW49NaEhCHs,3217
|
|
333
333
|
unique_toolkit/experimental/integrations/openai/streaming/event_routing/_async_bridge.py,sha256=j7fK4Q555pXUpSPXdBllKk__b-susz_Jhmh5NqdM_EA,1377
|
|
334
|
+
unique_toolkit/experimental/integrations/openai/streaming/event_routing/_model_params.py,sha256=K-aBUzLbIVOJprafZl6UD-gsJZW2acbY0O8NRFQxocY,4981
|
|
334
335
|
unique_toolkit/experimental/integrations/openai/streaming/event_routing/chat_completions/__init__.py,sha256=sv9Ldr0GeAwc0I7tyM4NbOf_sYJl602S0T2Z0oHb1nE,578
|
|
335
|
-
unique_toolkit/experimental/integrations/openai/streaming/event_routing/chat_completions/complete_with_references.py,sha256=
|
|
336
|
+
unique_toolkit/experimental/integrations/openai/streaming/event_routing/chat_completions/complete_with_references.py,sha256=YvYIGaHjqeUL-C6MJMKNhTKTinvbZ09mBHvLTRaq4sA,21284
|
|
336
337
|
unique_toolkit/experimental/integrations/openai/streaming/event_routing/chat_completions/stream_event_router.py,sha256=XNByWclJXeYOeeDBGkUBVY5r1aNckg4B5xf27UybPYc,6199
|
|
337
338
|
unique_toolkit/experimental/integrations/openai/streaming/event_routing/chat_completions/text_event_handler.py,sha256=1g_EVQ4IpWeorZ3cm9YuN4NMdg19Zv64Ts0ABUzWzR4,5664
|
|
338
339
|
unique_toolkit/experimental/integrations/openai/streaming/event_routing/chat_completions/tool_call_event_handler.py,sha256=Dxg8odtkSO8ErqLLhh0OEObsB-mSUVJ98eE2huTJUUg,2965
|
|
@@ -342,7 +343,7 @@ unique_toolkit/experimental/integrations/openai/streaming/event_routing/protocol
|
|
|
342
343
|
unique_toolkit/experimental/integrations/openai/streaming/event_routing/protocols/responses.py,sha256=bM5qSZjJOTWQyPDUPyMasMwZ-Wu7LQKR64OcKVpUY5E,3294
|
|
343
344
|
unique_toolkit/experimental/integrations/openai/streaming/event_routing/responses/__init__.py,sha256=-8Ey_srOpxX4B_HJhh27h4nZaNC6Y4mk5o8wSLelPwA,847
|
|
344
345
|
unique_toolkit/experimental/integrations/openai/streaming/event_routing/responses/code_interpreter_event_handler.py,sha256=3WFT-zuVCrTP01riJY9uuu5U8-tmFUD-XYTZYDrGx4w,6013
|
|
345
|
-
unique_toolkit/experimental/integrations/openai/streaming/event_routing/responses/complete_with_references.py,sha256=
|
|
346
|
+
unique_toolkit/experimental/integrations/openai/streaming/event_routing/responses/complete_with_references.py,sha256=LAIt3xqroByvTw2DQrFs38Tods3ZjBnpOwzliAg17eM,26176
|
|
346
347
|
unique_toolkit/experimental/integrations/openai/streaming/event_routing/responses/completed_event_handler.py,sha256=BqsJC14KOk_cwelXqyMWlBrFwj5fugkr2gzvwYb3aYM,1360
|
|
347
348
|
unique_toolkit/experimental/integrations/openai/streaming/event_routing/responses/stream_event_router.py,sha256=hvQHDPmfYD-ZDRR5W079TFYEgQ-vhIGMNRyagiG6RzM,8280
|
|
348
349
|
unique_toolkit/experimental/integrations/openai/streaming/event_routing/responses/text_delta_event_handler.py,sha256=JB-7W89K4pT6K8A9Z_f_Pow5p-EIGwLoLUSb9BI3qW4,3634
|
|
@@ -421,6 +422,6 @@ unique_toolkit/short_term_memory/service.py,sha256=2JMBEBn6GoyK-a0xvdcWpPft-3C74
|
|
|
421
422
|
unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
422
423
|
unique_toolkit/smart_rules/compile.py,sha256=vRe0aMJWuVIK-VsqomgxQImzke7MDmwgSxxJfYCa7zw,1386
|
|
423
424
|
unique_toolkit/test_utilities/events.py,sha256=FLrhMh0A_mQutAUjoD0FdMcVQ4Gq31r35OVGzRjvLro,6760
|
|
424
|
-
unique_toolkit-2026.36.0.
|
|
425
|
-
unique_toolkit-2026.36.0.
|
|
426
|
-
unique_toolkit-2026.36.0.
|
|
425
|
+
unique_toolkit-2026.36.0.dev7.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
|
|
426
|
+
unique_toolkit-2026.36.0.dev7.dist-info/METADATA,sha256=Wqg6T1X6FZR7xev8-poWDfWwRIcdTFIH6hwdfRRB9XE,7821
|
|
427
|
+
unique_toolkit-2026.36.0.dev7.dist-info/RECORD,,
|
|
File without changes
|