python-fastllm 0.0.12__tar.gz → 0.0.15__tar.gz
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.
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/PKG-INFO +2 -1
- python_fastllm-0.0.15/fastllm/__init__.py +1 -0
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/fastllm/_modidx.py +4 -1
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/fastllm/anthropic.py +11 -5
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/fastllm/chat.py +3 -3
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/fastllm/gemini.py +1 -0
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/fastllm/openai_chat.py +1 -0
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/fastllm/openai_responses.py +6 -2
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/fastllm/streaming.py +1 -5
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/fastllm/types.py +26 -10
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/pyproject.toml +1 -1
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/python_fastllm.egg-info/PKG-INFO +2 -1
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/python_fastllm.egg-info/requires.txt +1 -0
- python_fastllm-0.0.12/fastllm/__init__.py +0 -1
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/README.md +0 -0
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/fastllm/acomplete.py +0 -0
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/fastllm/codex.py +0 -0
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/fastllm/specs/anthropic.json +0 -0
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/fastllm/specs/anthropic.yml +0 -0
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/fastllm/specs/gemini.json +0 -0
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/fastllm/specs/openai.with-code-samples.json +0 -0
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/fastllm/specs/openai.with-code-samples.yml +0 -0
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/fastllm/specs/spec_manifest.json +0 -0
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/python_fastllm.egg-info/SOURCES.txt +0 -0
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/python_fastllm.egg-info/dependency_links.txt +0 -0
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/python_fastllm.egg-info/entry_points.txt +0 -0
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/python_fastllm.egg-info/top_level.txt +0 -0
- {python_fastllm-0.0.12 → python_fastllm-0.0.15}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-fastllm
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.15
|
|
4
4
|
Author-email: Kerem Turgutlu <keremturgutlu@gmail.com>
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Project-URL: Repository, https://github.com/AnswerDotAI/fastllm
|
|
@@ -11,6 +11,7 @@ Requires-Python: >=3.10
|
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
Requires-Dist: fastspec
|
|
13
13
|
Requires-Dist: toolslm
|
|
14
|
+
Requires-Dist: pillow
|
|
14
15
|
|
|
15
16
|
# fastllm
|
|
16
17
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.0.15"
|
|
@@ -19,6 +19,7 @@ d = { 'settings': { 'branch': 'main',
|
|
|
19
19
|
'fastllm.acomplete.mk_client': ('acomplete.html#mk_client', 'fastllm/acomplete.py')},
|
|
20
20
|
'fastllm.anthropic': { 'fastllm.anthropic._ant_cc': ('anthropic.html#_ant_cc', 'fastllm/anthropic.py'),
|
|
21
21
|
'fastllm.anthropic._ant_part_type': ('anthropic.html#_ant_part_type', 'fastllm/anthropic.py'),
|
|
22
|
+
'fastllm.anthropic._sanid': ('anthropic.html#_sanid', 'fastllm/anthropic.py'),
|
|
22
23
|
'fastllm.anthropic.acollect_stream': ('anthropic.html#acollect_stream', 'fastllm/anthropic.py'),
|
|
23
24
|
'fastllm.anthropic.cost': ('anthropic.html#cost', 'fastllm/anthropic.py'),
|
|
24
25
|
'fastllm.anthropic.delta_index_fn': ('anthropic.html#delta_index_fn', 'fastllm/anthropic.py'),
|
|
@@ -204,7 +205,8 @@ d = { 'settings': { 'branch': 'main',
|
|
|
204
205
|
'fastllm.openai_chat.norm_parts': ('oai_chat.html#norm_parts', 'fastllm/openai_chat.py'),
|
|
205
206
|
'fastllm.openai_chat.norm_sse_event': ('oai_chat.html#norm_sse_event', 'fastllm/openai_chat.py'),
|
|
206
207
|
'fastllm.openai_chat.norm_tool_calls': ('oai_chat.html#norm_tool_calls', 'fastllm/openai_chat.py')},
|
|
207
|
-
'fastllm.openai_responses': { 'fastllm.openai_responses.
|
|
208
|
+
'fastllm.openai_responses': { 'fastllm.openai_responses._sanid': ('oai_responses.html#_sanid', 'fastllm/openai_responses.py'),
|
|
209
|
+
'fastllm.openai_responses.acollect_stream': ( 'oai_responses.html#acollect_stream',
|
|
208
210
|
'fastllm/openai_responses.py'),
|
|
209
211
|
'fastllm.openai_responses.cost': ('oai_responses.html#cost', 'fastllm/openai_responses.py'),
|
|
210
212
|
'fastllm.openai_responses.delta_index_fn': ( 'oai_responses.html#delta_index_fn',
|
|
@@ -291,5 +293,6 @@ d = { 'settings': { 'branch': 'main',
|
|
|
291
293
|
'fastllm.types.part_txt': ('types.html#part_txt', 'fastllm/types.py'),
|
|
292
294
|
'fastllm.types.payload_kwargs': ('types.html#payload_kwargs', 'fastllm/types.py'),
|
|
293
295
|
'fastllm.types.register_model_info': ('types.html#register_model_info', 'fastllm/types.py'),
|
|
296
|
+
'fastllm.types.resize_b64': ('types.html#resize_b64', 'fastllm/types.py'),
|
|
294
297
|
'fastllm.types.sys_text': ('types.html#sys_text', 'fastllm/types.py'),
|
|
295
298
|
'fastllm.types.url_mime': ('types.html#url_mime', 'fastllm/types.py')}}}
|
|
@@ -85,6 +85,7 @@ def norm_parts(resp):
|
|
|
85
85
|
|
|
86
86
|
# %% ../nbs/04_anthropic.ipynb #a3869e31
|
|
87
87
|
def norm_sse_event(ev, **kwargs):
|
|
88
|
+
ev = obj2dict(ev)
|
|
88
89
|
typ = ev.get("type")
|
|
89
90
|
text, thinking, tcs, citations = None, None, [], None
|
|
90
91
|
if typ == "content_block_start":
|
|
@@ -125,11 +126,14 @@ def _ant_cc(block, p):
|
|
|
125
126
|
if (cc := (p.data or {}).get('cache_control')): block['cache_control'] = cc
|
|
126
127
|
return block
|
|
127
128
|
|
|
129
|
+
# %% ../nbs/04_anthropic.ipynb #62e9a042
|
|
130
|
+
def _sanid(id_str): return re.sub(r'[^a-zA-Z0-9_-]', '_', id_str or '')
|
|
131
|
+
|
|
128
132
|
# %% ../nbs/04_anthropic.ipynb #6ec772cb
|
|
129
133
|
def denorm_tool_use(p:Part):
|
|
130
134
|
"Convert canonical tool_use Part to Anthropic tool_use content block."
|
|
131
135
|
d = p.data or {}
|
|
132
|
-
block = dict(type='tool_use', id=d.get('id',''), name=d.get('name',''), input=d.get('arguments') or {})
|
|
136
|
+
block = dict(type='tool_use', id=_sanid(d.get('id','')), name=d.get('name',''), input=d.get('arguments') or {})
|
|
133
137
|
if 'caller' in d: block['caller'] = d['caller']
|
|
134
138
|
return _ant_cc(block, p)
|
|
135
139
|
|
|
@@ -238,8 +242,10 @@ def denorm_user(m:Msg):
|
|
|
238
242
|
return dict(role='user', content=parts)
|
|
239
243
|
|
|
240
244
|
# %% ../nbs/04_anthropic.ipynb #edd87272
|
|
241
|
-
def denorm_image(p):
|
|
242
|
-
if (b64:=data_url(p.text)):
|
|
245
|
+
def denorm_image(p, max_sz=None):
|
|
246
|
+
if (b64:=data_url(p.text)):
|
|
247
|
+
data = resize_b64(b64[1], max_sz) if max_sz else b64[1]
|
|
248
|
+
return {"type": "image", "source": {"type": "base64", "media_type": b64[0], "data": data}}
|
|
243
249
|
return {"type": "image", "source": {"type": "url", "url": p.text}}
|
|
244
250
|
|
|
245
251
|
# %% ../nbs/04_anthropic.ipynb #fc6bbdfc
|
|
@@ -251,12 +257,12 @@ def denorm_file(p):
|
|
|
251
257
|
def denorm_tool_result(p:Part):
|
|
252
258
|
"Convert canonical tool_result Part to Anthropic tool_result content block."
|
|
253
259
|
d = p.data or {}
|
|
254
|
-
tid = d.get('id') or d.get('call_id','')
|
|
260
|
+
tid = _sanid(d.get('id') or d.get('call_id',''))
|
|
255
261
|
if isinstance(p.text, list):
|
|
256
262
|
blocks = []
|
|
257
263
|
for pp in p.text:
|
|
258
264
|
if pp.type == PartType.text: blocks.append({"type": "text", "text": pp.text or ""})
|
|
259
|
-
elif pp.type == PartType.input_image: blocks.append(denorm_image(pp))
|
|
265
|
+
elif pp.type == PartType.input_image: blocks.append(denorm_image(pp, max_sz=2000))
|
|
260
266
|
elif pp.type == PartType.input_file: blocks.append(denorm_file(pp))
|
|
261
267
|
else: raise ValueError(f"Anthropic tool_result does not support {pp.type}")
|
|
262
268
|
return _ant_cc(dict(type='tool_result', tool_use_id=tid, content=blocks), p)
|
|
@@ -183,7 +183,7 @@ def fmt2hist(outp:str)->list[Msg]:
|
|
|
183
183
|
"Transform a formatted output string into fastllm canonical Msgs"
|
|
184
184
|
if token_dtls_tag in outp: outp = re_token.sub('', outp)
|
|
185
185
|
if tool_dtls_tag not in outp:
|
|
186
|
-
msg = Msg(role='assistant', content=[Part(type=PartType.text, text=outp.strip())])
|
|
186
|
+
msg = Msg(role='assistant', content=[Part(type=PartType.text, text=outp.strip() or '.')])
|
|
187
187
|
return _split_msg_on_fences(msg)
|
|
188
188
|
hist, asst_parts, tool_parts = [], [], []
|
|
189
189
|
def flush():
|
|
@@ -194,7 +194,7 @@ def fmt2hist(outp:str)->list[Msg]:
|
|
|
194
194
|
for txt,_,tj in split_tools(outp):
|
|
195
195
|
if txt and txt.strip():
|
|
196
196
|
if tool_parts: flush()
|
|
197
|
-
asst_parts.append(Part(type=PartType.text, text=txt.strip()))
|
|
197
|
+
asst_parts.append(Part(type=PartType.text, text=txt.strip() or '.'))
|
|
198
198
|
if tj and (tp := _extract_tool_parts(tj)):
|
|
199
199
|
asst_parts.append(tp[0])
|
|
200
200
|
tool_parts.append(tp[1])
|
|
@@ -316,7 +316,7 @@ def _has_stop(tres_parts): return any(isinstance(p.text, StopResponse) for p in
|
|
|
316
316
|
def _trunc_str(s, mx=2000, skip=10, replace="TRUNCATED"):
|
|
317
317
|
"Truncate `s` to `mx` chars max, adding `replace` if truncated"
|
|
318
318
|
if not isinstance(s, str): s = str(s)
|
|
319
|
-
s = s.rstrip()
|
|
319
|
+
s = type(s)(s.rstrip())
|
|
320
320
|
if len(s)>2 and s[0]=='𝍁' and s[-1]=='𝍁':
|
|
321
321
|
s = s[1:-1]
|
|
322
322
|
if replace: return s
|
|
@@ -86,6 +86,7 @@ def norm_parts(resp):
|
|
|
86
86
|
# %% ../nbs/05_gemini.ipynb #9a5024ee
|
|
87
87
|
def norm_sse_event(ev, **kwargs):
|
|
88
88
|
"Normalize Gemini stream event into Delta."
|
|
89
|
+
ev = obj2dict(ev)
|
|
89
90
|
cand = nested_idx(ev, 'candidates', 0) or {}
|
|
90
91
|
finish_reason = norm_finish(ev)
|
|
91
92
|
parts = nested_idx(cand, 'content', 'parts') or []
|
|
@@ -55,6 +55,7 @@ def norm_parts(resp):
|
|
|
55
55
|
def norm_sse_event(ev, **kwargs):
|
|
56
56
|
"Normalize a chat completion stream event."
|
|
57
57
|
# usage always arrives as a single final event with choices: []
|
|
58
|
+
ev = obj2dict(ev)
|
|
58
59
|
fin = nested_idx(ev, 'choices', 0, 'finish_reason')
|
|
59
60
|
tcs = norm_tool_calls(ev, delta=True)
|
|
60
61
|
if (dlt:=nested_idx(ev, 'choices', 0, 'delta')) is not None:
|
|
@@ -82,6 +82,7 @@ def norm_parts(resp):
|
|
|
82
82
|
# %% ../nbs/02_oai_responses.ipynb #7cd48aa5
|
|
83
83
|
def norm_sse_event(ev, **kwargs):
|
|
84
84
|
"Normalize OpenAI Responses API stream event into Delta."
|
|
85
|
+
ev = obj2dict(ev)
|
|
85
86
|
typ = ev.get("type")
|
|
86
87
|
if typ == "response.output_text.delta": return Delta(text=ev.get("delta"), raw=ev, **kwargs)
|
|
87
88
|
if typ == "response.reasoning_text.delta": return Delta(thinking=ev.get("delta",""), raw=ev, **kwargs)
|
|
@@ -109,10 +110,13 @@ async def acollect_stream(resp, **kwargs):
|
|
|
109
110
|
res = mk_acollect_stream(norm_and_yield(resp, norm_sse_event), index_fn=delta_index_fn, api_name='openai', **kwargs)
|
|
110
111
|
async for o in res: yield o
|
|
111
112
|
|
|
113
|
+
# %% ../nbs/02_oai_responses.ipynb #9608e813
|
|
114
|
+
def _sanid(id_str): return id_str[:64] # codex max 64 char limit
|
|
115
|
+
|
|
112
116
|
# %% ../nbs/02_oai_responses.ipynb #b746c82b
|
|
113
117
|
def denorm_tool_use(p:Part):
|
|
114
118
|
"Convert canonical tool_use Part back to OpenAI Responses function_call item."
|
|
115
|
-
return dict(type='function_call', call_id=p.data.get('id'), name=p.data.get('name'), arguments=json.dumps(p.data.get('arguments', '{}')))
|
|
119
|
+
return dict(type='function_call', call_id=_sanid(p.data.get('id')), name=p.data.get('name'), arguments=json.dumps(p.data.get('arguments', '{}')))
|
|
116
120
|
|
|
117
121
|
# %% ../nbs/02_oai_responses.ipynb #8f42adf7
|
|
118
122
|
def denorm_tool(m:Msg):
|
|
@@ -208,7 +212,7 @@ def denorm_file(p):
|
|
|
208
212
|
# %% ../nbs/02_oai_responses.ipynb #145b1c79
|
|
209
213
|
def denorm_tool_result(m:Part):
|
|
210
214
|
"Convert canonical tool result back to OpenAI Responses function_call_output item."
|
|
211
|
-
cid = m.data.get('id', '') or m.data.get('call_id')
|
|
215
|
+
cid = _sanid(m.data.get('id', '') or m.data.get('call_id'))
|
|
212
216
|
if isinstance(m.text, list):
|
|
213
217
|
out = []
|
|
214
218
|
for p in m.text:
|
|
@@ -137,14 +137,10 @@ async def mk_acollect_stream(it, index_fn, model=None, api_name=None, vendor_nam
|
|
|
137
137
|
data = {**acc.extra, 'id':acc.id, 'name':acc.name, 'arguments':args, 'server':acc.server}
|
|
138
138
|
yield Part(type=PartType.tool_use, data=data)
|
|
139
139
|
# Server tool results for anthropic are yielded in d.server_tool_result by checking injected dummy `_delta`
|
|
140
|
-
if acc.server
|
|
140
|
+
if acc.server: yield Part(type=PartType.tool_result, text="Server tool call executed.", data=data)
|
|
141
141
|
if d.server_tool_result:
|
|
142
142
|
idx = _fidx(d, 'server_tool_result')
|
|
143
143
|
part_accum.parts[idx] = Part(type=typ, data=d.server_tool_result)
|
|
144
|
-
srv_tc = next((p for p in reversed(list(part_accum.parts.values())) if isinstance(p, ToolCall) and p.server), None)
|
|
145
|
-
if srv_tc:
|
|
146
|
-
data = {**srv_tc.extra, 'id':srv_tc.id, 'name':srv_tc.name, 'arguments':srv_tc.arguments, 'server':True}
|
|
147
|
-
yield Part(type=PartType.tool_result, text="Server tool call executed.", data=data)
|
|
148
144
|
r = _proc(d, 'refusal')
|
|
149
145
|
if r[0]: yield r[0]
|
|
150
146
|
if d.finish_reason: fin = d.finish_reason
|
|
@@ -7,15 +7,16 @@ __all__ = ['PartType', 'FinishReason', 'api_registry', 'model_prices_url', 'haik
|
|
|
7
7
|
'gpt54', 'gpt54m', 'gpt55', 'codex54', 'codex54m', 'codex55', 'codex53spark', 'model_info_registry',
|
|
8
8
|
'modern_llm', 'deepseek_v4_common', 'mimo_v25_common', 'codex_pricing', 'Part', 'Msg', 'ToolCall',
|
|
9
9
|
'display_list', 'Usage', 'Completion', 'APIRegistry', 'mk_completion', 'mk_tool_res_msg', 'fn_schema',
|
|
10
|
-
'sys_text', 'part_txt', 'data_url', 'url_mime', 'payload_kwargs', 'get_api_key', '
|
|
11
|
-
'infer_api_name', 'get_model_meta', 'register_model_info', 'get_model_info',
|
|
12
|
-
'approx_pricing']
|
|
10
|
+
'sys_text', 'part_txt', 'data_url', 'url_mime', 'payload_kwargs', 'get_api_key', 'resize_b64',
|
|
11
|
+
'model_prices_meta', 'infer_api_name', 'get_model_meta', 'register_model_info', 'get_model_info',
|
|
12
|
+
'get_model_pricing', 'approx_pricing']
|
|
13
13
|
|
|
14
14
|
# %% ../nbs/00_types.ipynb #b4d047fd
|
|
15
|
-
import httpx
|
|
15
|
+
import httpx, base64, io
|
|
16
16
|
from dataclasses import dataclass, field
|
|
17
17
|
from fastcore.net import urljson
|
|
18
18
|
from fastcore.utils import *
|
|
19
|
+
from PIL import Image as PImg
|
|
19
20
|
|
|
20
21
|
# %% ../nbs/00_types.ipynb #e568bade
|
|
21
22
|
@dataclass
|
|
@@ -160,6 +161,7 @@ api_registry = APIRegistry()
|
|
|
160
161
|
# %% ../nbs/00_types.ipynb #d58a5f96
|
|
161
162
|
def mk_completion(resp, model, api_name, vendor_name):
|
|
162
163
|
"Normalize an api response into Completion."
|
|
164
|
+
resp = obj2dict(resp)
|
|
163
165
|
api = api_registry.apis[api_name]
|
|
164
166
|
tcs = api.norm_tool_calls(resp)
|
|
165
167
|
parts = api.norm_parts(resp)
|
|
@@ -242,11 +244,26 @@ def get_api_key(api_key, default):
|
|
|
242
244
|
if not key: raise ValueError(f"Missing API key: set environment variable '{default}' or pass `api_key` parameter")
|
|
243
245
|
return key
|
|
244
246
|
|
|
247
|
+
# %% ../nbs/00_types.ipynb #25e9cd60
|
|
248
|
+
def resize_b64(b64, max_sz):
|
|
249
|
+
"Resize a base64 image data to a max long edge, preserving aspect ratio."
|
|
250
|
+
img = PImg.open(io.BytesIO(base64.b64decode(b64)))
|
|
251
|
+
if max(img.size) < max_sz: return b64
|
|
252
|
+
img.thumbnail((max_sz,max_sz), PImg.Resampling.LANCZOS)
|
|
253
|
+
fmt = (img.format or 'PNG').upper()
|
|
254
|
+
if fmt=='JPG': fmt = 'JPEG'
|
|
255
|
+
buf = io.BytesIO()
|
|
256
|
+
img.save(buf, format=fmt)
|
|
257
|
+
return base64.b64encode(buf.getvalue()).decode()
|
|
258
|
+
|
|
245
259
|
# %% ../nbs/00_types.ipynb #852adecd
|
|
246
260
|
model_prices_url = 'https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json'
|
|
247
261
|
|
|
248
|
-
|
|
249
|
-
|
|
262
|
+
def model_prices_meta():
|
|
263
|
+
"Download model prices to the module dir once, then load from disk."
|
|
264
|
+
p = Path(__file__).parent/'model_prices.json'
|
|
265
|
+
if not p.exists(): p.write_text(httpx.get(model_prices_url, follow_redirects=True).text)
|
|
266
|
+
return loads(p.read_text())
|
|
250
267
|
|
|
251
268
|
# %% ../nbs/00_types.ipynb #68e488d8
|
|
252
269
|
def infer_api_name(model):
|
|
@@ -256,7 +273,6 @@ def infer_api_name(model):
|
|
|
256
273
|
if any(o in model for o in ('gpt','o3-','o4-')): return 'openai'
|
|
257
274
|
|
|
258
275
|
# %% ../nbs/00_types.ipynb #2f0720c2
|
|
259
|
-
@flexicache(time_policy(24*60*60))
|
|
260
276
|
def get_model_meta(model, vendor_name=None, tfm=noop):
|
|
261
277
|
"Look up cost metadata for `model` from litellm price map, using `vendor_name` prefix if needed."
|
|
262
278
|
vendor_name = ifnone(vendor_name, infer_api_name(model))
|
|
@@ -264,7 +280,7 @@ def get_model_meta(model, vendor_name=None, tfm=noop):
|
|
|
264
280
|
if model in mp: key = model
|
|
265
281
|
elif vendor_name=='gemini' and model.startswith('models/'): key = f"gemini/{model.removeprefix('models/')}"
|
|
266
282
|
elif vendor_name: key = f"{vendor_name}/{model}"
|
|
267
|
-
return dict2obj(tfm(mp.get(key), model, vendor_name))
|
|
283
|
+
return dict2obj(tfm(mp.get(key, {}), model, vendor_name))
|
|
268
284
|
|
|
269
285
|
# %% ../nbs/00_types.ipynb #60607e23
|
|
270
286
|
haik45 = "claude-haiku-4-5"
|
|
@@ -342,9 +358,9 @@ register_model_info('deepseek-v4-pro', vendor_name='deepseek', base='deepseek/de
|
|
|
342
358
|
|
|
343
359
|
mimo_v25_common = dict(**modern_llm, supports_web_search=True, max_input_tokens=1048576, max_output_tokens=131072, max_tokens=131072)
|
|
344
360
|
|
|
345
|
-
register_model_info('mimo-v2.5-pro', vendor_name='mimo', **mimo_v25_common, base='deepseek
|
|
361
|
+
register_model_info('mimo-v2.5-pro', vendor_name='mimo', **mimo_v25_common, base='deepseek-v4-pro', base_vendor_name='deepseek',
|
|
346
362
|
input_cost_per_token=0.435e-6, output_cost_per_token=0.87e-6, cache_read_input_token_cost=0.0036e-6, search_context_cost_per_query=0.005)
|
|
347
|
-
register_model_info('mimo-v2.5', vendor_name='mimo', **mimo_v25_common, base='deepseek
|
|
363
|
+
register_model_info('mimo-v2.5', vendor_name='mimo', **mimo_v25_common, base='deepseek-v4-pro', base_vendor_name='deepseek',
|
|
348
364
|
input_cost_per_token=0.14e-6, output_cost_per_token=0.28e-6, cache_read_input_token_cost=0.0028e-6, search_context_cost_per_query=0.005,
|
|
349
365
|
supports_vision=True, supports_image_input=True)
|
|
350
366
|
|
|
@@ -15,7 +15,7 @@ classifiers = [
|
|
|
15
15
|
"Programming Language :: Python :: 3",
|
|
16
16
|
"Programming Language :: Python :: 3 :: Only",
|
|
17
17
|
]
|
|
18
|
-
dependencies = ['fastspec', 'toolslm']
|
|
18
|
+
dependencies = ['fastspec', 'toolslm', 'pillow']
|
|
19
19
|
|
|
20
20
|
[project.urls]
|
|
21
21
|
Repository = "https://github.com/AnswerDotAI/fastllm"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-fastllm
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.15
|
|
4
4
|
Author-email: Kerem Turgutlu <keremturgutlu@gmail.com>
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Project-URL: Repository, https://github.com/AnswerDotAI/fastllm
|
|
@@ -11,6 +11,7 @@ Requires-Python: >=3.10
|
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
Requires-Dist: fastspec
|
|
13
13
|
Requires-Dist: toolslm
|
|
14
|
+
Requires-Dist: pillow
|
|
14
15
|
|
|
15
16
|
# fastllm
|
|
16
17
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.0.12"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_fastllm-0.0.12 → python_fastllm-0.0.15}/python_fastllm.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|