python-fastllm 0.0.41__tar.gz → 0.0.43__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.
Files changed (28) hide show
  1. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/PKG-INFO +1 -1
  2. python_fastllm-0.0.43/fastllm/__init__.py +1 -0
  3. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/fastllm/_modidx.py +3 -1
  4. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/fastllm/acomplete.py +2 -1
  5. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/fastllm/types.py +38 -29
  6. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/pyproject.toml +1 -0
  7. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/python_fastllm.egg-info/PKG-INFO +1 -1
  8. python_fastllm-0.0.41/fastllm/__init__.py +0 -1
  9. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/README.md +0 -0
  10. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/fastllm/anthropic.py +0 -0
  11. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/fastllm/chat.py +0 -0
  12. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/fastllm/codex.py +0 -0
  13. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/fastllm/gemini.py +0 -0
  14. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/fastllm/openai_chat.py +0 -0
  15. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/fastllm/openai_responses.py +0 -0
  16. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/fastllm/specs/anthropic.json +0 -0
  17. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/fastllm/specs/anthropic.yml +0 -0
  18. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/fastllm/specs/gemini.json +0 -0
  19. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/fastllm/specs/openai.with-code-samples.json +0 -0
  20. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/fastllm/specs/openai.with-code-samples.yml +0 -0
  21. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/fastllm/specs/spec_manifest.json +0 -0
  22. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/fastllm/streaming.py +0 -0
  23. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/python_fastllm.egg-info/SOURCES.txt +0 -0
  24. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/python_fastllm.egg-info/dependency_links.txt +0 -0
  25. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/python_fastllm.egg-info/entry_points.txt +0 -0
  26. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/python_fastllm.egg-info/requires.txt +0 -0
  27. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/python_fastllm.egg-info/top_level.txt +0 -0
  28. {python_fastllm-0.0.41 → python_fastllm-0.0.43}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-fastllm
3
- Version: 0.0.41
3
+ Version: 0.0.43
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
@@ -0,0 +1 @@
1
+ __version__ = "0.0.43"
@@ -281,4 +281,6 @@ d = { 'settings': { 'branch': 'main',
281
281
  'fastllm.types.price_tier': ('types.html#price_tier', 'fastllm/types.py'),
282
282
  'fastllm.types.register_model_info': ('types.html#register_model_info', 'fastllm/types.py'),
283
283
  'fastllm.types.resize_b64': ('types.html#resize_b64', 'fastllm/types.py'),
284
- 'fastllm.types.tier_rate': ('types.html#tier_rate', 'fastllm/types.py')}}}
284
+ 'fastllm.types.tier_rate': ('types.html#tier_rate', 'fastllm/types.py'),
285
+ 'fastllm.types.unwrap_typed': ('types.html#unwrap_typed', 'fastllm/types.py'),
286
+ 'fastllm.types.wrap_typed': ('types.html#wrap_typed', 'fastllm/types.py')}}}
@@ -47,7 +47,8 @@ vendor_mapping = {
47
47
  "fireworks_ai": ('openai_chat', "https://api.fireworks.ai/inference/v1", "FIREWORKS_API_KEY"),
48
48
  "qwen": ('openai_chat', "https://dashscope.aliyuncs.com/compatible-mode/v1", "QWEN_API_KEY"),
49
49
  "minimax": ('anthropic', "https://api.minimax.io/anthropic", "MINIMAX_API_KEY"),
50
- "meta_ai": ('openai', "https://api.meta.ai/v1", "META_API_KEY")
50
+ "meta_ai": ('openai', "https://api.meta.ai/v1", "META_API_KEY"),
51
+ "zai": ('openai_chat', "https://api.z.ai/api/paas/v4", "ZAI_API_KEY")
51
52
  }
52
53
 
53
54
  # %% ../nbs/06_acomplete.ipynb #77d27ea7
