@arcfold/dsh 0.0.0-stage → 0.4.0
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.
- package/LICENSE +21 -0
- package/README.md +8 -2
- package/THIRD_PARTY_NOTICES.md +11 -0
- package/cordis.patch.yml +138 -0
- package/package.json +70 -4
- package/patches/deepseek-0.2.2-rc.1-transport.json +65 -0
- package/patches/deepseek-0.2.2-rc.1-transport.patch +61 -0
- package/presets/arcfold.patch.yml +110 -0
- package/runtime/README.md +19 -0
- package/runtime/bootstrap.json +15 -0
- package/runtime/desktop-python.tar.gz +0 -0
- package/runtime/host/package.json +11 -0
- package/runtime/host/pnpm-workspace.yaml +9 -0
- package/runtime/initial-policy.json +94 -0
- package/runtime/profile/pnpm-workspace.yaml +7 -0
- package/scripts/exact-package-patch.mjs +106 -0
- package/scripts/patch-deepseek-transport.mjs +14 -0
- package/src/agent.mjs +56 -0
- package/src/browse-scope.mjs +14 -0
- package/src/budget.mjs +369 -0
- package/src/business.mjs +334 -0
- package/src/context-material.mjs +119 -0
- package/src/deepseek-budget-plugin.mjs +58 -0
- package/src/deepseek-provider.mjs +57 -0
- package/src/deepseek-receipt.mjs +97 -0
- package/src/deepseek-transport.mjs +97 -0
- package/src/desktop/adapter.mjs +16 -0
- package/src/desktop/bootstrap.mjs +84 -0
- package/src/desktop/configuration.mjs +117 -0
- package/src/desktop/provider.mjs +46 -0
- package/src/desktop/python-runtime.mjs +105 -0
- package/src/desktop/setup-service.mjs +81 -0
- package/src/desktop/vendor/LICENSE.deepseek +21 -0
- package/src/desktop/vendor/NOTICE.md +5 -0
- package/src/desktop/vendor/deepseek-0.2.2-rc.1.mjs +2919 -0
- package/src/evidence-ownership.mjs +51 -0
- package/src/evidence.mjs +35 -0
- package/src/goal-context.mjs +52 -0
- package/src/goal-execution-tool.mjs +74 -0
- package/src/goal-execution.mjs +333 -0
- package/src/goal-tool.mjs +56 -0
- package/src/goal-work-control.mjs +63 -0
- package/src/goal-work.mjs +257 -0
- package/src/goals.mjs +578 -0
- package/src/importer.mjs +298 -0
- package/src/index.mjs +53 -0
- package/src/learning-contracts.mjs +220 -0
- package/src/learning-defaults.mjs +98 -0
- package/src/learning-goals.mjs +165 -0
- package/src/learning-plugin.mjs +28 -0
- package/src/learning-runner.mjs +275 -0
- package/src/learning.mjs +534 -0
- package/src/legacy-export.mjs +332 -0
- package/src/legacy-import-source.mjs +356 -0
- package/src/metered-provider-host.mjs +101 -0
- package/src/metered-transport.mjs +435 -0
- package/src/method-context.mjs +57 -0
- package/src/method-lifecycle.mjs +34 -0
- package/src/method-tool.mjs +61 -0
- package/src/methods.mjs +425 -0
- package/src/model-selection.mjs +41 -0
- package/src/native-context-call.mjs +88 -0
- package/src/native-continuation.mjs +217 -0
- package/src/native-request-authority.mjs +90 -0
- package/src/openai-models.mjs +4 -0
- package/src/openai-receipt.mjs +98 -0
- package/src/openai-transport.mjs +167 -0
- package/src/openai-usage.mjs +194 -0
- package/src/opportunities.mjs +295 -0
- package/src/preparation-artifacts.mjs +213 -0
- package/src/preparation-plugin.mjs +290 -0
- package/src/runtime-command.mjs +264 -0
- package/src/runtime-config.mjs +417 -0
- package/src/runtime-guard.mjs +284 -0
- package/src/runtime-host.mjs +212 -0
- package/src/runtime-init.mjs +278 -0
- package/src/runtime-installation.mjs +518 -0
- package/src/runtime-lifecycle.mjs +227 -0
- package/src/runtime-model-settings.mjs +111 -0
- package/src/runtime-readiness.mjs +285 -0
- package/src/runtime-workspace.mjs +18 -0
- package/src/session-bridge.mjs +365 -0
- package/src/store.mjs +394 -0
- package/src/tree/LICENSE +21 -0
- package/src/tree/attribution.mjs +120 -0
- package/src/tree/clusters.mjs +61 -0
- package/src/tree/consolidation.mjs +103 -0
- package/src/tree/context.mjs +211 -0
- package/src/tree/contracts.mjs +142 -0
- package/src/tree/experience.mjs +140 -0
- package/src/tree/experiment-budget.mjs +84 -0
- package/src/tree/hooks.mjs +254 -0
- package/src/tree/host-context.mjs +107 -0
- package/src/tree/host-process.mjs +288 -0
- package/src/tree/host.mjs +37 -0
- package/src/tree/improvement.mjs +106 -0
- package/src/tree/items.mjs +294 -0
- package/src/tree/jobs.mjs +184 -0
- package/src/tree/learning.mjs +202 -0
- package/src/tree/metrics.mjs +203 -0
- package/src/tree/model-owner.mjs +254 -0
- package/src/tree/observations.mjs +73 -0
- package/src/tree/prompts.mjs +500 -0
- package/src/tree/reports.mjs +67 -0
- package/src/tree/repository.mjs +236 -0
- package/src/tree/runtime.mjs +745 -0
- package/src/tree/script-writer.mjs +149 -0
- package/src/tree/scripts.mjs +208 -0
- package/src/tree/signals.mjs +118 -0
- package/src/tree/snapshots.mjs +379 -0
- package/src/tree/token-counter.mjs +75 -0
- package/src/tree/token-counter.py +37 -0
- package/src/tree/tokenizer-resources/LICENSE +21 -0
- package/src/tree/tokenizer-resources/README.md +31 -0
- package/src/tree/tokenizer-resources/deepseek_recipe-0.2.0-cp310-abi3-macosx_11_0_arm64.whl +0 -0
- package/src/tree/tokenizer-resources/manifest.json +61 -0
- package/src/tree/tokenizer-resources/native.pyi +1042 -0
- package/src/tree/tokenizer-resources/tokenizer-NOTICE.md +26 -0
- package/src/tree/tokenizer-resources/tokenizer-v4-NOTICE.md +27 -0
- package/src/tree/tokenizer-resources/tokenizer-v4.json +267359 -0
- package/src/tree/tokenizer-resources/tokenizer.json +267359 -0
- package/src/tree/tools.mjs +99 -0
- package/src/tree/tree.mjs +202 -0
- package/src/tree/ui.mjs +285 -0
- package/src/tree/verification.mjs +143 -0
- package/src/understandings.mjs +309 -0
- package/src/web-budget-recovery.mjs +181 -0
|
@@ -0,0 +1,1042 @@
|
|
|
1
|
+
from collections.abc import Callable, Sequence
|
|
2
|
+
from typing import Any, Literal, TypeAlias
|
|
3
|
+
|
|
4
|
+
__version__: str
|
|
5
|
+
|
|
6
|
+
IMAGE_SPECIAL_TOKEN_ID: int
|
|
7
|
+
|
|
8
|
+
ToolChoice: TypeAlias = Literal["auto", "none", "required"]
|
|
9
|
+
ReasoningEffort: TypeAlias = Literal["low", "high", "xhigh", "max"]
|
|
10
|
+
ResponseFormat: TypeAlias = Literal["text", "json_object", "json_schema", "regex"]
|
|
11
|
+
ImageDetail: TypeAlias = Literal["low", "high", "original", "auto"]
|
|
12
|
+
Role: TypeAlias = Literal["system", "user", "assistant", "tool", "latest_reminder"]
|
|
13
|
+
ImageSourceKind: TypeAlias = Literal["data_url", "url", "bytes"]
|
|
14
|
+
RequestBody: TypeAlias = bytes | str | dict[str, Any]
|
|
15
|
+
|
|
16
|
+
class SpecialToken:
|
|
17
|
+
"""A kind of special token."""
|
|
18
|
+
|
|
19
|
+
Bos: SpecialToken
|
|
20
|
+
Eos: SpecialToken
|
|
21
|
+
ThinkingStart: SpecialToken
|
|
22
|
+
ThinkingEnd: SpecialToken
|
|
23
|
+
System: SpecialToken
|
|
24
|
+
User: SpecialToken
|
|
25
|
+
Assistant: SpecialToken
|
|
26
|
+
LatestReminder: SpecialToken
|
|
27
|
+
Dsml: SpecialToken
|
|
28
|
+
Image: SpecialToken
|
|
29
|
+
Ref: SpecialToken
|
|
30
|
+
RefEnd: SpecialToken
|
|
31
|
+
Box: SpecialToken
|
|
32
|
+
BoxEnd: SpecialToken
|
|
33
|
+
Point: SpecialToken
|
|
34
|
+
PointEnd: SpecialToken
|
|
35
|
+
Polygon: SpecialToken
|
|
36
|
+
PolygonEnd: SpecialToken
|
|
37
|
+
|
|
38
|
+
def default_str(self) -> str:
|
|
39
|
+
"""Return the default literal spelling of this token."""
|
|
40
|
+
|
|
41
|
+
class SpecialTokens:
|
|
42
|
+
"""A mapping from each `SpecialToken` to its spelling.
|
|
43
|
+
|
|
44
|
+
Every keyword defaults to the default spelling of its token, so only
|
|
45
|
+
overridden tokens need to be supplied.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
def __init__(
|
|
49
|
+
self,
|
|
50
|
+
*,
|
|
51
|
+
bos: str | None = None,
|
|
52
|
+
eos: str | None = None,
|
|
53
|
+
thinking_start: str | None = None,
|
|
54
|
+
thinking_end: str | None = None,
|
|
55
|
+
system: str | None = None,
|
|
56
|
+
user: str | None = None,
|
|
57
|
+
assistant: str | None = None,
|
|
58
|
+
latest_reminder: str | None = None,
|
|
59
|
+
dsml: str | None = None,
|
|
60
|
+
image: str | None = None,
|
|
61
|
+
ref: str | None = None,
|
|
62
|
+
ref_end: str | None = None,
|
|
63
|
+
box: str | None = None,
|
|
64
|
+
box_end: str | None = None,
|
|
65
|
+
point: str | None = None,
|
|
66
|
+
point_end: str | None = None,
|
|
67
|
+
polygon: str | None = None,
|
|
68
|
+
polygon_end: str | None = None,
|
|
69
|
+
) -> None: ...
|
|
70
|
+
def token(self, token: SpecialToken) -> str:
|
|
71
|
+
"""Return the spelling of `token` in this mapping."""
|
|
72
|
+
|
|
73
|
+
class ConversionError(Exception):
|
|
74
|
+
"""Raised when a protocol request is invalid or cannot be converted."""
|
|
75
|
+
|
|
76
|
+
status_code: int
|
|
77
|
+
body: str
|
|
78
|
+
|
|
79
|
+
class ImageError(Exception):
|
|
80
|
+
"""A failure to resolve, fetch, or preprocess images, including request limits.
|
|
81
|
+
|
|
82
|
+
`kind` names the Rust `ImageError` variant, and `is_retryable` holds its
|
|
83
|
+
retry classification.
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
kind: str
|
|
87
|
+
is_retryable: bool
|
|
88
|
+
|
|
89
|
+
class CalcResizeError(ValueError):
|
|
90
|
+
"""The Rust image token calculation did not converge."""
|
|
91
|
+
|
|
92
|
+
class ToolCall:
|
|
93
|
+
"""A historical tool call and its arguments."""
|
|
94
|
+
|
|
95
|
+
def __init__(self, id: str, name: str, arguments: str) -> None: ...
|
|
96
|
+
@property
|
|
97
|
+
def id(self) -> str: ...
|
|
98
|
+
@property
|
|
99
|
+
def name(self) -> str: ...
|
|
100
|
+
@property
|
|
101
|
+
def arguments(self) -> str:
|
|
102
|
+
"""Caller-supplied arguments, expected to encode a JSON object; not validated."""
|
|
103
|
+
|
|
104
|
+
class ToolDefinition:
|
|
105
|
+
"""A client tool definition.
|
|
106
|
+
|
|
107
|
+
`strict` is passed through. Direct construction does not normalize
|
|
108
|
+
`parameters`, unlike conversion, which normalizes the parameters of a tool
|
|
109
|
+
with `strict: true`.
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
def __init__(
|
|
113
|
+
self,
|
|
114
|
+
name: str,
|
|
115
|
+
description: str | None = None,
|
|
116
|
+
parameters: Any = None,
|
|
117
|
+
strict: bool | None = None,
|
|
118
|
+
defer_loading: bool = False,
|
|
119
|
+
) -> None: ...
|
|
120
|
+
@property
|
|
121
|
+
def name(self) -> str: ...
|
|
122
|
+
@property
|
|
123
|
+
def description(self) -> str | None: ...
|
|
124
|
+
@property
|
|
125
|
+
def parameters(self) -> Any:
|
|
126
|
+
"""Input JSON Schema of the tool."""
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def strict(self) -> bool | None:
|
|
130
|
+
"""The `strict` setting, passed through without normalizing `parameters`."""
|
|
131
|
+
@property
|
|
132
|
+
def defer_loading(self) -> bool: ...
|
|
133
|
+
|
|
134
|
+
class ImageSource:
|
|
135
|
+
"""Base class of the image sources supplied with a conversation.
|
|
136
|
+
|
|
137
|
+
Every source records a `path`: the request location of the image as error
|
|
138
|
+
messages report it, such as `messages.0.content[1]`. Conversion fills it; a
|
|
139
|
+
source constructed directly has an empty path unless the `path` keyword
|
|
140
|
+
supplies one.
|
|
141
|
+
"""
|
|
142
|
+
|
|
143
|
+
@property
|
|
144
|
+
def kind(self) -> ImageSourceKind: ...
|
|
145
|
+
@property
|
|
146
|
+
def detail(self) -> ImageDetail: ...
|
|
147
|
+
@property
|
|
148
|
+
def data_url(self) -> str | None: ...
|
|
149
|
+
@property
|
|
150
|
+
def url(self) -> str | None: ...
|
|
151
|
+
@property
|
|
152
|
+
def data(self) -> bytes | None: ...
|
|
153
|
+
@property
|
|
154
|
+
def path(self) -> str:
|
|
155
|
+
"""Request location of the image; empty when the source has none."""
|
|
156
|
+
|
|
157
|
+
class DataUrlImageSource(ImageSource):
|
|
158
|
+
"""An image referenced by a data URL with a base64 or percent-encoded body."""
|
|
159
|
+
|
|
160
|
+
def __init__(self, data_url: str, detail: ImageDetail = "high", *, path: str = "") -> None: ...
|
|
161
|
+
|
|
162
|
+
class UrlImageSource(ImageSource):
|
|
163
|
+
"""An image referenced by an external URL."""
|
|
164
|
+
|
|
165
|
+
def __init__(self, url: str, detail: ImageDetail = "high", *, path: str = "") -> None: ...
|
|
166
|
+
|
|
167
|
+
class BytesImageSource(ImageSource):
|
|
168
|
+
"""An image supplied as encoded bytes."""
|
|
169
|
+
|
|
170
|
+
def __init__(self, data: bytes, detail: ImageDetail = "high", *, path: str = "") -> None: ...
|
|
171
|
+
|
|
172
|
+
class Message:
|
|
173
|
+
"""Base class of the messages in a conversation.
|
|
174
|
+
|
|
175
|
+
Every message has a role and content. On a message of another role, the
|
|
176
|
+
role-specific properties have fixed values: `reasoning_content`,
|
|
177
|
+
`tool_calls`, and `tool_call_id` are `None`, `prefix` is `False`, and
|
|
178
|
+
`image_sources` is an empty list.
|
|
179
|
+
"""
|
|
180
|
+
|
|
181
|
+
@property
|
|
182
|
+
def role(self) -> Role: ...
|
|
183
|
+
@property
|
|
184
|
+
def content(self) -> str: ...
|
|
185
|
+
@property
|
|
186
|
+
def reasoning_content(self) -> str | None: ...
|
|
187
|
+
@property
|
|
188
|
+
def tool_calls(self) -> list[ToolCall] | None: ...
|
|
189
|
+
@property
|
|
190
|
+
def tool_call_id(self) -> str | None: ...
|
|
191
|
+
@property
|
|
192
|
+
def image_sources(self) -> list[ImageSource]: ...
|
|
193
|
+
@property
|
|
194
|
+
def prefix(self) -> bool:
|
|
195
|
+
"""Whether an assistant message is continued instead of starting a new turn."""
|
|
196
|
+
|
|
197
|
+
class SystemMessage(Message):
|
|
198
|
+
"""A system message.
|
|
199
|
+
|
|
200
|
+
See `UserMessage` for image placeholder rules.
|
|
201
|
+
"""
|
|
202
|
+
|
|
203
|
+
def __init__(
|
|
204
|
+
self,
|
|
205
|
+
content: str,
|
|
206
|
+
image_sources: Sequence[ImageSource] | None = None,
|
|
207
|
+
tools: Sequence[ToolDefinition] | None = None,
|
|
208
|
+
*,
|
|
209
|
+
image_token: str | None = None,
|
|
210
|
+
) -> None: ...
|
|
211
|
+
@property
|
|
212
|
+
def tools(self) -> list[ToolDefinition] | None: ...
|
|
213
|
+
|
|
214
|
+
class UserMessage(Message):
|
|
215
|
+
"""A user message.
|
|
216
|
+
|
|
217
|
+
The first occurrences of `image_token` in `content`, one per image source,
|
|
218
|
+
become the placeholders of the image sources; later occurrences are plain
|
|
219
|
+
text. `image_token` defaults to the default image token spelling; a caller
|
|
220
|
+
that renders with a `SpecialTokens` mapping whose image token differs
|
|
221
|
+
passes that mapping's spelling. When `content` holds fewer occurrences than
|
|
222
|
+
there are image sources, the message keeps every image source, so a
|
|
223
|
+
rendered prompt holds fewer placeholders than image sources; construction
|
|
224
|
+
does not report the mismatch. An empty `image_token` raises `ValueError`.
|
|
225
|
+
"""
|
|
226
|
+
|
|
227
|
+
def __init__(
|
|
228
|
+
self,
|
|
229
|
+
content: str,
|
|
230
|
+
image_sources: Sequence[ImageSource] | None = None,
|
|
231
|
+
*,
|
|
232
|
+
image_token: str | None = None,
|
|
233
|
+
) -> None: ...
|
|
234
|
+
|
|
235
|
+
class AssistantMessage(Message):
|
|
236
|
+
"""An assistant message."""
|
|
237
|
+
|
|
238
|
+
def __init__(
|
|
239
|
+
self,
|
|
240
|
+
content: str,
|
|
241
|
+
reasoning_content: str | None = None,
|
|
242
|
+
tool_calls: Sequence[ToolCall] | None = None,
|
|
243
|
+
prefix: bool = False,
|
|
244
|
+
) -> None: ...
|
|
245
|
+
|
|
246
|
+
class ToolMessage(Message):
|
|
247
|
+
"""A tool result message.
|
|
248
|
+
|
|
249
|
+
The first occurrences of `image_token` in `content`, one per image source,
|
|
250
|
+
become the placeholders of the image sources; later occurrences are plain
|
|
251
|
+
text. `image_token` defaults to the default image token spelling; a caller
|
|
252
|
+
that renders with a `SpecialTokens` mapping whose image token differs
|
|
253
|
+
passes that mapping's spelling. When `content` holds fewer occurrences than
|
|
254
|
+
there are image sources, the message keeps every image source, so a
|
|
255
|
+
rendered prompt holds fewer placeholders than image sources; construction
|
|
256
|
+
does not report the mismatch. An empty `image_token` raises `ValueError`.
|
|
257
|
+
"""
|
|
258
|
+
|
|
259
|
+
def __init__(
|
|
260
|
+
self,
|
|
261
|
+
content: str,
|
|
262
|
+
tool_call_id: str | None = None,
|
|
263
|
+
image_sources: Sequence[ImageSource] | None = None,
|
|
264
|
+
*,
|
|
265
|
+
image_token: str | None = None,
|
|
266
|
+
) -> None: ...
|
|
267
|
+
|
|
268
|
+
class LatestReminderMessage(Message):
|
|
269
|
+
"""A reminder message that carries additional instructions."""
|
|
270
|
+
|
|
271
|
+
def __init__(self, content: str) -> None: ...
|
|
272
|
+
|
|
273
|
+
class Conversation:
|
|
274
|
+
"""A conversation and its prompt configuration.
|
|
275
|
+
|
|
276
|
+
Thinking mode is enabled by default, tool selection defaults to `auto`, and
|
|
277
|
+
the response format defaults to `text`. `response_format` accepts `text` or
|
|
278
|
+
`json_object`; `response_schema` selects the `json_schema` format with that
|
|
279
|
+
JSON Schema, and `response_regex` selects the `regex` format with that
|
|
280
|
+
regular expression. Supplying both, or either with `json_object`, raises
|
|
281
|
+
`ValueError`.
|
|
282
|
+
"""
|
|
283
|
+
|
|
284
|
+
def __init__(
|
|
285
|
+
self,
|
|
286
|
+
messages: Sequence[Message] | None = None,
|
|
287
|
+
*,
|
|
288
|
+
thinking_mode: bool = True,
|
|
289
|
+
tools: Sequence[ToolDefinition] | None = None,
|
|
290
|
+
tool_choice: ToolChoice = "auto",
|
|
291
|
+
reasoning_effort: ReasoningEffort | None = None,
|
|
292
|
+
response_format: Literal["text", "json_object"] = "text",
|
|
293
|
+
response_schema: Any | None = None,
|
|
294
|
+
response_regex: str | None = None,
|
|
295
|
+
) -> None: ...
|
|
296
|
+
@property
|
|
297
|
+
def messages(self) -> list[Message]: ...
|
|
298
|
+
@property
|
|
299
|
+
def thinking_mode(self) -> bool: ...
|
|
300
|
+
@property
|
|
301
|
+
def tools(self) -> list[ToolDefinition]: ...
|
|
302
|
+
@property
|
|
303
|
+
def tool_choice(self) -> ToolChoice: ...
|
|
304
|
+
@property
|
|
305
|
+
def reasoning_effort(self) -> ReasoningEffort | None: ...
|
|
306
|
+
@property
|
|
307
|
+
def response_format(self) -> ResponseFormat:
|
|
308
|
+
"""Requested answer format; the caller enforces it during inference."""
|
|
309
|
+
@property
|
|
310
|
+
def response_schema(self) -> Any | None:
|
|
311
|
+
"""The JSON Schema of a `json_schema` response format, or `None`."""
|
|
312
|
+
@property
|
|
313
|
+
def response_regex(self) -> str | None:
|
|
314
|
+
"""The regular expression of a `regex` response format, or `None`."""
|
|
315
|
+
|
|
316
|
+
class RenderedPrompt:
|
|
317
|
+
"""A rendered prompt and the image sources its placeholders refer to."""
|
|
318
|
+
|
|
319
|
+
@property
|
|
320
|
+
def prompt(self) -> str: ...
|
|
321
|
+
@property
|
|
322
|
+
def special_ranges(self) -> list[tuple[int, int]]:
|
|
323
|
+
"""Ascending, disjoint ranges of `prompt` that hold explicit special tokens.
|
|
324
|
+
|
|
325
|
+
Each range is a half-open `(start, end)` pair of code point offsets into
|
|
326
|
+
`prompt` (Python `str` indices), so `prompt[start:end]` is the spelling of
|
|
327
|
+
one token. The Rust `RenderedPrompt::special_ranges` field holds byte
|
|
328
|
+
offsets instead.
|
|
329
|
+
|
|
330
|
+
The text between the ranges is plain text, which prompt encoding encodes
|
|
331
|
+
without the tokenizer's added vocabulary. `Tokenizer.encode` uses the full
|
|
332
|
+
vocabulary, so it encodes a special-token spelling in plain text as that
|
|
333
|
+
token's ID. `DeepseekV4Encoding.encode` and `DeepseekV41Encoding.encode`
|
|
334
|
+
perform prompt encoding.
|
|
335
|
+
"""
|
|
336
|
+
@property
|
|
337
|
+
def image_sources(self) -> list[ImageSource]: ...
|
|
338
|
+
|
|
339
|
+
class DeepseekV4Encoding:
|
|
340
|
+
"""The V4 prompt encoding.
|
|
341
|
+
|
|
342
|
+
It renders a conversation and, with an attached tokenizer, encodes it into
|
|
343
|
+
token IDs.
|
|
344
|
+
"""
|
|
345
|
+
|
|
346
|
+
def __init__(self) -> None: ...
|
|
347
|
+
def with_tokenizer(self, tokenizer: Tokenizer) -> DeepseekV4Encoding:
|
|
348
|
+
"""Return a new prompt encoding that uses `tokenizer` for `encode`."""
|
|
349
|
+
def with_special_tokens(self, special_tokens: SpecialTokens) -> DeepseekV4Encoding:
|
|
350
|
+
"""Return a new prompt encoding that renders prompts with `special_tokens`."""
|
|
351
|
+
def render_conversation(self, conversation: Conversation) -> RenderedPrompt: ...
|
|
352
|
+
def encode(self, conversation: Conversation) -> list[int]:
|
|
353
|
+
"""Encode a conversation into token IDs using the attached tokenizer.
|
|
354
|
+
|
|
355
|
+
Raises `RuntimeError` when no tokenizer is attached or encoding fails.
|
|
356
|
+
"""
|
|
357
|
+
|
|
358
|
+
class DeepseekV41Encoding:
|
|
359
|
+
"""The V4.1 prompt encoding.
|
|
360
|
+
|
|
361
|
+
It renders a conversation and, with an attached tokenizer, encodes it into
|
|
362
|
+
token IDs.
|
|
363
|
+
"""
|
|
364
|
+
|
|
365
|
+
def __init__(self) -> None: ...
|
|
366
|
+
def with_tokenizer(self, tokenizer: Tokenizer) -> DeepseekV41Encoding:
|
|
367
|
+
"""Return a new prompt encoding that uses `tokenizer` for `encode`."""
|
|
368
|
+
def with_special_tokens(self, special_tokens: SpecialTokens) -> DeepseekV41Encoding:
|
|
369
|
+
"""Return a new prompt encoding that renders prompts with `special_tokens`."""
|
|
370
|
+
def render_conversation(self, conversation: Conversation) -> RenderedPrompt: ...
|
|
371
|
+
def encode(self, conversation: Conversation) -> list[int]:
|
|
372
|
+
"""Encode a conversation into token IDs using the attached tokenizer.
|
|
373
|
+
|
|
374
|
+
Raises `RuntimeError` when no tokenizer is attached or encoding fails.
|
|
375
|
+
"""
|
|
376
|
+
|
|
377
|
+
class WebSearchBehavior:
|
|
378
|
+
"""Handling of supported web-search declarations, choices, and Messages blocks."""
|
|
379
|
+
|
|
380
|
+
Drop: WebSearchBehavior
|
|
381
|
+
"""Drop matching declarations and choices, plus Messages server-tool blocks."""
|
|
382
|
+
Reject: WebSearchBehavior
|
|
383
|
+
"""Reject matching declarations and choices, plus Messages server-tool blocks."""
|
|
384
|
+
|
|
385
|
+
class ReasoningContentBehavior:
|
|
386
|
+
"""Handling of assistant history missing reasoning content in thinking mode."""
|
|
387
|
+
|
|
388
|
+
FillEmpty: ReasoningContentBehavior
|
|
389
|
+
"""Fill missing reasoning content with an empty string."""
|
|
390
|
+
Reject: ReasoningContentBehavior
|
|
391
|
+
"""Reject the request when reasoning content that must be passed back is missing."""
|
|
392
|
+
|
|
393
|
+
class ModelVersion:
|
|
394
|
+
"""The model version a converted conversation targets.
|
|
395
|
+
|
|
396
|
+
Conversion resolves it from the request's model name through
|
|
397
|
+
`ConversionOptions.model_versions_by_name`, and it selects the prompt
|
|
398
|
+
encoding: `DeepseekV4Encoding` or `DeepseekV41Encoding`.
|
|
399
|
+
"""
|
|
400
|
+
|
|
401
|
+
DeepseekV4Pro: ModelVersion
|
|
402
|
+
"""DeepSeek V4 Pro, rendered by `DeepseekV4Encoding`."""
|
|
403
|
+
DeepseekV41Flash: ModelVersion
|
|
404
|
+
"""DeepSeek V4.1 Flash, rendered by `DeepseekV41Encoding`."""
|
|
405
|
+
|
|
406
|
+
class ConversionOptions:
|
|
407
|
+
"""Options for protocol request conversion.
|
|
408
|
+
|
|
409
|
+
By default, thinking mode is enabled, missing reasoning content is filled
|
|
410
|
+
with an empty string, Responses `web_search` is dropped, Messages
|
|
411
|
+
`web_search` is rejected, the model version is resolved from the request's
|
|
412
|
+
model name (`DeepSeek-V4-Pro` or `DeepSeek-V4.1-Flash`), and the
|
|
413
|
+
`max_tokens` upper bound is 393216 in thinking mode and outside it.
|
|
414
|
+
"""
|
|
415
|
+
|
|
416
|
+
def __init__(
|
|
417
|
+
self,
|
|
418
|
+
*,
|
|
419
|
+
default_thinking_mode: bool = True,
|
|
420
|
+
reasoning_content_behavior: ReasoningContentBehavior = ReasoningContentBehavior.FillEmpty,
|
|
421
|
+
responses_web_search: WebSearchBehavior = WebSearchBehavior.Drop,
|
|
422
|
+
messages_web_search: WebSearchBehavior = WebSearchBehavior.Reject,
|
|
423
|
+
thinking_max_tokens_upper_bound: int = 393216,
|
|
424
|
+
non_thinking_max_tokens_upper_bound: int = 393216,
|
|
425
|
+
) -> None: ...
|
|
426
|
+
@property
|
|
427
|
+
def default_thinking_mode(self) -> bool:
|
|
428
|
+
"""Whether requests that do not specify a thinking mode use thinking mode.
|
|
429
|
+
|
|
430
|
+
Defaults to `True`.
|
|
431
|
+
"""
|
|
432
|
+
@property
|
|
433
|
+
def model_versions_by_name(self) -> dict[str, ModelVersion]:
|
|
434
|
+
"""The target model version of each accepted request model name.
|
|
435
|
+
|
|
436
|
+
Defaults to `DeepSeek-V4-Pro` and `DeepSeek-V4.1-Flash`; conversion
|
|
437
|
+
rejects a request whose model is not a key.
|
|
438
|
+
"""
|
|
439
|
+
@property
|
|
440
|
+
def thinking_max_tokens_upper_bound(self) -> int:
|
|
441
|
+
"""The largest accepted `max_tokens` (`max_output_tokens` in Responses)
|
|
442
|
+
of a request in thinking mode.
|
|
443
|
+
|
|
444
|
+
Chat Completions and Responses reject a larger value; Messages lowers it
|
|
445
|
+
to this bound.
|
|
446
|
+
"""
|
|
447
|
+
@property
|
|
448
|
+
def non_thinking_max_tokens_upper_bound(self) -> int:
|
|
449
|
+
"""The largest accepted `max_tokens` (`max_output_tokens` in Responses)
|
|
450
|
+
of a request outside thinking mode.
|
|
451
|
+
|
|
452
|
+
Chat Completions and Responses reject a larger value; Messages lowers it
|
|
453
|
+
to this bound.
|
|
454
|
+
"""
|
|
455
|
+
@property
|
|
456
|
+
def reasoning_content_behavior(self) -> ReasoningContentBehavior:
|
|
457
|
+
"""Missing-reasoning-content behavior, defaulting to `FillEmpty`."""
|
|
458
|
+
@property
|
|
459
|
+
def responses_web_search(self) -> WebSearchBehavior:
|
|
460
|
+
"""Responses web-search behavior, defaulting to `Drop`."""
|
|
461
|
+
@property
|
|
462
|
+
def messages_web_search(self) -> WebSearchBehavior:
|
|
463
|
+
"""Messages web-search behavior, defaulting to `Reject`."""
|
|
464
|
+
@property
|
|
465
|
+
def special_tokens(self) -> SpecialTokens:
|
|
466
|
+
"""Special token mapping, defaulting to the built-in mapping."""
|
|
467
|
+
def with_default_thinking_mode(self, default_thinking_mode: bool) -> ConversionOptions:
|
|
468
|
+
"""Construct options with the supplied default thinking mode."""
|
|
469
|
+
def with_reasoning_content_behavior(
|
|
470
|
+
self, reasoning_content_behavior: ReasoningContentBehavior
|
|
471
|
+
) -> ConversionOptions:
|
|
472
|
+
"""Construct options with the supplied missing-reasoning-content behavior."""
|
|
473
|
+
def with_responses_web_search(
|
|
474
|
+
self, responses_web_search: WebSearchBehavior
|
|
475
|
+
) -> ConversionOptions:
|
|
476
|
+
"""Construct options with the supplied Responses web-search behavior."""
|
|
477
|
+
def with_messages_web_search(
|
|
478
|
+
self, messages_web_search: WebSearchBehavior
|
|
479
|
+
) -> ConversionOptions:
|
|
480
|
+
"""Construct options with the supplied Messages web-search behavior."""
|
|
481
|
+
def with_special_tokens(self, special_tokens: SpecialTokens) -> ConversionOptions:
|
|
482
|
+
"""Construct options with the supplied special token mapping."""
|
|
483
|
+
def with_model_alias(self, model: str, model_version: ModelVersion) -> ConversionOptions:
|
|
484
|
+
"""Accept `model` as a name of `model_version`.
|
|
485
|
+
|
|
486
|
+
Adds the name, or replaces the version of an existing one.
|
|
487
|
+
"""
|
|
488
|
+
def with_model_versions_by_name(
|
|
489
|
+
self, model_versions_by_name: dict[str, ModelVersion]
|
|
490
|
+
) -> ConversionOptions:
|
|
491
|
+
"""Replace the whole table of accepted model names.
|
|
492
|
+
|
|
493
|
+
Drops the default names unless the mapping includes them.
|
|
494
|
+
"""
|
|
495
|
+
def with_thinking_max_tokens_upper_bound(
|
|
496
|
+
self, thinking_max_tokens_upper_bound: int
|
|
497
|
+
) -> ConversionOptions: ...
|
|
498
|
+
def with_non_thinking_max_tokens_upper_bound(self, non_thinking_max_tokens_upper_bound: int) -> ConversionOptions: ...
|
|
499
|
+
|
|
500
|
+
class ConversationRequest:
|
|
501
|
+
"""A Rust conversation request with inference and parsing options."""
|
|
502
|
+
|
|
503
|
+
def __init__(self, conversation: Conversation, model_version: ModelVersion) -> None:
|
|
504
|
+
"""Construct a request with default inference, parsing, and transport options."""
|
|
505
|
+
@property
|
|
506
|
+
def conversation(self) -> Conversation: ...
|
|
507
|
+
@property
|
|
508
|
+
def inference_options(self) -> InferenceOptions: ...
|
|
509
|
+
@property
|
|
510
|
+
def parsing_options(self) -> ParsingOptions: ...
|
|
511
|
+
@property
|
|
512
|
+
def model_version(self) -> ModelVersion:
|
|
513
|
+
"""The target model version.
|
|
514
|
+
|
|
515
|
+
Conversion resolves it from the request's model name; the constructor
|
|
516
|
+
takes it as an argument.
|
|
517
|
+
"""
|
|
518
|
+
@property
|
|
519
|
+
def stream(self) -> bool:
|
|
520
|
+
"""Whether the protocol request asks for a streamed response."""
|
|
521
|
+
def resolve_max_tokens(self, prompt_tokens: int, context_limit: int) -> int:
|
|
522
|
+
"""Resolve the `max_tokens` to send to the backend.
|
|
523
|
+
|
|
524
|
+
`prompt_tokens` is the number of tokens in the encoded prompt, with each
|
|
525
|
+
image counted at its image token count instead of as one placeholder,
|
|
526
|
+
and `context_limit` is the number of tokens the model's context holds.
|
|
527
|
+
A requested `max_tokens` is kept; an unspecified one becomes 8192
|
|
528
|
+
outside thinking mode, 131072 in thinking mode with `max` effort, and
|
|
529
|
+
65536 in thinking mode otherwise. The result is lowered to the context
|
|
530
|
+
left after the prompt and raised to at least 1. Raises `ConversionError`
|
|
531
|
+
when `prompt_tokens` plus the requested `max_tokens` exceeds
|
|
532
|
+
`context_limit`, or, without a requested `max_tokens`, when
|
|
533
|
+
`prompt_tokens` alone exceeds it.
|
|
534
|
+
"""
|
|
535
|
+
|
|
536
|
+
class ChatCompletionRequest:
|
|
537
|
+
"""A Rust Chat Completions request; even failed conversion consumes it."""
|
|
538
|
+
|
|
539
|
+
def __init__(self, body: RequestBody) -> None: ...
|
|
540
|
+
@property
|
|
541
|
+
def model(self) -> str:
|
|
542
|
+
"""The requested model name; read it before `convert` consumes the request."""
|
|
543
|
+
def convert(self, options: ConversionOptions) -> ConversationRequest: ...
|
|
544
|
+
@staticmethod
|
|
545
|
+
def chunk_generator(
|
|
546
|
+
request: ConversationRequest, id: str, model: str
|
|
547
|
+
) -> ChatCompletionChunkGenerator: ...
|
|
548
|
+
|
|
549
|
+
class ResponsesRequest:
|
|
550
|
+
"""A Rust Responses request; even failed conversion consumes it."""
|
|
551
|
+
|
|
552
|
+
def __init__(self, body: RequestBody) -> None: ...
|
|
553
|
+
@property
|
|
554
|
+
def model(self) -> str:
|
|
555
|
+
"""The requested model name; read it before `convert` consumes the request."""
|
|
556
|
+
def namespace_tool_map(self, options: ConversionOptions) -> dict[str, tuple[str, str]]:
|
|
557
|
+
"""Return the function names of the declared namespace tools.
|
|
558
|
+
|
|
559
|
+
Each function name maps to `(namespace, local name)`, as conversion with
|
|
560
|
+
`options` assigns them; read them before `convert` consumes this request.
|
|
561
|
+
Raises `ConversionError` for an invalid tool declaration.
|
|
562
|
+
"""
|
|
563
|
+
def echo(self) -> ResponsesEcho:
|
|
564
|
+
"""Return the request settings that responses report.
|
|
565
|
+
|
|
566
|
+
Read them before `convert` consumes this request.
|
|
567
|
+
"""
|
|
568
|
+
|
|
569
|
+
def convert(self, options: ConversionOptions) -> ConversationRequest: ...
|
|
570
|
+
@staticmethod
|
|
571
|
+
def chunk_generator(
|
|
572
|
+
request: ConversationRequest, id: str, model: str
|
|
573
|
+
) -> ResponsesChunkGenerator: ...
|
|
574
|
+
|
|
575
|
+
class MessagesRequest:
|
|
576
|
+
"""A Rust Messages request; even failed conversion consumes it."""
|
|
577
|
+
|
|
578
|
+
def __init__(self, body: RequestBody) -> None: ...
|
|
579
|
+
@property
|
|
580
|
+
def model(self) -> str:
|
|
581
|
+
"""The requested model name; read it before `convert` consumes the request."""
|
|
582
|
+
def convert(self, options: ConversionOptions) -> ConversationRequest: ...
|
|
583
|
+
@staticmethod
|
|
584
|
+
def chunk_generator(
|
|
585
|
+
request: ConversationRequest, id: str, model: str
|
|
586
|
+
) -> MessagesChunkGenerator: ...
|
|
587
|
+
|
|
588
|
+
class InferenceOptions:
|
|
589
|
+
"""Inference parameters extracted by protocol conversion.
|
|
590
|
+
|
|
591
|
+
Conversion always sets `temperature` (1.0 in thinking mode) and `top_p` to
|
|
592
|
+
their resolved values. Other unspecified parameters are `None`;
|
|
593
|
+
`ConversationRequest.resolve_max_tokens` supplies the default `max_tokens`,
|
|
594
|
+
and the caller applies the other model-specific defaults.
|
|
595
|
+
"""
|
|
596
|
+
|
|
597
|
+
@property
|
|
598
|
+
def max_tokens(self) -> int | None:
|
|
599
|
+
"""Maximum number of output tokens, or `None` when the request sets none.
|
|
600
|
+
|
|
601
|
+
`ConversationRequest.resolve_max_tokens` supplies the default after the
|
|
602
|
+
prompt is encoded.
|
|
603
|
+
"""
|
|
604
|
+
@property
|
|
605
|
+
def temperature(self) -> float | None:
|
|
606
|
+
"""Sampling temperature: 1.0 in thinking mode, otherwise the requested value or 1.0."""
|
|
607
|
+
@property
|
|
608
|
+
def top_p(self) -> float | None:
|
|
609
|
+
"""Final `top_p` for the target model version."""
|
|
610
|
+
@property
|
|
611
|
+
def logprobs(self) -> bool:
|
|
612
|
+
"""Whether the request asks for the log probability of each output token."""
|
|
613
|
+
@property
|
|
614
|
+
def top_logprobs(self) -> int | None:
|
|
615
|
+
"""Number of most likely alternatives reported per output token, in `[0, 20]`."""
|
|
616
|
+
@property
|
|
617
|
+
def seed(self) -> int | None:
|
|
618
|
+
"""Sampling seed in `[0, 2^63)`; the caller chooses an unspecified seed."""
|
|
619
|
+
@property
|
|
620
|
+
def output_constraint(self) -> OutputConstraint | None:
|
|
621
|
+
"""The constraint that constrained decoding would enforce on the output,
|
|
622
|
+
or `None`; whether the backend applies it is the caller's decision.
|
|
623
|
+
"""
|
|
624
|
+
|
|
625
|
+
class OutputConstraint:
|
|
626
|
+
"""A constraint on the model output that the backend can enforce by
|
|
627
|
+
constrained decoding, as a kind name and a constraint string.
|
|
628
|
+
"""
|
|
629
|
+
|
|
630
|
+
@property
|
|
631
|
+
def kind(self) -> str:
|
|
632
|
+
"""`json`, `regex`, `tool_call`, or `tool_call_required`."""
|
|
633
|
+
@property
|
|
634
|
+
def schema(self) -> str:
|
|
635
|
+
"""The schema as compact JSON, the regular expression, the tool list as
|
|
636
|
+
a compact JSON array of Chat Completions function tools with
|
|
637
|
+
`defer_loading: true` on deferred tools, or an empty string for any JSON
|
|
638
|
+
value.
|
|
639
|
+
"""
|
|
640
|
+
|
|
641
|
+
class ImageInfo:
|
|
642
|
+
"""A preprocessed image for the inference backend.
|
|
643
|
+
|
|
644
|
+
It holds the encoded image bytes and the image dimensions in pixels after
|
|
645
|
+
preprocessing.
|
|
646
|
+
"""
|
|
647
|
+
|
|
648
|
+
def __init__(self, data: bytes, width: int, height: int) -> None: ...
|
|
649
|
+
@property
|
|
650
|
+
def data(self) -> bytes: ...
|
|
651
|
+
@property
|
|
652
|
+
def width(self) -> int: ...
|
|
653
|
+
@property
|
|
654
|
+
def height(self) -> int: ...
|
|
655
|
+
|
|
656
|
+
class MultiModalData:
|
|
657
|
+
"""Images in the order their placeholders appear in a prompt."""
|
|
658
|
+
|
|
659
|
+
def __init__(self, images: Sequence[ImageInfo] | None = None) -> None: ...
|
|
660
|
+
@property
|
|
661
|
+
def images(self) -> list[ImageInfo]: ...
|
|
662
|
+
def is_empty(self) -> bool: ...
|
|
663
|
+
def image_token_adjustment(self) -> int:
|
|
664
|
+
"""Return the number of inference input tokens beyond one per placeholder.
|
|
665
|
+
|
|
666
|
+
The V4.1 image token specification gives the image token count of each
|
|
667
|
+
image, which occupies one placeholder in the prompt; the adjustment is the
|
|
668
|
+
sum of the differences. Raises `CalcResizeError` when fitting an image
|
|
669
|
+
does not converge.
|
|
670
|
+
"""
|
|
671
|
+
|
|
672
|
+
class ImageQuota:
|
|
673
|
+
"""The image count and encoded bytes recorded by the completed resolve calls of one request.
|
|
674
|
+
|
|
675
|
+
To apply the image count and total byte limits across the resolve calls of a
|
|
676
|
+
request, the caller must pass the same quota to every call. A call records
|
|
677
|
+
its sources after it preprocesses every one of them, so a failed call adds
|
|
678
|
+
nothing.
|
|
679
|
+
"""
|
|
680
|
+
|
|
681
|
+
def __init__(self) -> None: ...
|
|
682
|
+
def image_count(self) -> int: ...
|
|
683
|
+
def byte_size(self) -> int: ...
|
|
684
|
+
|
|
685
|
+
class PreprocessOptions:
|
|
686
|
+
"""Options passed to one Rust image preprocessing operation."""
|
|
687
|
+
|
|
688
|
+
def __init__(
|
|
689
|
+
self, detail: ImageDetail, max_dimension_px: int, low_detail_max_dimension_px: int
|
|
690
|
+
) -> None: ...
|
|
691
|
+
@property
|
|
692
|
+
def detail(self) -> ImageDetail: ...
|
|
693
|
+
@property
|
|
694
|
+
def max_dimension_px(self) -> int: ...
|
|
695
|
+
@property
|
|
696
|
+
def low_detail_max_dimension_px(self) -> int: ...
|
|
697
|
+
|
|
698
|
+
class ReqwestImageFetcher:
|
|
699
|
+
"""An image fetcher that downloads external image URLs through the Rust `reqwest` client.
|
|
700
|
+
|
|
701
|
+
Without a destination filter, this fetcher connects to any address. When
|
|
702
|
+
untrusted clients can supply image URLs, the caller should install a filter
|
|
703
|
+
with `with_destination_filter` to protect against SSRF.
|
|
704
|
+
"""
|
|
705
|
+
|
|
706
|
+
def __init__(self) -> None: ...
|
|
707
|
+
@staticmethod
|
|
708
|
+
def with_max_bytes(max_bytes: int) -> ReqwestImageFetcher: ...
|
|
709
|
+
def with_destination_filter(
|
|
710
|
+
self, destination_filter: Callable[[str, str], bool]
|
|
711
|
+
) -> ReqwestImageFetcher:
|
|
712
|
+
"""Return a fetcher with this size limit that connects only to allowed addresses.
|
|
713
|
+
|
|
714
|
+
`destination_filter(host, address)` receives the host of the image URL or
|
|
715
|
+
of a redirect target and one address as a string, such as `"10.0.0.1"`,
|
|
716
|
+
and returns whether the fetcher can connect to it. For a host name, the
|
|
717
|
+
fetcher connects only to the resolved addresses the filter allows. A host
|
|
718
|
+
with no allowed address raises `ImageError` with kind
|
|
719
|
+
`"DestinationRejected"`. A callable that raises or returns a non-boolean
|
|
720
|
+
value rejects the address. The returned fetcher uses no proxy. The
|
|
721
|
+
library does not include a filter implementation; the caller writes the
|
|
722
|
+
rule. Raises `TypeError` when `destination_filter` is not callable.
|
|
723
|
+
"""
|
|
724
|
+
def fetch(self, url: str) -> bytes: ...
|
|
725
|
+
|
|
726
|
+
class OpenCvImagePreprocessor:
|
|
727
|
+
"""An image preprocessor that uses the Rust OpenCV implementation."""
|
|
728
|
+
|
|
729
|
+
def __init__(self) -> None: ...
|
|
730
|
+
def preprocess(self, data: bytes, options: PreprocessOptions) -> ImageInfo: ...
|
|
731
|
+
|
|
732
|
+
class ImageResolver:
|
|
733
|
+
"""An image resolver built from explicit fetching and preprocessing components."""
|
|
734
|
+
|
|
735
|
+
def __init__(
|
|
736
|
+
self, fetcher: ReqwestImageFetcher, preprocessor: OpenCvImagePreprocessor
|
|
737
|
+
) -> None: ...
|
|
738
|
+
def resolve(self, sources: Sequence[ImageSource], quota: ImageQuota) -> MultiModalData:
|
|
739
|
+
"""Resolve image sources and update the supplied quota.
|
|
740
|
+
|
|
741
|
+
A failed call leaves the quota unchanged.
|
|
742
|
+
"""
|
|
743
|
+
|
|
744
|
+
class PromptUsage:
|
|
745
|
+
"""Prompt-side token counts from the backend."""
|
|
746
|
+
|
|
747
|
+
def __init__(
|
|
748
|
+
self, *, prompt_tokens: int = 0, prompt_cache_hit_tokens: int = 0,
|
|
749
|
+
) -> None: ...
|
|
750
|
+
@property
|
|
751
|
+
def prompt_tokens(self) -> int: ...
|
|
752
|
+
@property
|
|
753
|
+
def prompt_cache_hit_tokens(self) -> int: ...
|
|
754
|
+
|
|
755
|
+
class InferenceFinishReason:
|
|
756
|
+
"""Backend finish reasons; output parsing determines the protocol finish reason."""
|
|
757
|
+
|
|
758
|
+
Stop: InferenceFinishReason
|
|
759
|
+
Length: InferenceFinishReason
|
|
760
|
+
ContentFilter: InferenceFinishReason
|
|
761
|
+
|
|
762
|
+
class InferenceChunk:
|
|
763
|
+
"""One backend update, constructed with `ready`, `text`, `tokens`, or `finish`."""
|
|
764
|
+
|
|
765
|
+
@staticmethod
|
|
766
|
+
def ready(
|
|
767
|
+
*, prompt_usage: PromptUsage | None = None, system_fingerprint: str | None = None,
|
|
768
|
+
) -> InferenceChunk: ...
|
|
769
|
+
@staticmethod
|
|
770
|
+
def text(content: str, token_count: int = 0) -> InferenceChunk:
|
|
771
|
+
"""Construct a text chunk from `content` and the number of tokens it accounts for."""
|
|
772
|
+
@staticmethod
|
|
773
|
+
def tokens(
|
|
774
|
+
token_ids: Sequence[int],
|
|
775
|
+
logprobs: Sequence[tuple[float, Sequence[tuple[int, float]]]] | None = None,
|
|
776
|
+
) -> InferenceChunk:
|
|
777
|
+
"""Construct a chunk from the token IDs of one backend output.
|
|
778
|
+
|
|
779
|
+
`logprobs` holds one `(logprob, top_logprobs)` pair per token ID.
|
|
780
|
+
"""
|
|
781
|
+
@staticmethod
|
|
782
|
+
def finish(finish_reason: InferenceFinishReason) -> InferenceChunk: ...
|
|
783
|
+
@property
|
|
784
|
+
def kind(self) -> Literal["ready", "text", "tokens", "finish"]: ...
|
|
785
|
+
@property
|
|
786
|
+
def content(self) -> str | None: ...
|
|
787
|
+
@property
|
|
788
|
+
def token_ids(self) -> list[int] | None:
|
|
789
|
+
"""The token IDs of a `tokens` chunk."""
|
|
790
|
+
@property
|
|
791
|
+
def finish_reason(self) -> InferenceFinishReason | None: ...
|
|
792
|
+
@property
|
|
793
|
+
def prompt_usage(self) -> PromptUsage | None: ...
|
|
794
|
+
@property
|
|
795
|
+
def token_count(self) -> int | None:
|
|
796
|
+
"""The number of tokens this chunk's content accounts for; text chunks only."""
|
|
797
|
+
@property
|
|
798
|
+
def system_fingerprint(self) -> str | None: ...
|
|
799
|
+
|
|
800
|
+
class ThinkingInitialStage:
|
|
801
|
+
"""The stage where parsing begins in thinking mode."""
|
|
802
|
+
|
|
803
|
+
ReasoningStart: ThinkingInitialStage
|
|
804
|
+
"""Begin the reasoning content of a new assistant turn, discarding leading newlines."""
|
|
805
|
+
ReasoningContinuation: ThinkingInitialStage
|
|
806
|
+
"""Continue the reasoning content of a prefix continuation, preserving leading newlines."""
|
|
807
|
+
ContentContinuation: ThinkingInitialStage
|
|
808
|
+
"""Continue the answer content of a prefix continuation whose reasoning content has ended.
|
|
809
|
+
|
|
810
|
+
Leading newlines are preserved.
|
|
811
|
+
"""
|
|
812
|
+
|
|
813
|
+
def starts_in_reasoning(self) -> bool:
|
|
814
|
+
"""Return whether parsing begins in reasoning content."""
|
|
815
|
+
|
|
816
|
+
class ParsingOptions:
|
|
817
|
+
"""Settings passed directly to the Rust stream parser."""
|
|
818
|
+
|
|
819
|
+
def __init__(
|
|
820
|
+
self,
|
|
821
|
+
*,
|
|
822
|
+
parse_tool_calls: bool = True,
|
|
823
|
+
starts_in_tool_calls: bool = False,
|
|
824
|
+
parse_json_output: bool = False,
|
|
825
|
+
thinking_initial_stage: ThinkingInitialStage | None = None,
|
|
826
|
+
stop_sequences: Sequence[str] | None = None,
|
|
827
|
+
special_tokens: SpecialTokens | None = None,
|
|
828
|
+
) -> None: ...
|
|
829
|
+
parse_tool_calls: bool
|
|
830
|
+
"""Whether to parse model-specific tool-call markup."""
|
|
831
|
+
starts_in_tool_calls: bool
|
|
832
|
+
"""Whether parsing begins inside the tool-call block that the prompt opened.
|
|
833
|
+
|
|
834
|
+
Used for a required tool choice; takes precedence over `thinking_initial_stage`.
|
|
835
|
+
"""
|
|
836
|
+
parse_json_output: bool
|
|
837
|
+
"""Whether to recognize fenced or bare JSON output and replace the text around it with spaces."""
|
|
838
|
+
thinking_initial_stage: ThinkingInitialStage | None
|
|
839
|
+
"""The stage where parsing begins in thinking mode; `None` means thinking mode is off.
|
|
840
|
+
|
|
841
|
+
A stage also makes the processor report reasoning tokens.
|
|
842
|
+
"""
|
|
843
|
+
@property
|
|
844
|
+
def stop_sequences(self) -> list[str]: ...
|
|
845
|
+
@stop_sequences.setter
|
|
846
|
+
def stop_sequences(self, value: Sequence[str]) -> None: ...
|
|
847
|
+
@property
|
|
848
|
+
def special_tokens(self) -> SpecialTokens: ...
|
|
849
|
+
@special_tokens.setter
|
|
850
|
+
def special_tokens(self, value: SpecialTokens) -> None: ...
|
|
851
|
+
|
|
852
|
+
class ChatCompletionChunkGenerator:
|
|
853
|
+
"""A Rust Chat Completions generator consumed by a stream processor."""
|
|
854
|
+
|
|
855
|
+
class ResponsesChunkGenerator:
|
|
856
|
+
"""A Rust Responses generator consumed by a stream processor."""
|
|
857
|
+
|
|
858
|
+
def with_namespace_tool_map(
|
|
859
|
+
self, namespace_tool_map: dict[str, tuple[str, str]]
|
|
860
|
+
) -> ResponsesChunkGenerator:
|
|
861
|
+
"""Consume this generator and construct one that splits namespace tool names."""
|
|
862
|
+
def with_echo(self, echo: ResponsesEcho) -> ResponsesChunkGenerator:
|
|
863
|
+
"""Consume this generator and construct one whose responses report the request settings."""
|
|
864
|
+
|
|
865
|
+
class ResponsesEcho:
|
|
866
|
+
"""Request settings that Responses response objects report, as the request specified them.
|
|
867
|
+
|
|
868
|
+
`ResponsesRequest.echo` reads them from a request; the constructor builds
|
|
869
|
+
the settings of an unspecified request. The properties expose the scalar
|
|
870
|
+
settings; the reasoning, text, tool choice, and tool settings are reported
|
|
871
|
+
only through the response.
|
|
872
|
+
"""
|
|
873
|
+
|
|
874
|
+
def __init__(self) -> None:
|
|
875
|
+
"""Construct the settings of an unspecified request.
|
|
876
|
+
|
|
877
|
+
No instructions, output token limit, or user; temperature and `top_p` of
|
|
878
|
+
1.0; zero `top_logprobs`.
|
|
879
|
+
"""
|
|
880
|
+
@property
|
|
881
|
+
def instructions(self) -> str | None: ...
|
|
882
|
+
@property
|
|
883
|
+
def max_output_tokens(self) -> int | None: ...
|
|
884
|
+
@property
|
|
885
|
+
def temperature(self) -> float:
|
|
886
|
+
"""The requested temperature or 1.0, not the sampling temperature."""
|
|
887
|
+
@property
|
|
888
|
+
def top_p(self) -> float:
|
|
889
|
+
"""The requested `top_p` or 1.0, not the sampling `top_p`."""
|
|
890
|
+
@property
|
|
891
|
+
def top_logprobs(self) -> int:
|
|
892
|
+
"""The requested `top_logprobs`, or 0."""
|
|
893
|
+
@property
|
|
894
|
+
def user(self) -> str | None: ...
|
|
895
|
+
|
|
896
|
+
class MessagesChunkGenerator:
|
|
897
|
+
"""A Rust Messages generator consumed by a stream processor."""
|
|
898
|
+
|
|
899
|
+
def __init__(self, id: str, model: str, thinking_mode: bool) -> None: ...
|
|
900
|
+
def with_signature(self, signature: str) -> MessagesChunkGenerator:
|
|
901
|
+
"""Consume this generator and construct one with the supplied signature.
|
|
902
|
+
|
|
903
|
+
The new generator emits `signature` at the end of each thinking block. The
|
|
904
|
+
default signature is the response ID.
|
|
905
|
+
"""
|
|
906
|
+
|
|
907
|
+
class ChatCompletionChunk:
|
|
908
|
+
"""A Rust Chat Completions chunk consumed by response accumulation."""
|
|
909
|
+
|
|
910
|
+
def to_json(self) -> str: ...
|
|
911
|
+
|
|
912
|
+
class ResponsesStreamEvent:
|
|
913
|
+
"""A Rust Responses event consumed by response accumulation."""
|
|
914
|
+
|
|
915
|
+
def to_json(self) -> str: ...
|
|
916
|
+
|
|
917
|
+
class MessagesStreamEvent:
|
|
918
|
+
"""A Rust Messages event consumed by response accumulation."""
|
|
919
|
+
|
|
920
|
+
def to_json(self) -> str: ...
|
|
921
|
+
|
|
922
|
+
class ChatCompletionResponse:
|
|
923
|
+
"""A Rust Chat Completions response with explicit accumulation."""
|
|
924
|
+
|
|
925
|
+
def __init__(
|
|
926
|
+
self, id: str, model: str, created: int, prompt_tokens: int, prompt_cache_hit_tokens: int
|
|
927
|
+
) -> None: ...
|
|
928
|
+
def accumulate(self, chunk: ChatCompletionChunk) -> None:
|
|
929
|
+
"""Consume this chunk and apply its delta to the response."""
|
|
930
|
+
|
|
931
|
+
def to_json(self) -> str: ...
|
|
932
|
+
@staticmethod
|
|
933
|
+
def sse_event_name(chunk: ChatCompletionChunk) -> str | None:
|
|
934
|
+
"""Return the SSE event name of `chunk`, or `None` for an unnamed data event."""
|
|
935
|
+
@staticmethod
|
|
936
|
+
def sse_done_data() -> str | None:
|
|
937
|
+
"""Return the data of the final SSE message, `[DONE]`."""
|
|
938
|
+
|
|
939
|
+
class ResponsesResponse:
|
|
940
|
+
"""A Rust Responses response with explicit accumulation."""
|
|
941
|
+
|
|
942
|
+
def __init__(
|
|
943
|
+
self, id: str, model: str, created: int, prompt_tokens: int, prompt_cache_hit_tokens: int
|
|
944
|
+
) -> None: ...
|
|
945
|
+
def accumulate(self, chunk: ResponsesStreamEvent) -> None:
|
|
946
|
+
"""Consume this event and apply its delta to the response."""
|
|
947
|
+
|
|
948
|
+
def to_json(self) -> str: ...
|
|
949
|
+
@staticmethod
|
|
950
|
+
def sse_event_name(chunk: ResponsesStreamEvent) -> str | None:
|
|
951
|
+
"""Return the SSE event name of `chunk`."""
|
|
952
|
+
@staticmethod
|
|
953
|
+
def sse_done_data() -> str | None:
|
|
954
|
+
"""Return `None`: a Responses stream has no final data message."""
|
|
955
|
+
|
|
956
|
+
class MessagesResponse:
|
|
957
|
+
"""A Rust Messages response with explicit accumulation."""
|
|
958
|
+
|
|
959
|
+
def __init__(
|
|
960
|
+
self, id: str, model: str, created: int, prompt_tokens: int, prompt_cache_hit_tokens: int
|
|
961
|
+
) -> None: ...
|
|
962
|
+
def accumulate(self, chunk: MessagesStreamEvent) -> None:
|
|
963
|
+
"""Consume this event and apply its delta to the response."""
|
|
964
|
+
|
|
965
|
+
def to_json(self) -> str: ...
|
|
966
|
+
@staticmethod
|
|
967
|
+
def sse_event_name(chunk: MessagesStreamEvent) -> str | None:
|
|
968
|
+
"""Return the SSE event name of `chunk`."""
|
|
969
|
+
@staticmethod
|
|
970
|
+
def sse_done_data() -> str | None:
|
|
971
|
+
"""Return `None`: a Messages stream has no final data message."""
|
|
972
|
+
|
|
973
|
+
class Tokenizer:
|
|
974
|
+
"""A Hugging Face tokenizer loaded from a `tokenizer.json` file.
|
|
975
|
+
|
|
976
|
+
A prompt encoding uses it, after `with_tokenizer`, to encode conversations into
|
|
977
|
+
token IDs. A stream processor uses it to decode the token IDs of `tokens`
|
|
978
|
+
inference chunks.
|
|
979
|
+
"""
|
|
980
|
+
|
|
981
|
+
@staticmethod
|
|
982
|
+
def from_file(path: str) -> Tokenizer:
|
|
983
|
+
"""Load a tokenizer from a `tokenizer.json` file."""
|
|
984
|
+
|
|
985
|
+
@staticmethod
|
|
986
|
+
def from_str(text: str) -> Tokenizer:
|
|
987
|
+
"""Load a tokenizer from the contents of a `tokenizer.json` file."""
|
|
988
|
+
|
|
989
|
+
@staticmethod
|
|
990
|
+
def from_pretrained(
|
|
991
|
+
identifier: str, revision: str | None = None, token: str | None = None
|
|
992
|
+
) -> Tokenizer:
|
|
993
|
+
"""Download and cache `tokenizer.json` from the Hugging Face Hub."""
|
|
994
|
+
|
|
995
|
+
def encode(self, text: str) -> list[int]:
|
|
996
|
+
"""Encode `text` into token IDs with the full vocabulary, including the added vocabulary.
|
|
997
|
+
|
|
998
|
+
A special-token spelling in `text` encodes as that token's ID. The
|
|
999
|
+
post-processor adds no special tokens, such as a BOS token. This is not
|
|
1000
|
+
prompt encoding, which encodes plain text without the added vocabulary:
|
|
1001
|
+
`DeepseekV4Encoding.encode` and `DeepseekV41Encoding.encode` perform
|
|
1002
|
+
prompt encoding.
|
|
1003
|
+
"""
|
|
1004
|
+
|
|
1005
|
+
class StreamProcessor:
|
|
1006
|
+
"""Adapt Python inference chunks to the Rust processor's input stream."""
|
|
1007
|
+
|
|
1008
|
+
def __init__(
|
|
1009
|
+
self,
|
|
1010
|
+
generator: ChatCompletionChunkGenerator | ResponsesChunkGenerator | MessagesChunkGenerator,
|
|
1011
|
+
options: ParsingOptions,
|
|
1012
|
+
tokenizer: Tokenizer | None = None,
|
|
1013
|
+
) -> None:
|
|
1014
|
+
"""Consume the generator and construct a Rust stream processor.
|
|
1015
|
+
|
|
1016
|
+
The optional tokenizer decodes `tokens` chunks. Without one, such a chunk
|
|
1017
|
+
raises `RuntimeError` and closes the processor.
|
|
1018
|
+
"""
|
|
1019
|
+
|
|
1020
|
+
@property
|
|
1021
|
+
def finished(self) -> bool:
|
|
1022
|
+
"""Whether processing completed normally and the processor remains unclosed."""
|
|
1023
|
+
|
|
1024
|
+
def push(
|
|
1025
|
+
self, chunk: InferenceChunk
|
|
1026
|
+
) -> list[ChatCompletionChunk | ResponsesStreamEvent | MessagesStreamEvent]:
|
|
1027
|
+
"""Process one chunk.
|
|
1028
|
+
|
|
1029
|
+
Raises `RuntimeError` after completion or close, or on a stream error: a
|
|
1030
|
+
`tokens` chunk without a tokenizer, a decoding failure, or a log
|
|
1031
|
+
probability count that differs from the token ID count. A stream error
|
|
1032
|
+
closes the processor.
|
|
1033
|
+
"""
|
|
1034
|
+
|
|
1035
|
+
def finish(self) -> list[ChatCompletionChunk | ResponsesStreamEvent | MessagesStreamEvent]:
|
|
1036
|
+
"""Close the input and process buffered output; repeated calls after completion yield no chunks.
|
|
1037
|
+
|
|
1038
|
+
Calls after close or a stream error raise `RuntimeError`.
|
|
1039
|
+
"""
|
|
1040
|
+
|
|
1041
|
+
def close(self) -> None:
|
|
1042
|
+
"""Release processing state without producing successful completion."""
|