model-library 0.1.0__py3-none-any.whl → 0.1.2__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.
- model_library/__init__.py +7 -3
- model_library/base/__init__.py +7 -0
- model_library/{base.py → base/base.py} +47 -423
- model_library/base/batch.py +121 -0
- model_library/base/delegate_only.py +94 -0
- model_library/base/input.py +100 -0
- model_library/base/output.py +175 -0
- model_library/base/utils.py +42 -0
- model_library/config/all_models.json +164 -2
- model_library/config/anthropic_models.yaml +4 -0
- model_library/config/deepseek_models.yaml +3 -1
- model_library/config/openai_models.yaml +48 -0
- model_library/exceptions.py +2 -0
- model_library/logging.py +30 -0
- model_library/providers/__init__.py +0 -0
- model_library/providers/ai21labs.py +2 -0
- model_library/providers/alibaba.py +16 -78
- model_library/providers/amazon.py +3 -0
- model_library/providers/anthropic.py +213 -2
- model_library/providers/azure.py +2 -0
- model_library/providers/cohere.py +14 -80
- model_library/providers/deepseek.py +14 -90
- model_library/providers/fireworks.py +17 -81
- model_library/providers/google/google.py +22 -20
- model_library/providers/inception.py +15 -83
- model_library/providers/kimi.py +15 -83
- model_library/providers/mistral.py +2 -0
- model_library/providers/openai.py +2 -0
- model_library/providers/perplexity.py +12 -79
- model_library/providers/together.py +2 -0
- model_library/providers/vals.py +2 -0
- model_library/providers/xai.py +2 -0
- model_library/providers/zai.py +15 -83
- model_library/register_models.py +75 -55
- model_library/registry_utils.py +5 -5
- model_library/utils.py +3 -28
- {model_library-0.1.0.dist-info → model_library-0.1.2.dist-info}/METADATA +36 -7
- model_library-0.1.2.dist-info/RECORD +61 -0
- model_library-0.1.0.dist-info/RECORD +0 -53
- {model_library-0.1.0.dist-info → model_library-0.1.2.dist-info}/WHEEL +0 -0
- {model_library-0.1.0.dist-info → model_library-0.1.2.dist-info}/licenses/LICENSE +0 -0
- {model_library-0.1.0.dist-info → model_library-0.1.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import io
|
|
2
|
+
from typing import Any, Literal, Sequence
|
|
3
|
+
|
|
4
|
+
from typing_extensions import override
|
|
5
|
+
|
|
6
|
+
from model_library.base import (
|
|
7
|
+
LLM,
|
|
8
|
+
FileInput,
|
|
9
|
+
FileWithId,
|
|
10
|
+
InputItem,
|
|
11
|
+
LLMConfig,
|
|
12
|
+
QueryResult,
|
|
13
|
+
ToolDefinition,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class DelegateOnlyException(Exception):
|
|
18
|
+
"""
|
|
19
|
+
Raised when native model functionality is performed on a
|
|
20
|
+
delegate-only model.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
DEFAULT_MESSAGE: str = "This model supports only delegate-only functionality. Only the query() method should be used."
|
|
24
|
+
|
|
25
|
+
def __init__(self, message: str | None = None):
|
|
26
|
+
super().__init__(message or DelegateOnlyException.DEFAULT_MESSAGE)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class DelegateOnly(LLM):
|
|
30
|
+
@override
|
|
31
|
+
def get_client(self) -> None:
|
|
32
|
+
raise DelegateOnlyException()
|
|
33
|
+
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
model_name: str,
|
|
37
|
+
provider: str,
|
|
38
|
+
*,
|
|
39
|
+
config: LLMConfig | None = None,
|
|
40
|
+
):
|
|
41
|
+
config = config or LLMConfig()
|
|
42
|
+
config.native = False
|
|
43
|
+
super().__init__(model_name, provider, config=config)
|
|
44
|
+
|
|
45
|
+
@override
|
|
46
|
+
async def _query_impl(
|
|
47
|
+
self,
|
|
48
|
+
input: Sequence[InputItem],
|
|
49
|
+
*,
|
|
50
|
+
tools: list[ToolDefinition],
|
|
51
|
+
**kwargs: object,
|
|
52
|
+
) -> QueryResult:
|
|
53
|
+
assert self.delegate
|
|
54
|
+
|
|
55
|
+
return await self.delegate_query(input, tools=tools, **kwargs)
|
|
56
|
+
|
|
57
|
+
@override
|
|
58
|
+
async def parse_input(
|
|
59
|
+
self,
|
|
60
|
+
input: Sequence[InputItem],
|
|
61
|
+
**kwargs: Any,
|
|
62
|
+
) -> Any:
|
|
63
|
+
raise DelegateOnlyException()
|
|
64
|
+
|
|
65
|
+
@override
|
|
66
|
+
async def parse_image(
|
|
67
|
+
self,
|
|
68
|
+
image: FileInput,
|
|
69
|
+
) -> Any:
|
|
70
|
+
raise DelegateOnlyException()
|
|
71
|
+
|
|
72
|
+
@override
|
|
73
|
+
async def parse_file(
|
|
74
|
+
self,
|
|
75
|
+
file: FileInput,
|
|
76
|
+
) -> Any:
|
|
77
|
+
raise DelegateOnlyException()
|
|
78
|
+
|
|
79
|
+
@override
|
|
80
|
+
async def parse_tools(
|
|
81
|
+
self,
|
|
82
|
+
tools: list[ToolDefinition],
|
|
83
|
+
) -> Any:
|
|
84
|
+
raise DelegateOnlyException()
|
|
85
|
+
|
|
86
|
+
@override
|
|
87
|
+
async def upload_file(
|
|
88
|
+
self,
|
|
89
|
+
name: str,
|
|
90
|
+
mime: str,
|
|
91
|
+
bytes: io.BytesIO,
|
|
92
|
+
type: Literal["image", "file"] = "file",
|
|
93
|
+
) -> FileWithId:
|
|
94
|
+
raise DelegateOnlyException()
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from pprint import pformat
|
|
2
|
+
from typing import Annotated, Any, Literal
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
from typing_extensions import override
|
|
6
|
+
|
|
7
|
+
from model_library.utils import truncate_str
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
--- FILES ---
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class FileBase(BaseModel):
|
|
15
|
+
type: Literal["image", "file"]
|
|
16
|
+
name: str
|
|
17
|
+
mime: str
|
|
18
|
+
|
|
19
|
+
@override
|
|
20
|
+
def __repr__(self):
|
|
21
|
+
attrs = vars(self).copy()
|
|
22
|
+
if "base64" in attrs:
|
|
23
|
+
attrs["base64"] = truncate_str(attrs["base64"])
|
|
24
|
+
return f"{self.__class__.__name__}(\n{pformat(attrs, indent=2)}\n)"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class FileWithBase64(FileBase):
|
|
28
|
+
append_type: Literal["base64"] = "base64"
|
|
29
|
+
base64: str
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class FileWithUrl(FileBase):
|
|
33
|
+
append_type: Literal["url"] = "url"
|
|
34
|
+
url: str
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class FileWithId(FileBase):
|
|
38
|
+
append_type: Literal["file_id"] = "file_id"
|
|
39
|
+
file_id: str
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
FileInput = Annotated[
|
|
43
|
+
FileWithBase64 | FileWithUrl | FileWithId,
|
|
44
|
+
Field(discriminator="append_type"),
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
"""
|
|
49
|
+
--- TOOLS ---
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class ToolBody(BaseModel):
|
|
54
|
+
name: str
|
|
55
|
+
description: str
|
|
56
|
+
properties: dict[str, Any]
|
|
57
|
+
required: list[str]
|
|
58
|
+
kwargs: dict[str, Any] = {}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class ToolDefinition(BaseModel):
|
|
62
|
+
name: str # acts as a key
|
|
63
|
+
body: ToolBody | Any
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class ToolCall(BaseModel):
|
|
67
|
+
id: str
|
|
68
|
+
call_id: str | None = None
|
|
69
|
+
name: str
|
|
70
|
+
args: dict[str, Any] | str
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
"""
|
|
74
|
+
--- INPUT ---
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
RawResponse = Any
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class ToolInput(BaseModel):
|
|
81
|
+
tools: list[ToolDefinition] = []
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class ToolResult(BaseModel):
|
|
85
|
+
tool_call: ToolCall
|
|
86
|
+
result: Any
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class TextInput(BaseModel):
|
|
90
|
+
text: str
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
RawInputItem = dict[
|
|
94
|
+
str, Any
|
|
95
|
+
] # to pass in, for example, a mock convertsation with {"role": "user", "content": "Hello"}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
InputItem = (
|
|
99
|
+
TextInput | FileInput | ToolResult | RawInputItem | RawResponse
|
|
100
|
+
) # input item can either be a prompt, a file (image or file), a tool call result, raw input, or a previous response
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""
|
|
2
|
+
--- OUTPUT ---
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from pprint import pformat
|
|
6
|
+
from typing import Any, Mapping, Sequence, cast
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, Field, computed_field, field_validator
|
|
9
|
+
from typing_extensions import override
|
|
10
|
+
|
|
11
|
+
from model_library.base.input import InputItem, ToolCall
|
|
12
|
+
from model_library.base.utils import (
|
|
13
|
+
sum_optional,
|
|
14
|
+
)
|
|
15
|
+
from model_library.utils import truncate_str
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Citation(BaseModel):
|
|
19
|
+
type: str | None = None
|
|
20
|
+
title: str | None = None
|
|
21
|
+
url: str | None = None
|
|
22
|
+
start_index: int | None = None
|
|
23
|
+
end_index: int | None = None
|
|
24
|
+
file_id: str | None = None
|
|
25
|
+
filename: str | None = None
|
|
26
|
+
index: int | None = None
|
|
27
|
+
container_id: str | None = None
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class QueryResultExtras(BaseModel):
|
|
31
|
+
citations: list[Citation] = Field(default_factory=list)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class QueryResultCost(BaseModel):
|
|
35
|
+
"""
|
|
36
|
+
Cost information for a query
|
|
37
|
+
Includes total cost and a structured breakdown.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
input: float
|
|
41
|
+
output: float
|
|
42
|
+
reasoning: float | None = None
|
|
43
|
+
cache_read: float | None = None
|
|
44
|
+
cache_write: float | None = None
|
|
45
|
+
|
|
46
|
+
@computed_field
|
|
47
|
+
@property
|
|
48
|
+
def total(self) -> float:
|
|
49
|
+
return sum(
|
|
50
|
+
filter(
|
|
51
|
+
None,
|
|
52
|
+
[
|
|
53
|
+
self.input,
|
|
54
|
+
self.output,
|
|
55
|
+
self.reasoning,
|
|
56
|
+
self.cache_read,
|
|
57
|
+
self.cache_write,
|
|
58
|
+
],
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
@override
|
|
63
|
+
def __repr__(self):
|
|
64
|
+
use_cents = self.total < 1
|
|
65
|
+
|
|
66
|
+
def format_cost(value: float | None):
|
|
67
|
+
if value is None:
|
|
68
|
+
return None
|
|
69
|
+
return f"{value * 100:.3f} cents" if use_cents else f"${value:.2f}"
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
f"{format_cost(self.total)} "
|
|
73
|
+
+ f"(uncached input: {format_cost(self.input)} | output: {format_cost(self.output)} | reasoning: {format_cost(self.reasoning)} | cache_read: {format_cost(self.cache_read)} | cache_write: {format_cost(self.cache_write)})"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class QueryResultMetadata(BaseModel):
|
|
78
|
+
"""
|
|
79
|
+
Metadata for a query: token usage and timing.
|
|
80
|
+
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
cost: QueryResultCost | None = None # set post query
|
|
84
|
+
duration_seconds: float | None = None # set post query
|
|
85
|
+
in_tokens: int = 0
|
|
86
|
+
out_tokens: int = 0
|
|
87
|
+
reasoning_tokens: int | None = None
|
|
88
|
+
cache_read_tokens: int | None = None
|
|
89
|
+
cache_write_tokens: int | None = None
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def default_duration_seconds(self) -> float:
|
|
93
|
+
return self.duration_seconds or 0
|
|
94
|
+
|
|
95
|
+
def __add__(self, other: "QueryResultMetadata") -> "QueryResultMetadata":
|
|
96
|
+
return QueryResultMetadata(
|
|
97
|
+
in_tokens=self.in_tokens + other.in_tokens,
|
|
98
|
+
out_tokens=self.out_tokens + other.out_tokens,
|
|
99
|
+
reasoning_tokens=sum_optional(
|
|
100
|
+
self.reasoning_tokens, other.reasoning_tokens
|
|
101
|
+
),
|
|
102
|
+
cache_read_tokens=sum_optional(
|
|
103
|
+
self.cache_read_tokens, other.cache_read_tokens
|
|
104
|
+
),
|
|
105
|
+
cache_write_tokens=sum_optional(
|
|
106
|
+
self.cache_write_tokens, other.cache_write_tokens
|
|
107
|
+
),
|
|
108
|
+
duration_seconds=self.default_duration_seconds
|
|
109
|
+
+ other.default_duration_seconds,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
@override
|
|
113
|
+
def __repr__(self):
|
|
114
|
+
attrs = vars(self).copy()
|
|
115
|
+
return f"{self.__class__.__name__}(\n{pformat(attrs, indent=2, sort_dicts=False)}\n)"
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class QueryResult(BaseModel):
|
|
119
|
+
"""
|
|
120
|
+
Result of a query
|
|
121
|
+
Contains the text, reasoning, metadata, tool calls, and history
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
output_text: str | None = None
|
|
125
|
+
reasoning: str | None = None
|
|
126
|
+
metadata: QueryResultMetadata = Field(default_factory=QueryResultMetadata)
|
|
127
|
+
tool_calls: list[ToolCall] = Field(default_factory=list)
|
|
128
|
+
history: list[InputItem] = Field(default_factory=list)
|
|
129
|
+
extras: QueryResultExtras = Field(default_factory=QueryResultExtras)
|
|
130
|
+
raw: dict[str, Any] = Field(default_factory=dict)
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def output_text_str(self) -> str:
|
|
134
|
+
return self.output_text or ""
|
|
135
|
+
|
|
136
|
+
@field_validator("reasoning", mode="before")
|
|
137
|
+
def default_reasoning(cls, v: str | None):
|
|
138
|
+
return None if not v else v # make reasoning None if empty
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def search_results(self) -> Any | None:
|
|
142
|
+
"""Expose provider-supplied search metadata without additional processing."""
|
|
143
|
+
raw_dict = cast(dict[str, Any], getattr(self, "raw", {}))
|
|
144
|
+
raw_candidate = raw_dict.get("search_results")
|
|
145
|
+
if raw_candidate is not None:
|
|
146
|
+
return raw_candidate
|
|
147
|
+
|
|
148
|
+
return _get_from_history(self.history, "search_results")
|
|
149
|
+
|
|
150
|
+
@override
|
|
151
|
+
def __repr__(self):
|
|
152
|
+
attrs = vars(self).copy()
|
|
153
|
+
ordered_attrs = {
|
|
154
|
+
"output_text": truncate_str(attrs.pop("output_text", None), 400),
|
|
155
|
+
"reasoning": truncate_str(attrs.pop("reasoning", None), 400),
|
|
156
|
+
"metadata": attrs.pop("metadata", None),
|
|
157
|
+
}
|
|
158
|
+
if self.tool_calls:
|
|
159
|
+
ordered_attrs["tool_calls"] = self.tool_calls
|
|
160
|
+
return f"{self.__class__.__name__}(\n{pformat(ordered_attrs, indent=2, sort_dicts=False)}\n)"
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _get_from_history(history: Sequence[InputItem], key: str) -> Any | None:
|
|
164
|
+
for item in reversed(history):
|
|
165
|
+
value = getattr(item, key, None)
|
|
166
|
+
if value is not None:
|
|
167
|
+
return value
|
|
168
|
+
|
|
169
|
+
extra = getattr(item, "model_extra", None)
|
|
170
|
+
if isinstance(extra, Mapping):
|
|
171
|
+
value = cast(Mapping[str, Any], extra).get(key)
|
|
172
|
+
if value is not None:
|
|
173
|
+
return value
|
|
174
|
+
|
|
175
|
+
return None
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from typing import Sequence, cast
|
|
2
|
+
|
|
3
|
+
from model_library.base.input import (
|
|
4
|
+
FileBase,
|
|
5
|
+
InputItem,
|
|
6
|
+
RawInputItem,
|
|
7
|
+
TextInput,
|
|
8
|
+
ToolResult,
|
|
9
|
+
)
|
|
10
|
+
from model_library.utils import truncate_str
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def sum_optional(a: int | None, b: int | None) -> int | None:
|
|
14
|
+
"""Sum two optional integers, returning None if both are None.
|
|
15
|
+
|
|
16
|
+
Preserves None to indicate "unknown/not provided" when both inputs are None,
|
|
17
|
+
otherwise treats None as 0 for summation.
|
|
18
|
+
"""
|
|
19
|
+
if a is None and b is None:
|
|
20
|
+
return None
|
|
21
|
+
return (a or 0) + (b or 0)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_pretty_input_types(input: Sequence["InputItem"]) -> str:
|
|
25
|
+
# for logging
|
|
26
|
+
def process_item(item: "InputItem"):
|
|
27
|
+
match item:
|
|
28
|
+
case TextInput():
|
|
29
|
+
return truncate_str(repr(item))
|
|
30
|
+
case FileBase(): # FileInput
|
|
31
|
+
return repr(item)
|
|
32
|
+
case ToolResult():
|
|
33
|
+
return repr(item)
|
|
34
|
+
case dict():
|
|
35
|
+
item = cast(RawInputItem, item)
|
|
36
|
+
return repr(item)
|
|
37
|
+
case _:
|
|
38
|
+
# RawResponse
|
|
39
|
+
return repr(item)
|
|
40
|
+
|
|
41
|
+
processed_items = [f" {process_item(item)}" for item in input]
|
|
42
|
+
return "\n" + "\n".join(processed_items) if processed_items else ""
|
|
@@ -1,4 +1,148 @@
|
|
|
1
1
|
{
|
|
2
|
+
"openai/gpt-5.1-codex-mini": {
|
|
3
|
+
"company": "OpenAI",
|
|
4
|
+
"label": "GPT 5.1 Codex Mini",
|
|
5
|
+
"description": "OpenAI's miniature coding model",
|
|
6
|
+
"release_date": "2025-11-13",
|
|
7
|
+
"open_source": false,
|
|
8
|
+
"documentation_url": "https://platform.openai.com/docs/models/gpt-5.1-codex-mini",
|
|
9
|
+
"properties": {
|
|
10
|
+
"context_window": 400000,
|
|
11
|
+
"max_token_output": 128000,
|
|
12
|
+
"training_cutoff": null,
|
|
13
|
+
"reasoning_model": true
|
|
14
|
+
},
|
|
15
|
+
"class_properties": {
|
|
16
|
+
"supports_images": true,
|
|
17
|
+
"supports_files": true,
|
|
18
|
+
"supports_batch_requests": true,
|
|
19
|
+
"supports_temperature": false,
|
|
20
|
+
"supports_tools": true,
|
|
21
|
+
"deprecated": false,
|
|
22
|
+
"available_for_everyone": false,
|
|
23
|
+
"available_as_evaluator": false,
|
|
24
|
+
"ignored_for_cost": false
|
|
25
|
+
},
|
|
26
|
+
"provider_properties": {},
|
|
27
|
+
"costs_per_million_token": {
|
|
28
|
+
"input": 0.25,
|
|
29
|
+
"output": 2.0,
|
|
30
|
+
"cache": {
|
|
31
|
+
"read": 0.025,
|
|
32
|
+
"write_markup": 1.0
|
|
33
|
+
},
|
|
34
|
+
"batch": {
|
|
35
|
+
"input_discount": 0.5,
|
|
36
|
+
"output_discount": 0.5
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"alternative_keys": [],
|
|
40
|
+
"default_parameters": {
|
|
41
|
+
"max_output_tokens": 128000,
|
|
42
|
+
"temperature": 1.0,
|
|
43
|
+
"reasoning_effort": "high"
|
|
44
|
+
},
|
|
45
|
+
"provider_name": "openai",
|
|
46
|
+
"provider_endpoint": "gpt-5.1-codex-mini",
|
|
47
|
+
"full_key": "openai/gpt-5.1-codex-mini",
|
|
48
|
+
"slug": "openai_gpt-5.1-codex-mini"
|
|
49
|
+
},
|
|
50
|
+
"openai/gpt-5.1-codex": {
|
|
51
|
+
"company": "OpenAI",
|
|
52
|
+
"label": "GPT 5.1 Codex",
|
|
53
|
+
"description": "OpenAI's latest coding model",
|
|
54
|
+
"release_date": "2025-11-13",
|
|
55
|
+
"open_source": false,
|
|
56
|
+
"documentation_url": "https://platform.openai.com/docs/models/gpt-5.1-codex",
|
|
57
|
+
"properties": {
|
|
58
|
+
"context_window": 400000,
|
|
59
|
+
"max_token_output": 128000,
|
|
60
|
+
"training_cutoff": null,
|
|
61
|
+
"reasoning_model": true
|
|
62
|
+
},
|
|
63
|
+
"class_properties": {
|
|
64
|
+
"supports_images": true,
|
|
65
|
+
"supports_files": true,
|
|
66
|
+
"supports_batch_requests": true,
|
|
67
|
+
"supports_temperature": false,
|
|
68
|
+
"supports_tools": true,
|
|
69
|
+
"deprecated": false,
|
|
70
|
+
"available_for_everyone": false,
|
|
71
|
+
"available_as_evaluator": false,
|
|
72
|
+
"ignored_for_cost": false
|
|
73
|
+
},
|
|
74
|
+
"provider_properties": {},
|
|
75
|
+
"costs_per_million_token": {
|
|
76
|
+
"input": 1.25,
|
|
77
|
+
"output": 10.0,
|
|
78
|
+
"cache": {
|
|
79
|
+
"read": 0.125,
|
|
80
|
+
"write_markup": 1.0
|
|
81
|
+
},
|
|
82
|
+
"batch": {
|
|
83
|
+
"input_discount": 0.5,
|
|
84
|
+
"output_discount": 0.5
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"alternative_keys": [],
|
|
88
|
+
"default_parameters": {
|
|
89
|
+
"max_output_tokens": 128000,
|
|
90
|
+
"temperature": 1.0,
|
|
91
|
+
"reasoning_effort": "high"
|
|
92
|
+
},
|
|
93
|
+
"provider_name": "openai",
|
|
94
|
+
"provider_endpoint": "gpt-5.1-codex",
|
|
95
|
+
"full_key": "openai/gpt-5.1-codex",
|
|
96
|
+
"slug": "openai_gpt-5.1-codex"
|
|
97
|
+
},
|
|
98
|
+
"openai/gpt-5.1-2025-11-13": {
|
|
99
|
+
"company": "OpenAI",
|
|
100
|
+
"label": "GPT 5.1",
|
|
101
|
+
"description": "GPT-5.1 is OpenAI's flagship model for coding and agentic tasks with configurable reasoning and non-reasoning effort.",
|
|
102
|
+
"release_date": "2025-11-13",
|
|
103
|
+
"open_source": false,
|
|
104
|
+
"documentation_url": "https://platform.openai.com/docs/models/gpt-5.1",
|
|
105
|
+
"properties": {
|
|
106
|
+
"context_window": 400000,
|
|
107
|
+
"max_token_output": 128000,
|
|
108
|
+
"training_cutoff": "2024-09",
|
|
109
|
+
"reasoning_model": true
|
|
110
|
+
},
|
|
111
|
+
"class_properties": {
|
|
112
|
+
"supports_images": true,
|
|
113
|
+
"supports_files": true,
|
|
114
|
+
"supports_batch_requests": true,
|
|
115
|
+
"supports_temperature": false,
|
|
116
|
+
"supports_tools": true,
|
|
117
|
+
"deprecated": false,
|
|
118
|
+
"available_for_everyone": false,
|
|
119
|
+
"available_as_evaluator": true,
|
|
120
|
+
"ignored_for_cost": false
|
|
121
|
+
},
|
|
122
|
+
"provider_properties": {},
|
|
123
|
+
"costs_per_million_token": {
|
|
124
|
+
"input": 1.25,
|
|
125
|
+
"output": 10.0,
|
|
126
|
+
"cache": {
|
|
127
|
+
"read": 0.125,
|
|
128
|
+
"write_markup": 1.0
|
|
129
|
+
},
|
|
130
|
+
"batch": {
|
|
131
|
+
"input_discount": 0.5,
|
|
132
|
+
"output_discount": 0.5
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
"alternative_keys": [],
|
|
136
|
+
"default_parameters": {
|
|
137
|
+
"max_output_tokens": 128000,
|
|
138
|
+
"temperature": 1.0,
|
|
139
|
+
"reasoning_effort": "high"
|
|
140
|
+
},
|
|
141
|
+
"provider_name": "openai",
|
|
142
|
+
"provider_endpoint": "gpt-5.1-2025-11-13",
|
|
143
|
+
"full_key": "openai/gpt-5.1-2025-11-13",
|
|
144
|
+
"slug": "openai_gpt-5.1-2025-11-13"
|
|
145
|
+
},
|
|
2
146
|
"kimi/kimi-k2-thinking": {
|
|
3
147
|
"company": "Kimi",
|
|
4
148
|
"label": "Kimi K2 Thinking",
|
|
@@ -187,6 +331,7 @@
|
|
|
187
331
|
"class_properties": {
|
|
188
332
|
"supports_images": true,
|
|
189
333
|
"supports_files": true,
|
|
334
|
+
"supports_batch_requests": true,
|
|
190
335
|
"supports_temperature": true,
|
|
191
336
|
"supports_tools": true,
|
|
192
337
|
"deprecated": false,
|
|
@@ -234,6 +379,7 @@
|
|
|
234
379
|
"class_properties": {
|
|
235
380
|
"supports_images": true,
|
|
236
381
|
"supports_files": true,
|
|
382
|
+
"supports_batch_requests": true,
|
|
237
383
|
"supports_temperature": true,
|
|
238
384
|
"supports_tools": true,
|
|
239
385
|
"deprecated": false,
|
|
@@ -386,7 +532,11 @@
|
|
|
386
532
|
"provider_properties": {},
|
|
387
533
|
"costs_per_million_token": {
|
|
388
534
|
"input": 0.28,
|
|
389
|
-
"output": 0.42
|
|
535
|
+
"output": 0.42,
|
|
536
|
+
"cache": {
|
|
537
|
+
"read_discount": 0.1,
|
|
538
|
+
"write_markup": 1.0
|
|
539
|
+
}
|
|
390
540
|
},
|
|
391
541
|
"alternative_keys": [],
|
|
392
542
|
"default_parameters": {
|
|
@@ -424,7 +574,11 @@
|
|
|
424
574
|
"provider_properties": {},
|
|
425
575
|
"costs_per_million_token": {
|
|
426
576
|
"input": 0.28,
|
|
427
|
-
"output": 0.42
|
|
577
|
+
"output": 0.42,
|
|
578
|
+
"cache": {
|
|
579
|
+
"read_discount": 0.1,
|
|
580
|
+
"write_markup": 1.0
|
|
581
|
+
}
|
|
428
582
|
},
|
|
429
583
|
"alternative_keys": [],
|
|
430
584
|
"default_parameters": {
|
|
@@ -451,6 +605,7 @@
|
|
|
451
605
|
"class_properties": {
|
|
452
606
|
"supports_images": true,
|
|
453
607
|
"supports_files": true,
|
|
608
|
+
"supports_batch_requests": true,
|
|
454
609
|
"supports_temperature": true,
|
|
455
610
|
"supports_tools": true,
|
|
456
611
|
"deprecated": false,
|
|
@@ -508,6 +663,7 @@
|
|
|
508
663
|
"class_properties": {
|
|
509
664
|
"supports_images": true,
|
|
510
665
|
"supports_files": true,
|
|
666
|
+
"supports_batch_requests": true,
|
|
511
667
|
"supports_temperature": true,
|
|
512
668
|
"supports_tools": true,
|
|
513
669
|
"deprecated": false,
|
|
@@ -1979,6 +2135,7 @@
|
|
|
1979
2135
|
"class_properties": {
|
|
1980
2136
|
"supports_images": true,
|
|
1981
2137
|
"supports_files": true,
|
|
2138
|
+
"supports_batch_requests": true,
|
|
1982
2139
|
"supports_temperature": true,
|
|
1983
2140
|
"supports_tools": true,
|
|
1984
2141
|
"deprecated": false,
|
|
@@ -2026,6 +2183,7 @@
|
|
|
2026
2183
|
"class_properties": {
|
|
2027
2184
|
"supports_images": true,
|
|
2028
2185
|
"supports_files": true,
|
|
2186
|
+
"supports_batch_requests": true,
|
|
2029
2187
|
"supports_temperature": true,
|
|
2030
2188
|
"supports_tools": true,
|
|
2031
2189
|
"deprecated": false,
|
|
@@ -3350,6 +3508,7 @@
|
|
|
3350
3508
|
"class_properties": {
|
|
3351
3509
|
"supports_images": true,
|
|
3352
3510
|
"supports_files": true,
|
|
3511
|
+
"supports_batch_requests": true,
|
|
3353
3512
|
"supports_temperature": false,
|
|
3354
3513
|
"supports_tools": true,
|
|
3355
3514
|
"deprecated": false,
|
|
@@ -3407,6 +3566,7 @@
|
|
|
3407
3566
|
"class_properties": {
|
|
3408
3567
|
"supports_images": true,
|
|
3409
3568
|
"supports_files": true,
|
|
3569
|
+
"supports_batch_requests": true,
|
|
3410
3570
|
"supports_temperature": true,
|
|
3411
3571
|
"supports_tools": true,
|
|
3412
3572
|
"deprecated": false,
|
|
@@ -3475,6 +3635,7 @@
|
|
|
3475
3635
|
"class_properties": {
|
|
3476
3636
|
"supports_images": true,
|
|
3477
3637
|
"supports_files": true,
|
|
3638
|
+
"supports_batch_requests": true,
|
|
3478
3639
|
"supports_temperature": true,
|
|
3479
3640
|
"supports_tools": true,
|
|
3480
3641
|
"deprecated": false,
|
|
@@ -3522,6 +3683,7 @@
|
|
|
3522
3683
|
"class_properties": {
|
|
3523
3684
|
"supports_images": true,
|
|
3524
3685
|
"supports_files": true,
|
|
3686
|
+
"supports_batch_requests": true,
|
|
3525
3687
|
"supports_temperature": true,
|
|
3526
3688
|
"supports_tools": true,
|
|
3527
3689
|
"deprecated": false,
|
|
@@ -23,6 +23,10 @@ base-config:
|
|
|
23
23
|
temperature: 1
|
|
24
24
|
|
|
25
25
|
claude-4-models:
|
|
26
|
+
base-config:
|
|
27
|
+
class_properties:
|
|
28
|
+
supports_batch_requests: true
|
|
29
|
+
|
|
26
30
|
anthropic/claude-opus-4-1-20250805:
|
|
27
31
|
label: Claude Opus 4.1 (Nonthinking)
|
|
28
32
|
description: Advanced model for specialized complex
|
|
@@ -10,7 +10,7 @@ base-config:
|
|
|
10
10
|
ignored_for_cost: false
|
|
11
11
|
properties:
|
|
12
12
|
reasoning_model: false
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
deepseek-v3p2-exp-models:
|
|
15
15
|
base-config:
|
|
16
16
|
class_properties:
|
|
@@ -23,6 +23,8 @@ deepseek-v3p2-exp-models:
|
|
|
23
23
|
costs_per_million_token:
|
|
24
24
|
input: 0.28
|
|
25
25
|
output: 0.42
|
|
26
|
+
cache:
|
|
27
|
+
read_discount: 0.1
|
|
26
28
|
|
|
27
29
|
deepseek/deepseek-chat:
|
|
28
30
|
label: DeepSeek V3.2-Exp (Nonthinking)
|