@@ -7,9 +7,9 @@ __all__ = ['FinishReason', 'api_registry', 'model_prices_url', 'haik45', 'sonn45
7
7
  'opus', 'opus5', 'fable', 'fable5', 'gpt54', 'gpt54m', 'gpt55', 'codex54', 'codex54m', 'codex55',
8
8
  'codex53spark', 'model_info_registry', 'modern_llm', 'deepseek_v4_common', 'mimo_v25_common',
9
9
  'codex_pricing', 'sol', 'terra', 'luna', 'gpt56s', 'Usage', 'APIRegistry', 'mk_completion', 'fn_schema',
10
- 'payload_kwargs', 'get_api_key', 'resize_b64', 'model_prices_meta', 'infer_api_name', 'get_model_meta',
11
- 'register_model_info', 'get_model_info', 'get_model_pricing', 'approx_pricing', 'is_deepseek_peak_hour',
12
- 'price_tier', 'tier_rate']
10
+ 'payload_kwargs', 'get_api_key', 'wrap_typed', 'unwrap_typed', 'resize_b64', 'model_prices_meta',
11
+ 'infer_api_name', 'get_model_meta', 'register_model_info', 'get_model_info', 'get_model_pricing',
12
+ 'approx_pricing', 'is_deepseek_peak_hour', 'price_tier', 'tier_rate']
13
13
 
14
14
  # %% ../nbs/00_types.ipynb #b4d047fd
15
15
  import httpx2, base64, io
@@ -17,7 +17,7 @@ from importlib.metadata import entry_points
17
17
  from datetime import datetime, timezone
18
18
  from fastcore.utils import *
19
19
  from PIL import Image as PImg
20
- from aidialog.msg_parts import Msg, Thinking, ToolUse, Completion
20
+ from aidialog.msg_parts import Msg, Thinking, ToolUse, Completion, StopResponse, FullResponse
21
21
 
22
22
 
23
23
  # %% ../nbs/00_types.ipynb #802ad832
@@ -81,14 +81,8 @@ def mk_completion(resp, model, api_name, vendor_name):
81
81
  tcs = api.norm_tool_calls(resp)
82
82
  parts = api.norm_parts(resp)
83
83
  usg = api.finalize_usage(api.norm_usage(resp), parts)
84
- return Completion(
85
- model=model,
86
- message=Msg(role="assistant", content=parts),
87
- finish_reason=api.norm_finish(resp, tcs),
88
- usage=usg,
89
- api_name=api_name,
90
- vendor_name=vendor_name,
91
- raw=resp)
84
+ return Completion(model=model, message=Msg(role="assistant", content=parts), finish_reason=api.norm_finish(resp, tcs),
85
+ usage=usg, api_name=api_name, vendor_name=vendor_name, raw=resp)
92
86
 
93
87
  # %% ../nbs/00_types.ipynb #8a8e468b
94
88
  def fn_schema(t):
@@ -110,6 +104,20 @@ def get_api_key(api_key, default):
110
104
  if not key: raise ValueError(f"Missing API key: set environment variable '{default}' or pass `api_key` parameter")
111
105
  return key
112
106
 
107
+ # %% ../nbs/00_types.ipynb #e6e9ac99
108
+ _typed_re = re.compile(r'^𝍁(\w+)𝍁(.+)$', re.S)
109
+ _typed_strs = {c.__name__: c for c in (StopResponse, FullResponse)}
110
+
111
+ def wrap_typed(s):
112
+ "Mark `s` with a `𝍁TypeName𝍁` prefix when it is a `str` subclass, so the type survives a plain-string wire"
113
+ return s if type(s) is str else f'𝍁{type(s).__name__}𝍁{s}'
114
+
115
+ def unwrap_typed(s):
116
+ "Rebuild the named `str` subclass from a `𝍁`-marked string; unknown names get a minted ephemeral type"
117
+ if not (m := _typed_re.match(s)): return s
118
+ nm,body = m.groups()
119
+ return _typed_strs.setdefault(nm, type(nm, (str,), {}))(body)
120
+
113
121
  # %% ../nbs/00_types.ipynb #25e9cd60
