lm-deluge 0.0.12__py3-none-any.whl → 0.0.14__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.
Potentially problematic release.
This version of lm-deluge might be problematic. Click here for more details.
- lm_deluge/__init__.py +11 -1
- lm_deluge/agent.py +0 -0
- lm_deluge/api_requests/anthropic.py +90 -58
- lm_deluge/api_requests/base.py +63 -180
- lm_deluge/api_requests/bedrock.py +34 -10
- lm_deluge/api_requests/common.py +2 -1
- lm_deluge/api_requests/mistral.py +6 -15
- lm_deluge/api_requests/openai.py +342 -50
- lm_deluge/api_requests/response.py +153 -0
- lm_deluge/batches.py +498 -0
- lm_deluge/client.py +354 -636
- lm_deluge/computer_use/anthropic_tools.py +75 -0
- lm_deluge/{sampling_params.py → config.py} +12 -4
- lm_deluge/embed.py +17 -11
- lm_deluge/file.py +149 -0
- lm_deluge/models.py +33 -0
- lm_deluge/prompt.py +156 -15
- lm_deluge/rerank.py +18 -12
- lm_deluge/tool.py +11 -1
- lm_deluge/tracker.py +214 -2
- lm_deluge/util/json.py +18 -1
- {lm_deluge-0.0.12.dist-info → lm_deluge-0.0.14.dist-info}/METADATA +8 -5
- lm_deluge-0.0.14.dist-info/RECORD +44 -0
- {lm_deluge-0.0.12.dist-info → lm_deluge-0.0.14.dist-info}/WHEEL +1 -1
- lm_deluge-0.0.12.dist-info/RECORD +0 -39
- {lm_deluge-0.0.12.dist-info → lm_deluge-0.0.14.dist-info}/licenses/LICENSE +0 -0
- {lm_deluge-0.0.12.dist-info → lm_deluge-0.0.14.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
|
|
3
|
+
ToolVersion = Literal["2024-10-22", "2025-01-24", "2025-04-29"]
|
|
4
|
+
ToolType = Literal["bash", "computer", "editor"]
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def model_to_version(model: str) -> ToolVersion:
|
|
8
|
+
if "opus" not in model and "sonnet" not in model:
|
|
9
|
+
raise ValueError("cannot use computer tools with incompatible model")
|
|
10
|
+
if "claude-4" in model:
|
|
11
|
+
return "2025-04-29"
|
|
12
|
+
elif "3.7" in model:
|
|
13
|
+
return "2025-01-24"
|
|
14
|
+
else:
|
|
15
|
+
return "2024-10-22"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_anthropic_cu_tools(
|
|
19
|
+
model: str,
|
|
20
|
+
display_width: int,
|
|
21
|
+
display_height: int,
|
|
22
|
+
exclude_tools: list[ToolType] | None = None,
|
|
23
|
+
):
|
|
24
|
+
version = model_to_version(model)
|
|
25
|
+
if version == "2024-10-22":
|
|
26
|
+
result = [
|
|
27
|
+
{
|
|
28
|
+
"name": "computer",
|
|
29
|
+
"type": "computer_20241022",
|
|
30
|
+
"display_width_px": display_width,
|
|
31
|
+
"display_height_px": display_height,
|
|
32
|
+
"display_number": None,
|
|
33
|
+
},
|
|
34
|
+
{"name": "str_replace_editor", "type": "text_editor_20250429"},
|
|
35
|
+
{"type": "bash_20250124", "name": "bash"},
|
|
36
|
+
]
|
|
37
|
+
elif version == "2025-01-24":
|
|
38
|
+
result = [
|
|
39
|
+
{
|
|
40
|
+
"name": "computer",
|
|
41
|
+
"type": "computer_20250124",
|
|
42
|
+
"display_width_px": display_width,
|
|
43
|
+
"display_height_px": display_height,
|
|
44
|
+
"display_number": None,
|
|
45
|
+
},
|
|
46
|
+
{"name": "str_replace_editor", "type": "text_editor_20250124"},
|
|
47
|
+
{"type": "bash_20250124", "name": "bash"},
|
|
48
|
+
]
|
|
49
|
+
elif version == "2025-04-29":
|
|
50
|
+
result = [
|
|
51
|
+
{
|
|
52
|
+
"name": "computer",
|
|
53
|
+
"type": "computer_20250124",
|
|
54
|
+
"display_width_px": display_width,
|
|
55
|
+
"display_height_px": display_height,
|
|
56
|
+
"display_number": None,
|
|
57
|
+
},
|
|
58
|
+
{"name": "str_replace_based_edit_tool", "type": "text_editor_20250429"},
|
|
59
|
+
{
|
|
60
|
+
"name": "bash",
|
|
61
|
+
"type": "bash_20250124",
|
|
62
|
+
},
|
|
63
|
+
]
|
|
64
|
+
else:
|
|
65
|
+
raise ValueError("invalid tool version")
|
|
66
|
+
|
|
67
|
+
if exclude_tools is None:
|
|
68
|
+
return result
|
|
69
|
+
if "bash" in exclude_tools:
|
|
70
|
+
result = [x for x in result if x["name"] != "bash"]
|
|
71
|
+
if "editor" in exclude_tools:
|
|
72
|
+
result = [x for x in result if "edit" not in x["name"]]
|
|
73
|
+
if "computer" in exclude_tools:
|
|
74
|
+
result = [x for x in result if "computer" not in x["name"]]
|
|
75
|
+
return result
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
1
|
from typing import Literal
|
|
3
2
|
|
|
3
|
+
from pydantic import BaseModel
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
class SamplingParams:
|
|
5
|
+
|
|
6
|
+
class SamplingParams(BaseModel):
|
|
7
7
|
temperature: float = 0.0
|
|
8
8
|
top_p: float = 1.0
|
|
9
9
|
json_mode: bool = False
|
|
10
10
|
max_new_tokens: int = 512
|
|
11
|
-
reasoning_effort: Literal["low", "medium", "high", None] = None
|
|
11
|
+
reasoning_effort: Literal["low", "medium", "high", "none", None] = None
|
|
12
|
+
logprobs: bool = False
|
|
13
|
+
top_logprobs: int | None = None
|
|
12
14
|
|
|
13
15
|
def to_vllm(self):
|
|
14
16
|
try:
|
|
@@ -23,3 +25,9 @@ class SamplingParams:
|
|
|
23
25
|
top_p=self.top_p,
|
|
24
26
|
max_tokens=self.max_new_tokens,
|
|
25
27
|
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ComputerUseParams(BaseModel):
|
|
31
|
+
enabled: bool = False
|
|
32
|
+
display_width: int = 1024
|
|
33
|
+
display_height: int = 768
|
lm_deluge/embed.py
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
### specific utility for cohere rerank api
|
|
2
|
-
import os
|
|
3
|
-
import numpy as np
|
|
4
|
-
import aiohttp
|
|
5
|
-
from tqdm.auto import tqdm
|
|
6
2
|
import asyncio
|
|
3
|
+
import os
|
|
7
4
|
import time
|
|
8
|
-
from typing import Any
|
|
9
5
|
from dataclasses import dataclass
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import aiohttp
|
|
9
|
+
import numpy as np
|
|
10
|
+
from tqdm.auto import tqdm
|
|
11
|
+
|
|
10
12
|
from .tracker import StatusTracker
|
|
11
13
|
|
|
12
14
|
registry = {
|
|
@@ -56,7 +58,6 @@ class EmbeddingRequest:
|
|
|
56
58
|
texts: list[str],
|
|
57
59
|
attempts_left: int,
|
|
58
60
|
status_tracker: StatusTracker,
|
|
59
|
-
retry_queue: asyncio.Queue,
|
|
60
61
|
request_timeout: int,
|
|
61
62
|
pbar: tqdm | None = None,
|
|
62
63
|
**kwargs, # openai or cohere specific params
|
|
@@ -66,7 +67,6 @@ class EmbeddingRequest:
|
|
|
66
67
|
self.texts = texts
|
|
67
68
|
self.attempts_left = attempts_left
|
|
68
69
|
self.status_tracker = status_tracker
|
|
69
|
-
self.retry_queue = retry_queue
|
|
70
70
|
self.request_timeout = request_timeout
|
|
71
71
|
self.pbar = pbar
|
|
72
72
|
self.result = []
|
|
@@ -89,7 +89,8 @@ class EmbeddingRequest:
|
|
|
89
89
|
print(error_to_print)
|
|
90
90
|
if self.attempts_left > 0:
|
|
91
91
|
self.attempts_left -= 1
|
|
92
|
-
self.retry_queue
|
|
92
|
+
assert self.status_tracker.retry_queue
|
|
93
|
+
self.status_tracker.retry_queue.put_nowait(self)
|
|
93
94
|
return
|
|
94
95
|
else:
|
|
95
96
|
print(f"Task {self.task_id} out of tries.")
|
|
@@ -243,7 +244,11 @@ async def embed_parallel_async(
|
|
|
243
244
|
|
|
244
245
|
# initialize trackers
|
|
245
246
|
retry_queue = asyncio.Queue()
|
|
246
|
-
status_tracker = StatusTracker(
|
|
247
|
+
status_tracker = StatusTracker(
|
|
248
|
+
max_tokens_per_minute=10_000_000,
|
|
249
|
+
max_requests_per_minute=max_requests_per_minute,
|
|
250
|
+
max_concurrent_requests=1_000,
|
|
251
|
+
)
|
|
247
252
|
next_request = None # variable to hold the next request to call
|
|
248
253
|
|
|
249
254
|
# initialize available capacity counts
|
|
@@ -262,7 +267,8 @@ async def embed_parallel_async(
|
|
|
262
267
|
while True:
|
|
263
268
|
# get next request (if one is not already waiting for capacity)
|
|
264
269
|
if next_request is None:
|
|
265
|
-
|
|
270
|
+
assert status_tracker.retry_queue
|
|
271
|
+
if not status_tracker.retry_queue.empty():
|
|
266
272
|
next_request = retry_queue.get_nowait()
|
|
267
273
|
print(f"Retrying request {next_request.task_id}.")
|
|
268
274
|
elif prompts_not_finished:
|
|
@@ -285,7 +291,7 @@ async def embed_parallel_async(
|
|
|
285
291
|
|
|
286
292
|
except StopIteration:
|
|
287
293
|
prompts_not_finished = False
|
|
288
|
-
print("API requests finished, only retries remain.")
|
|
294
|
+
# print("API requests finished, only retries remain.")
|
|
289
295
|
|
|
290
296
|
# update available capacity
|
|
291
297
|
current_time = time.time()
|
lm_deluge/file.py
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import io
|
|
3
|
+
import requests
|
|
4
|
+
import base64
|
|
5
|
+
import mimetypes
|
|
6
|
+
import xxhash
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(slots=True)
|
|
12
|
+
class File:
|
|
13
|
+
# raw bytes, pathlike, http url, base64 data url, or file_id
|
|
14
|
+
data: bytes | io.BytesIO | Path | str
|
|
15
|
+
media_type: str | None = None # inferred if None
|
|
16
|
+
filename: str | None = None # optional filename for uploads
|
|
17
|
+
file_id: str | None = None # for OpenAI file uploads or Anthropic file API
|
|
18
|
+
type: str = field(init=False, default="file")
|
|
19
|
+
|
|
20
|
+
# helpers -----------------------------------------------------------------
|
|
21
|
+
def _bytes(self) -> bytes:
|
|
22
|
+
if isinstance(self.data, bytes):
|
|
23
|
+
return self.data
|
|
24
|
+
elif isinstance(self.data, io.BytesIO):
|
|
25
|
+
return self.data.getvalue()
|
|
26
|
+
elif isinstance(self.data, str) and self.data.startswith("http"):
|
|
27
|
+
res = requests.get(self.data)
|
|
28
|
+
res.raise_for_status()
|
|
29
|
+
return res.content
|
|
30
|
+
elif isinstance(self.data, str) and os.path.exists(self.data):
|
|
31
|
+
with open(self.data, "rb") as f:
|
|
32
|
+
return f.read()
|
|
33
|
+
elif isinstance(self.data, Path) and self.data.exists():
|
|
34
|
+
return Path(self.data).read_bytes()
|
|
35
|
+
elif isinstance(self.data, str) and self.data.startswith("data:"):
|
|
36
|
+
header, encoded = self.data.split(",", 1)
|
|
37
|
+
return base64.b64decode(encoded)
|
|
38
|
+
else:
|
|
39
|
+
raise ValueError("unreadable file format")
|
|
40
|
+
|
|
41
|
+
def _mime(self) -> str:
|
|
42
|
+
if self.media_type:
|
|
43
|
+
return self.media_type
|
|
44
|
+
if isinstance(self.data, (Path, str)):
|
|
45
|
+
# For URL or path, try to guess from the string
|
|
46
|
+
path_str = str(self.data)
|
|
47
|
+
guess = mimetypes.guess_type(path_str)[0]
|
|
48
|
+
if guess:
|
|
49
|
+
return guess
|
|
50
|
+
return "application/pdf" # default to PDF
|
|
51
|
+
|
|
52
|
+
def _filename(self) -> str:
|
|
53
|
+
if self.filename:
|
|
54
|
+
return self.filename
|
|
55
|
+
if isinstance(self.data, (Path, str)):
|
|
56
|
+
path_str = str(self.data)
|
|
57
|
+
if path_str.startswith("http"):
|
|
58
|
+
# Extract filename from URL
|
|
59
|
+
return path_str.split("/")[-1].split("?")[0] or "document.pdf"
|
|
60
|
+
else:
|
|
61
|
+
# Extract from local path
|
|
62
|
+
return os.path.basename(path_str) or "document.pdf"
|
|
63
|
+
return "document.pdf"
|
|
64
|
+
|
|
65
|
+
def _base64(self, include_header: bool = True) -> str:
|
|
66
|
+
encoded = base64.b64encode(self._bytes()).decode("utf-8")
|
|
67
|
+
if not include_header:
|
|
68
|
+
return encoded
|
|
69
|
+
return f"data:{self._mime()};base64,{encoded}"
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def fingerprint(self) -> str:
|
|
73
|
+
# Hash the file contents for fingerprinting
|
|
74
|
+
file_bytes = self._bytes()
|
|
75
|
+
return xxhash.xxh64(file_bytes).hexdigest()
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def size(self) -> int:
|
|
79
|
+
"""Return file size in bytes."""
|
|
80
|
+
return len(self._bytes())
|
|
81
|
+
|
|
82
|
+
# ── provider-specific emission ────────────────────────────────────────────
|
|
83
|
+
def oa_chat(self) -> dict:
|
|
84
|
+
"""For OpenAI Chat Completions - file content as base64 or file_id."""
|
|
85
|
+
if self.file_id:
|
|
86
|
+
return {
|
|
87
|
+
"type": "file",
|
|
88
|
+
"file": {
|
|
89
|
+
"file_id": self.file_id,
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
else:
|
|
93
|
+
return {
|
|
94
|
+
"type": "file",
|
|
95
|
+
"file": {
|
|
96
|
+
"filename": self._filename(),
|
|
97
|
+
"file_data": self._base64(),
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
def oa_resp(self) -> dict:
|
|
102
|
+
"""For OpenAI Responses API - file content as base64 or file_id."""
|
|
103
|
+
if self.file_id:
|
|
104
|
+
return {
|
|
105
|
+
"type": "input_file",
|
|
106
|
+
"file_id": self.file_id,
|
|
107
|
+
}
|
|
108
|
+
else:
|
|
109
|
+
return {
|
|
110
|
+
"type": "input_file",
|
|
111
|
+
"filename": self._filename(),
|
|
112
|
+
"file_data": self._base64(),
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
def anthropic(self) -> dict:
|
|
116
|
+
"""For Anthropic Messages API - file content as base64 or file_id."""
|
|
117
|
+
if self.file_id:
|
|
118
|
+
return {
|
|
119
|
+
"type": "document",
|
|
120
|
+
"source": {
|
|
121
|
+
"type": "file",
|
|
122
|
+
"file_id": self.file_id,
|
|
123
|
+
},
|
|
124
|
+
}
|
|
125
|
+
else:
|
|
126
|
+
b64 = base64.b64encode(self._bytes()).decode()
|
|
127
|
+
return {
|
|
128
|
+
"type": "document",
|
|
129
|
+
"source": {
|
|
130
|
+
"type": "base64",
|
|
131
|
+
"media_type": self._mime(),
|
|
132
|
+
"data": b64,
|
|
133
|
+
},
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
def anthropic_file_upload(self) -> tuple[str, bytes, str]:
|
|
137
|
+
"""For Anthropic Files API - return tuple for file upload."""
|
|
138
|
+
filename = self._filename()
|
|
139
|
+
content = self._bytes()
|
|
140
|
+
media_type = self._mime()
|
|
141
|
+
return filename, content, media_type
|
|
142
|
+
|
|
143
|
+
def gemini(self) -> dict:
|
|
144
|
+
"""For Gemini API - not yet supported."""
|
|
145
|
+
raise NotImplementedError("File support for Gemini is not yet implemented")
|
|
146
|
+
|
|
147
|
+
def mistral(self) -> dict:
|
|
148
|
+
"""For Mistral API - not yet supported."""
|
|
149
|
+
raise NotImplementedError("File support for Mistral is not yet implemented")
|
lm_deluge/models.py
CHANGED
|
@@ -178,6 +178,21 @@ registry = {
|
|
|
178
178
|
# ░███
|
|
179
179
|
# █████
|
|
180
180
|
# ░░░░░
|
|
181
|
+
"openai-computer-use-preview": {
|
|
182
|
+
"id": "openai-computer-use-preview",
|
|
183
|
+
"name": "computer-use-preview",
|
|
184
|
+
"api_base": "https://api.openai.com/v1",
|
|
185
|
+
"api_key_env_var": "OPENAI_API_KEY",
|
|
186
|
+
"supports_json": True,
|
|
187
|
+
"supports_logprobs": False,
|
|
188
|
+
"supports_responses": True,
|
|
189
|
+
"api_spec": "openai-responses",
|
|
190
|
+
"input_cost": 2.0,
|
|
191
|
+
"output_cost": 8.0,
|
|
192
|
+
"requests_per_minute": 20,
|
|
193
|
+
"tokens_per_minute": 100_000,
|
|
194
|
+
"reasoning_model": False,
|
|
195
|
+
},
|
|
181
196
|
"o3": {
|
|
182
197
|
"id": "o3",
|
|
183
198
|
"name": "o3-2025-04-16",
|
|
@@ -185,6 +200,7 @@ registry = {
|
|
|
185
200
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
186
201
|
"supports_json": False,
|
|
187
202
|
"supports_logprobs": True,
|
|
203
|
+
"supports_responses": True,
|
|
188
204
|
"api_spec": "openai",
|
|
189
205
|
"input_cost": 10.0,
|
|
190
206
|
"output_cost": 40.0,
|
|
@@ -199,6 +215,7 @@ registry = {
|
|
|
199
215
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
200
216
|
"supports_json": False,
|
|
201
217
|
"supports_logprobs": True,
|
|
218
|
+
"supports_responses": True,
|
|
202
219
|
"api_spec": "openai",
|
|
203
220
|
"input_cost": 1.1,
|
|
204
221
|
"output_cost": 4.4,
|
|
@@ -213,6 +230,7 @@ registry = {
|
|
|
213
230
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
214
231
|
"supports_json": True,
|
|
215
232
|
"supports_logprobs": True,
|
|
233
|
+
"supports_responses": True,
|
|
216
234
|
"api_spec": "openai",
|
|
217
235
|
"input_cost": 2.0,
|
|
218
236
|
"output_cost": 8.0,
|
|
@@ -227,6 +245,7 @@ registry = {
|
|
|
227
245
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
228
246
|
"supports_json": True,
|
|
229
247
|
"supports_logprobs": True,
|
|
248
|
+
"supports_responses": True,
|
|
230
249
|
"api_spec": "openai",
|
|
231
250
|
"input_cost": 0.4,
|
|
232
251
|
"output_cost": 1.6,
|
|
@@ -241,6 +260,7 @@ registry = {
|
|
|
241
260
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
242
261
|
"supports_json": True,
|
|
243
262
|
"supports_logprobs": True,
|
|
263
|
+
"supports_responses": True,
|
|
244
264
|
"api_spec": "openai",
|
|
245
265
|
"input_cost": 0.1,
|
|
246
266
|
"output_cost": 0.4,
|
|
@@ -255,6 +275,7 @@ registry = {
|
|
|
255
275
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
256
276
|
"supports_json": False,
|
|
257
277
|
"supports_logprobs": True,
|
|
278
|
+
"supports_responses": True,
|
|
258
279
|
"api_spec": "openai",
|
|
259
280
|
"input_cost": 75.0,
|
|
260
281
|
"output_cost": 150.0,
|
|
@@ -269,6 +290,7 @@ registry = {
|
|
|
269
290
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
270
291
|
"supports_json": False,
|
|
271
292
|
"supports_logprobs": True,
|
|
293
|
+
"supports_responses": True,
|
|
272
294
|
"api_spec": "openai",
|
|
273
295
|
"input_cost": 1.1,
|
|
274
296
|
"output_cost": 4.4,
|
|
@@ -283,6 +305,7 @@ registry = {
|
|
|
283
305
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
284
306
|
"supports_json": False,
|
|
285
307
|
"supports_logprobs": True,
|
|
308
|
+
"supports_responses": True,
|
|
286
309
|
"api_spec": "openai",
|
|
287
310
|
"input_cost": 15.0,
|
|
288
311
|
"output_cost": 60.0,
|
|
@@ -297,6 +320,7 @@ registry = {
|
|
|
297
320
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
298
321
|
"supports_json": False,
|
|
299
322
|
"supports_logprobs": True,
|
|
323
|
+
"supports_responses": True,
|
|
300
324
|
"api_spec": "openai",
|
|
301
325
|
"input_cost": 15.0,
|
|
302
326
|
"output_cost": 60.0,
|
|
@@ -311,6 +335,7 @@ registry = {
|
|
|
311
335
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
312
336
|
"supports_json": False,
|
|
313
337
|
"supports_logprobs": True,
|
|
338
|
+
"supports_responses": True,
|
|
314
339
|
"api_spec": "openai",
|
|
315
340
|
"input_cost": 3.0,
|
|
316
341
|
"output_cost": 15.0,
|
|
@@ -325,6 +350,7 @@ registry = {
|
|
|
325
350
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
326
351
|
"supports_json": True,
|
|
327
352
|
"supports_logprobs": True,
|
|
353
|
+
"supports_responses": True,
|
|
328
354
|
"api_spec": "openai",
|
|
329
355
|
"input_cost": 5.0,
|
|
330
356
|
"output_cost": 15.0,
|
|
@@ -338,6 +364,7 @@ registry = {
|
|
|
338
364
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
339
365
|
"supports_json": True,
|
|
340
366
|
"supports_logprobs": True,
|
|
367
|
+
"supports_responses": True,
|
|
341
368
|
"api_spec": "openai",
|
|
342
369
|
"input_cost": 0.15,
|
|
343
370
|
"output_cost": 0.6,
|
|
@@ -351,6 +378,7 @@ registry = {
|
|
|
351
378
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
352
379
|
"supports_json": True,
|
|
353
380
|
"supports_logprobs": True,
|
|
381
|
+
"supports_responses": True,
|
|
354
382
|
"api_spec": "openai",
|
|
355
383
|
"input_cost": 0.0,
|
|
356
384
|
"output_cost": 0.0,
|
|
@@ -364,6 +392,7 @@ registry = {
|
|
|
364
392
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
365
393
|
"supports_json": True,
|
|
366
394
|
"supports_logprobs": True,
|
|
395
|
+
"supports_responses": True,
|
|
367
396
|
"api_spec": "openai",
|
|
368
397
|
"input_cost": 0.5,
|
|
369
398
|
"output_cost": 1.5,
|
|
@@ -377,6 +406,7 @@ registry = {
|
|
|
377
406
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
378
407
|
"supports_json": True,
|
|
379
408
|
"supports_logprobs": True,
|
|
409
|
+
"supports_responses": True,
|
|
380
410
|
"api_spec": "openai",
|
|
381
411
|
"input_cost": 10.0,
|
|
382
412
|
"output_cost": 30.0,
|
|
@@ -390,6 +420,7 @@ registry = {
|
|
|
390
420
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
391
421
|
"supports_json": False,
|
|
392
422
|
"supports_logprobs": False,
|
|
423
|
+
"supports_responses": True,
|
|
393
424
|
"api_spec": "openai",
|
|
394
425
|
"input_cost": 30.0,
|
|
395
426
|
"output_cost": 60.0,
|
|
@@ -403,6 +434,7 @@ registry = {
|
|
|
403
434
|
"api_key_env_var": "OPENAI_API_KEY",
|
|
404
435
|
"supports_json": False,
|
|
405
436
|
"supports_logprobs": False,
|
|
437
|
+
"supports_responses": True,
|
|
406
438
|
"api_spec": "openai",
|
|
407
439
|
"input_cost": 60.0,
|
|
408
440
|
"output_cost": 120.0,
|
|
@@ -1093,6 +1125,7 @@ class APIModel:
|
|
|
1093
1125
|
output_cost: float | None = 0 # $ per million output tokens
|
|
1094
1126
|
supports_json: bool = False
|
|
1095
1127
|
supports_logprobs: bool = False
|
|
1128
|
+
supports_responses: bool = False
|
|
1096
1129
|
reasoning_model: bool = False
|
|
1097
1130
|
regions: list[str] | dict[str, int] = field(default_factory=list)
|
|
1098
1131
|
tokens_per_minute: int | None = None
|