114
122
  def resize_b64(b64, max_sz):
115
123
  "Resize a base64 image data to a max long edge, preserving aspect ratio."
@@ -204,8 +212,7 @@ register_model_info('accounts/fireworks/routers/glm-5p2-fast', vendor_name='fire
204
212
  input_cost_per_token=2.8e-6, cache_read_input_token_cost=0.28e-6, output_cost_per_token=8.8e-6)
205
213
 
206
214
  register_model_info('gemini-3.5-flash', vendor_name='gemini', base='gemini-3-flash-preview',
207
- input_cost_per_token=1.5e-6, output_cost_per_token=9e-6,
208
- output_cost_per_reasoning_token=9e-6, cache_read_input_token_cost=1.5e-7)
215
+ input_cost_per_token=1.5e-6, output_cost_per_token=9e-6, output_cost_per_reasoning_token=9e-6, cache_read_input_token_cost=1.5e-7)
209
216
 
210
217
  register_model_info('gpt-5.4', vendor_name='openai', base='gpt-5.4', supports_web_search=True, mode=None)
211
218
  # Upstream metadata says 1,050,000 input tokens for gpt-5.4-mini, but OpenAI documents a 272k limit
@@ -226,9 +233,8 @@ register_model_info('accounts/fireworks/models/kimi-k2p6', vendor_name='firework
226
233
  input_cost_per_token=0.95e-6, cache_read_input_token_cost=0.16e-6, output_cost_per_token=4.0e-6)
227
234
  register_model_info('kimi-k2.7-code', vendor_name='moonshot', base='kimi-k2.6',
228
235
  input_cost_per_token=0.95e-6, cache_read_input_token_cost=0.19e-6, output_cost_per_token=4.0e-6)
229
- register_model_info('kimi-k3', vendor_name='moonshot', base='kimi-k2.6',
230
- supports_reasoning=True, supports_vision=True, max_input_tokens=1_000_000,
231
- input_cost_per_token=3e-6, cache_read_input_token_cost=0.30e-6, output_cost_per_token=15.0e-6)
236
+ register_model_info('kimi-k3', vendor_name='moonshot', base='kimi-k2.6', supports_reasoning=True, supports_vision=True,
237
+ max_input_tokens=1_000_000, input_cost_per_token=3e-6, cache_read_input_token_cost=0.30e-6, output_cost_per_token=15.0e-6)
232
238
 
233
239
  # %% ../nbs/00_types.ipynb #948d55d0
234
240
  deepseek_v4_common = dict(**modern_llm, max_input_tokens=1048576, max_output_tokens=393216, max_tokens=393216)
@@ -251,18 +257,23 @@ register_model_info('mimo-v2.5-pro-ultraspeed', vendor_name='mimo', **mimo_v25_c
251
257
  input_cost_per_token=1.305e-6, output_cost_per_token=2.61e-6, cache_read_input_token_cost=0.0108e-6, search_context_cost_per_query=0.005)
252
258
 
253
259
  # %% ../nbs/00_types.ipynb #defb1c5c
254
- register_model_info('MiniMax-M3', vendor_name='minimax', **modern_llm, max_input_tokens=512_000, max_output_tokens=512_000, max_tokens=512_000, input_cost_per_token=0.3e-6, output_cost_per_token=1.2e-6, cache_read_input_token_cost=0.06e-6, supports_vision=True, supports_video_input=True)
260
+ register_model_info('MiniMax-M3', vendor_name='minimax', **modern_llm, max_input_tokens=512_000, max_output_tokens=512_000, max_tokens=512_000,
261
+ input_cost_per_token=0.3e-6, output_cost_per_token=1.2e-6, cache_read_input_token_cost=0.06e-6, supports_vision=True, supports_video_input=True)
255
262
 
256
263
  # %% ../nbs/00_types.ipynb #4e1b40b3
257
- register_model_info('muse-spark-1.1', vendor_name='meta_ai', **modern_llm,
258
- max_input_tokens=1_048_576, max_output_tokens=128000, max_tokens=128000,
259
- supports_vision=True, supports_image_input=True, supports_video_input=True, supports_pdf_input=True,
260
- supports_web_search=True, search_context_cost_per_query=0.0025,
261
- input_cost_per_token=1.25e-6, output_cost_per_token=4.25e-6, cache_read_input_token_cost=0.15e-6)
264
+ register_model_info('muse-spark-1.1', vendor_name='meta_ai', **modern_llm, max_input_tokens=1_048_576, max_output_tokens=128000, max_tokens=128000,
265
+ supports_vision=True, supports_image_input=True, supports_video_input=True, supports_pdf_input=True, supports_web_search=True,
266
+ search_context_cost_per_query=0.0025, input_cost_per_token=1.25e-6, output_cost_per_token=4.25e-6, cache_read_input_token_cost=0.15e-6)
267
+
268
+ # %% ../nbs/00_types.ipynb #5a2b3430
269
+ # z.ai list pricing (a 50% discount applies until 2026-09-09)
270
+ register_model_info('glm-5.3-flash', vendor_name='zai', base='glm-5.1', **modern_llm,
271
+ supports_vision=True, supports_image_input=True,
272
+ max_input_tokens=1_000_000, max_output_tokens=128_000, max_tokens=128_000,
273
+ input_cost_per_token=0.15e-6, cache_read_input_token_cost=0.03e-6, output_cost_per_token=0.5e-6)
262
274
 
263
275
  # %% ../nbs/00_types.ipynb #2c23d11e
264
- codex_pricing = dict(
265
- input_cost_per_token = 0.10/1_000_000, output_cost_per_token = 0.50/1_000_000,
276
+ codex_pricing = dict(input_cost_per_token = 0.10/1_000_000, output_cost_per_token = 0.50/1_000_000,
266
277
  cache_creation_input_token_cost = 0.10/1_000_000, cache_read_input_token_cost = 0.10/1_000_000)
267
278
 
268
279
  def _rm_ctx_tiers(vendor_name, model):
@@ -284,8 +295,7 @@ for model in (haik45, sonn45, sonn46, sonn5, opus46, opus48, opus5, fable5):
284
295
 
285
296
  # %% ../nbs/00_types.ipynb #bb0c4c2a
286
297
  sol,terra,luna = gpt56s = 'gpt-5.6-sol gpt-5.6-terra gpt-5.6-luna'.split()
287
- for model in ['gpt-5.6']+gpt56s:
288
- register_model_info(model, 'openai', base=model, base_vendor_name='openai')
298
+ for model in ['gpt-5.6']+gpt56s: register_model_info(model, 'openai', base=model, base_vendor_name='openai')
289
299
  # Codex serves only the suffixed names; bare `gpt-5.6` is rejected with a ChatGPT account.
290
300
  # Its window is smaller than the API's: 371,331 input tokens is accepted and 371,981 is not, on all three.
291
301
  for model in gpt56s:
@@ -294,8 +304,7 @@ for model in gpt56s:
294
304
 
295
305
  # %% ../nbs/00_types.ipynb #24cc47ec
296
306
  def get_model_pricing(mn, vendor_name, million=True):
297
- return {k:round(v * (1e6 if million else 1), 6)
298
- for k,v in get_model_info(mn, vendor_name).items()
307
+ return {k:round(v * (1e6 if million else 1), 6) for k,v in get_model_info(mn, vendor_name).items()
299
308
  if 'cost' in k and isinstance(v,float) and 'priority' not in k}
300
309
 
301
310
  # %% ../nbs/00_types.ipynb #79304cd9
@@ -43,3 +43,4 @@ lib_path = "fastllm"
43
43
 
44
44
  [tool.chkstyle]
45
45
  skip_paths = ["_modidx.py"]
46
+ ignore = ["undocumented-export", "exported-run"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-fastllm
3
- Version: 0.0.41
3
+ Version: 0.0.43
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
@@ -1 +0,0 @@
1
- __version__ = "0.0.41"