python-fastllm 0.0.32__tar.gz → 0.0.34__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.32 → python_fastllm-0.0.34}/PKG-INFO +2 -2
  2. python_fastllm-0.0.34/fastllm/__init__.py +1 -0
  3. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/fastllm/_modidx.py +4 -5
  4. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/fastllm/acomplete.py +22 -7
  5. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/fastllm/chat.py +2 -30
  6. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/fastllm/streaming.py +1 -1
  7. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/fastllm/types.py +28 -25
  8. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/pyproject.toml +1 -1
  9. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/python_fastllm.egg-info/PKG-INFO +2 -2
  10. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/python_fastllm.egg-info/requires.txt +1 -1
  11. python_fastllm-0.0.32/fastllm/__init__.py +0 -1
  12. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/README.md +0 -0
  13. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/fastllm/anthropic.py +0 -0
  14. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/fastllm/codex.py +0 -0
  15. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/fastllm/gemini.py +0 -0
  16. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/fastllm/openai_chat.py +0 -0
  17. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/fastllm/openai_responses.py +0 -0
  18. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/fastllm/specs/anthropic.json +0 -0
  19. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/fastllm/specs/anthropic.yml +0 -0
  20. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/fastllm/specs/gemini.json +0 -0
  21. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/fastllm/specs/openai.with-code-samples.json +0 -0
  22. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/fastllm/specs/openai.with-code-samples.yml +0 -0
  23. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/fastllm/specs/spec_manifest.json +0 -0
  24. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/python_fastllm.egg-info/SOURCES.txt +0 -0
  25. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/python_fastllm.egg-info/dependency_links.txt +0 -0
  26. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/python_fastllm.egg-info/entry_points.txt +0 -0
  27. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/python_fastllm.egg-info/top_level.txt +0 -0
  28. {python_fastllm-0.0.32 → python_fastllm-0.0.34}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-fastllm
3
- Version: 0.0.32
3
+ Version: 0.0.34
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
@@ -10,7 +10,7 @@ Classifier: Programming Language :: Python :: 3 :: Only
10
10
  Requires-Python: >=3.10
11
11
  Description-Content-Type: text/markdown
12
12
  Requires-Dist: fastcore>=2.1.11
13
- Requires-Dist: aidialog>=0.0.3
13
+ Requires-Dist: aidialog>=0.0.5
14
14
  Requires-Dist: fastspec>=0.0.11
15
15
  Requires-Dist: toolslm
16
16
  Requires-Dist: pillow
@@ -0,0 +1 @@
1
+ __version__ = "0.0.34"
@@ -10,6 +10,7 @@ d = { 'settings': { 'branch': 'main',
10
10
  'fastllm.acomplete._classify_error': ('acomplete.html#_classify_error', 'fastllm/acomplete.py'),
11
11
  'fastllm.acomplete._classify_error_stream': ( 'acomplete.html#_classify_error_stream',
12
12
  'fastllm/acomplete.py'),
13
+ 'fastllm.acomplete._codex_mtime_policy': ('acomplete.html#_codex_mtime_policy', 'fastllm/acomplete.py'),
13
14
  'fastllm.acomplete._debug_print': ('acomplete.html#_debug_print', 'fastllm/acomplete.py'),
14
15
  'fastllm.acomplete._is_ctx_exceeded': ('acomplete.html#_is_ctx_exceeded', 'fastllm/acomplete.py'),
15
16
  'fastllm.acomplete._raise_if_done': ('acomplete.html#_raise_if_done', 'fastllm/acomplete.py'),
@@ -106,7 +107,6 @@ d = { 'settings': { 'branch': 'main',
106
107
  'fastllm.chat._add_cache_control': ('chat.html#_add_cache_control', 'fastllm/chat.py'),
107
108
  'fastllm.chat._alite_call_func': ('chat.html#_alite_call_func', 'fastllm/chat.py'),
108
109
  'fastllm.chat._apply_cache_idxs': ('chat.html#_apply_cache_idxs', 'fastllm/chat.py'),
109
- 'fastllm.chat._bytes2content': ('chat.html#_bytes2content', 'fastllm/chat.py'),
110
110
  'fastllm.chat._call_func': ('chat.html#_call_func', 'fastllm/chat.py'),
111
111
  'fastllm.chat._handle_stop_reason': ('chat.html#_handle_stop_reason', 'fastllm/chat.py'),
112
112
  'fastllm.chat._has_cache': ('chat.html#_has_cache', 'fastllm/chat.py'),
@@ -114,14 +114,11 @@ d = { 'settings': { 'branch': 'main',
114
114
  'fastllm.chat._has_stop': ('chat.html#_has_stop', 'fastllm/chat.py'),
115
115
  'fastllm.chat._inject_tool_reminder': ('chat.html#_inject_tool_reminder', 'fastllm/chat.py'),
116
116
  'fastllm.chat._lite_call_func': ('chat.html#_lite_call_func', 'fastllm/chat.py'),
117
- 'fastllm.chat._mime2part_type': ('chat.html#_mime2part_type', 'fastllm/chat.py'),
118
- 'fastllm.chat._mk_content': ('chat.html#_mk_content', 'fastllm/chat.py'),
119
117
  'fastllm.chat._mk_prefill': ('chat.html#_mk_prefill', 'fastllm/chat.py'),
120
118
  'fastllm.chat._mk_tool_result': ('chat.html#_mk_tool_result', 'fastllm/chat.py'),
121
119
  'fastllm.chat._tc_summary': ('chat.html#_tc_summary', 'fastllm/chat.py'),
122
120
  'fastllm.chat._think_kw': ('chat.html#_think_kw', 'fastllm/chat.py'),
123
121
  'fastllm.chat._trunc_param': ('chat.html#_trunc_param', 'fastllm/chat.py'),
124
- 'fastllm.chat._url2content': ('chat.html#_url2content', 'fastllm/chat.py'),
125
122
  'fastllm.chat._usrtools': ('chat.html#_usrtools', 'fastllm/chat.py'),
126
123
  'fastllm.chat.add_warning': ('chat.html#add_warning', 'fastllm/chat.py'),
127
124
  'fastllm.chat.adisplay_stream': ('chat.html#adisplay_stream', 'fastllm/chat.py'),
@@ -253,7 +250,9 @@ d = { 'settings': { 'branch': 'main',
253
250
  'fastllm.streaming.norm_and_yield': ('streaming.html#norm_and_yield', 'fastllm/streaming.py'),
254
251
  'fastllm.streaming.stop_and_trim': ('streaming.html#stop_and_trim', 'fastllm/streaming.py')},
255
252
  'fastllm.types': { 'fastllm.types.APIRegistry': ('types.html#apiregistry', 'fastllm/types.py'),
256
- 'fastllm.types.APIRegistry.__init__': ('types.html#apiregistry.__init__', 'fastllm/types.py'),
253
+ 'fastllm.types.APIRegistry.__contains__': ('types.html#apiregistry.__contains__', 'fastllm/types.py'),
254
+ 'fastllm.types.APIRegistry.__missing__': ('types.html#apiregistry.__missing__', 'fastllm/types.py'),
255
+ 'fastllm.types.APIRegistry._load': ('types.html#apiregistry._load', 'fastllm/types.py'),
257
256
  'fastllm.types.APIRegistry.register': ('types.html#apiregistry.register', 'fastllm/types.py'),
258
257
  'fastllm.types.Completion': ('types.html#completion', 'fastllm/types.py'),
259
258
  'fastllm.types.Completion._repr_markdown_': ('types.html#completion._repr_markdown_', 'fastllm/types.py'),
@@ -54,14 +54,29 @@ api2spec = {'openai':oai_spec, 'openai_chat':oai_spec, 'anthropic':ant_spec, 'ge
54
54
 
55
55
  # %% ../nbs/06_acomplete.ipynb #e3ed40fb
56
56
  def split_vendor(model):
57
- "Split a `'vendor/model'` path into `(vendor_name, model)`: the prefix must name a known vendor or a registered api, else `(None, model)`."
57
+ "Split a `'vendor/model'` path into `(vendor_name, model)`: the prefix must name a known vendor or a registered api (installed `fastllm.apis` plugins load on demand), else `(None, model)`."
58
58
  if model and '/' in model:
59
59
  v, m = model.split('/', 1)
60
- if v in vendor_mapping or v in api_registry.apis: return v, m
60
+ if v in vendor_mapping or v in api_registry: return v, m
61
61
  return None, model
62
62
 
63
+ # %% ../nbs/06_acomplete.ipynb #977a115b
64
+ def _codex_mtime_policy():
65
+ "`flexicache` policy: expire codex clients when the codex auth file changes"
66
+ def policy(state, args, kwargs):
67
+ v = kwargs.get('vendor_name') or (args[1] if len(args)>1 else None)
68
+ if not v:
69
+ m = kwargs.get('model') or (args[0] if args else None)
70
+ v = split_vendor(m)[0] if m else None
71
+ if v != 'codex': return None
72
+ try: mt = Path(_codex_path).expanduser().stat().st_mtime
73
+ except OSError: mt = None
74
+ return mt if state != mt else None
75
+ policy.needs_args = True
76
+ return policy
77
+
63
78
  # %% ../nbs/06_acomplete.ipynb #79075d95
64
- @flexicache()
79
+ @flexicache(_codex_mtime_policy())
65
80
  def mk_client(model=None, vendor_name=None, api_name=None, api_key=None, base_url=None, xtra_hdrs=None,
66
81
  timeout=httpx.Timeout(connect=30, read=300, write=30, pool=10)):
67
82
  err_msg = f"please pass a valid one vendor: {', '.join(list(vendor_mapping))} or pass `api_name`,`base_url` and `api_key`"
@@ -82,7 +97,7 @@ def mk_client(model=None, vendor_name=None, api_name=None, api_key=None, base_ur
82
97
  elif base_url and api_key: vendor_name, api_name = ifnone(vendor_name, 'custom'), ifnone(api_name, 'openai_chat')
83
98
  elif (api_name:=infer_api_name(model)): base_url, vendor_name = None, api_name
84
99
  else: raise ValueError(f"Model {model} can't be auto resolved, {err_msg}")
85
- api = api_registry.apis[api_name]
100
+ api = api_registry[api_name]
86
101
  spec, hdrs = api2spec[api_name], api.get_hdrs(api_key)
87
102
  cli = OpenAPIClient(spec, headers=merge(hdrs, ifnone(xtra_hdrs, {})), timeout=timeout)
88
103
  if base_url is not None:
@@ -163,13 +178,13 @@ async def acomplete(msgs, model, api_name=None, vendor_name=None, api_key=None,
163
178
  elif v: api_name, model = v, m # a registered transport api (e.g. claude_code): not an HTTP vendor
164
179
  if api_name == 'claude_code':
165
180
  if not stream: raise NotImplementedError("claude_code backend supports stream=True only for now")
166
- api = api_registry.apis[api_name]
181
+ api = api_registry[api_name]
167
182
  payload = api.mk_payload(msgs, model, stream=stream, **kwargs)
168
183
  async def _mk_gen():
169
184
  async for o in api.acollect_stream(payload, model=model, vendor_name='claude_code', stop_callables=stop_callables): yield o
170
185
  return _retry_stream(_mk_gen, retries, retry_delay)
171
- cli, api_name, vendor_name = mk_client(model, vendor_name, api_name, api_key, base_url, xtra_hdrs)
172
- api = api_registry.apis[api_name]
186
+ cli, api_name, vendor_name = mk_client(model=model, vendor_name=vendor_name, api_name=api_name, api_key=api_key, base_url=base_url, xtra_hdrs=xtra_hdrs)
187
+ api = api_registry[api_name]
173
188
  payload = api.mk_payload(msgs, model, stream=stream, **kwargs)
174
189
  payload = merge(payload, ifnone(xtra_body, {}))
175
190
  if vendor_name == 'codex':
@@ -15,35 +15,13 @@ from toolslm.funccall import mk_ns, call_func, call_func_async, get_schema
15
15
  from fastcore.utils import *
16
16
  from fastcore.meta import delegates
17
17
  from dataclasses import dataclass
18
- import base64
19
18
 
20
19
  from .types import *
21
- from fastcore.xtras import detect_mime
22
20
  from aidialog.msg_parts import (Msg, Part, PartType, ToolCall, mk_tool_res_msg, mk_tr_details,
23
- tool_info, usage_info, think_start, think_end, StopResponse, display_list, MediaUrl, url_mime, fmt2hist,
24
- _mk_result_fence, _split_fence_msgs, _fence_back, _trunc_str)
21
+ tool_info, usage_info, think_start, think_end, StopResponse, display_list, fmt2hist,
22
+ _mk_content, _mk_result_fence, _split_fence_msgs, _fence_back, _trunc_str)
25
23
  from .acomplete import *
26
24
 
27
- # %% ../nbs/07_chat.ipynb #4a37bae5
28
- def _mime2part_type(mime):
29
- "Map MIME string to canonical PartType"
30
- if mime.startswith('image/'): return PartType.input_image
31
- if mime.startswith('audio/'): return PartType.input_audio
32
- if mime.startswith('video/'): return PartType.input_video
33
- return PartType.input_file
34
-
35
- def _bytes2content(data):
36
- "Convert bytes to fastllm canonical content"
37
- mtype = detect_mime(data)
38
- if not mtype: raise ValueError(f'Data must be a supported file type, got {data[:10]}')
39
- encoded = base64.b64encode(data).decode("utf-8")
40
- return Part(type=_mime2part_type(mtype), text=f'data:{mtype};base64,{encoded}')
41
-
42
- def _url2content(o):
43
- "Convert MediaUrl to fastllm canonical content"
44
- mime = o.mime or url_mime(o.url)
45
- return Part(type=_mime2part_type(mime), text=o.url, data=dict(mime=mime))
46
-
47
25
  # %% ../nbs/07_chat.ipynb #43a55cda
48
26
  def _add_cache_control(
49
27
  msg, # LiteLLM formatted msg
@@ -67,12 +45,6 @@ def remove_cache_ckpts(msg):
67
45
  if part.data: part.data.pop('cache_control', None)
68
46
  return msg
69
47
 
70
- def _mk_content(o):
71
- if isinstance(o, str): return Part(type=PartType.text, text=o)
72
- elif isinstance(o, bytes): return _bytes2content(o)
73
- elif isinstance(o, MediaUrl): return _url2content(o)
74
- return o
75
-
76
48
 
77
49
  # %% ../nbs/07_chat.ipynb #48c78e48
78
50
  def contents(c):
@@ -150,7 +150,7 @@ async def mk_acollect_stream(it, index_fn, model=None, api_name=None, vendor_nam
150
150
  deltas.append(d)
151
151
  part_accum.finalize()
152
152
  tcs = part_accum.tool_calls
153
- if api_name: usg = api_registry.apis[api_name].finalize_usage(usg, part_accum.parts)
153
+ if api_name: usg = api_registry[api_name].finalize_usage(usg, part_accum.parts)
154
154
  if stop: fin = FinishReason.stop
155
155
  fin = FinishReason.tool_calls if fin==FinishReason.stop and any(~L(tcs).attrgot('server')) else fin # recheck tool calls post collation
156
156
  # tool calls and non-anthropic citations are yielded at the end
@@ -3,15 +3,17 @@
3
3
  # AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/00_types.ipynb.
4
4
 
5
5
  # %% auto #0
6
- __all__ = ['FinishReason', 'api_registry', 'model_prices_url', 'haik45', 'sonn45', 'sonn', 'sonn46', 'sonn5', 'opus46', 'opus',
7
- 'gpt54', 'gpt54m', 'gpt55', 'codex54', 'codex54m', 'codex55', 'codex53spark', 'model_info_registry',
8
- 'modern_llm', 'deepseek_v4_common', 'mimo_v25_common', 'codex_pricing', 'sol', 'terra', 'luna', 'gpt56s',
9
- 'Usage', 'Completion', 'APIRegistry', 'mk_completion', 'fn_schema', 'payload_kwargs', 'get_api_key',
10
- 'resize_b64', 'model_prices_meta', 'infer_api_name', 'get_model_meta', 'register_model_info',
11
- 'get_model_info', 'get_model_pricing', 'approx_pricing', 'is_deepseek_peak_hour']
6
+ __all__ = ['FinishReason', 'api_registry', 'model_prices_url', 'haik45', 'sonn45', 'sonn46', 'sonn', 'sonn5', 'opus46', 'opus48',
7
+ 'opus', 'opus5', 'fable', 'fable5', 'gpt54', 'gpt54m', 'gpt55', 'codex54', 'codex54m', 'codex55',
8
+ 'codex53spark', 'model_info_registry', 'modern_llm', 'deepseek_v4_common', 'mimo_v25_common',
9
+ 'codex_pricing', 'sol', 'terra', 'luna', 'gpt56s', 'Usage', 'Completion', 'APIRegistry', 'mk_completion',
10
+ 'fn_schema', 'payload_kwargs', 'get_api_key', 'resize_b64', 'model_prices_meta', 'infer_api_name',
11
+ 'get_model_meta', 'register_model_info', 'get_model_info', 'get_model_pricing', 'approx_pricing',
12
+ 'is_deepseek_peak_hour']
12
13
 
13
14
  # %% ../nbs/00_types.ipynb #b4d047fd
14
15
  import httpx, base64, io
16
+ from importlib.metadata import entry_points
15
17
  from dataclasses import dataclass, field
16
18
  from datetime import datetime, timezone
17
19
  from fastcore.net import urljson
@@ -73,9 +75,18 @@ def _repr_markdown_(self: Completion):
73
75
  FinishReason = str_enum('finish_reason', 'stop', 'tool_calls', 'length', 'content_filter')
74
76
 
75
77
  # %% ../nbs/00_types.ipynb #fc681c52
76
- class APIRegistry:
77
- def __init__(self): self.apis = {}
78
- def register(self, name, finalize_usage=noop, **kwargs): self.apis[name] = SimpleNamespace(finalize_usage=finalize_usage, **kwargs)
78
+ class APIRegistry(dict):
79
+ _eps = None
80
+ def register(self, name, finalize_usage=noop, **kwargs): self[name] = SimpleNamespace(finalize_usage=finalize_usage, **kwargs)
81
+ def _load(self, name):
82
+ "Import the plugin providing api `name` from the `fastllm.apis` entry-point group; its import registers the api."
83
+ if self._eps is None: self._eps = {o.name:o for o in entry_points(group='fastllm.apis')}
84
+ if name in self._eps: self._eps[name].load()
85
+ return dict.__contains__(self, name)
86
+ def __contains__(self, name): return dict.__contains__(self, name) or self._load(name)
87
+ def __missing__(self, name):
88
+ if self._load(name): return self[name]
89
+ raise KeyError(name)
79
90
 
80
91
  api_registry = APIRegistry()
81
92
 
@@ -84,7 +95,7 @@ api_registry = APIRegistry()
84
95
  def mk_completion(resp, model, api_name, vendor_name):
85
96
  "Normalize an api response into Completion."
86
97
  resp = obj2dict(resp)
87
- api = api_registry.apis[api_name]
98
+ api = api_registry[api_name]
88
99
  tcs = api.norm_tool_calls(resp)
89
100
  parts = api.norm_parts(resp)
90
101
  usg = api.finalize_usage(api.norm_usage(resp), parts)
@@ -158,10 +169,12 @@ def get_model_meta(model, vendor_name=None, tfm=noop):
158
169
  # %% ../nbs/00_types.ipynb #60607e23
159
170
  haik45 = "claude-haiku-4-5"
160
171
  sonn45 = "claude-sonnet-4-5"
161
- sonn = sonn46 = "claude-sonnet-4-6"
162
- sonn5 = "claude-sonnet-5"
172
+ sonn46 = "claude-sonnet-4-6"
173
+ sonn = sonn5 = "claude-sonnet-5"
163
174
  opus46 = "claude-opus-4-6"
164
- opus = "claude-opus-4-8"
175
+ opus48 = "claude-opus-4-8"
176
+ opus = opus5 = "claude-opus-5"
177
+ fable = fable5 = 'claude-fable-5'
165
178
  gpt54 = "gpt-5.4"
166
179
  gpt54m = "gpt-5.4-mini"
167
180
  gpt55 = "gpt-5.5"
@@ -186,9 +199,6 @@ def get_model_info(mn, vendor_name=None):
186
199
  if 'search_context_cost_per_query' in info: info['supports_web_search'] = True
187
200
  return dict2obj(info)
188
201
 
189
- # %% ../nbs/00_types.ipynb #331c5d0a
190
- register_model_info("claude-opus-4-8", vendor_name='anthropic', base="claude-opus-4-6")
191
-
192
202
  # %% ../nbs/00_types.ipynb #b36178d4
193
203
  modern_llm = dict(supports_function_calling=True, supports_tool_choice=True, supports_prompt_caching=True,
194
204
  supports_parallel_function_calling=True, supports_native_streaming=True, supports_native_structured_output=True,
@@ -259,10 +269,6 @@ register_model_info('mimo-v2.5-pro-ultraspeed', vendor_name='mimo', **mimo_v25_c
259
269
  # %% ../nbs/00_types.ipynb #defb1c5c
260
270
  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)
261
271
 
262
- register_model_info('claude-fable-5', vendor_name='anthropic', base="claude-opus-4-8",
263
- input_cost_per_token=10e-6, cache_creation_input_token_cost=12.5e-6, output_cost_per_token=50e-6,
264
- cache_read_input_token_cost=1e-6, search_context_cost_per_query=0.005)
265
-
266
272
  # %% ../nbs/00_types.ipynb #4e1b40b3
267
273
  register_model_info('muse-spark-1.1', vendor_name='meta_ai', **modern_llm,
268
274
  max_input_tokens=1_048_576, max_output_tokens=128000, max_tokens=128000,
@@ -283,12 +289,9 @@ register_model_info(codex53spark, 'codex', **codex_pricing,
283
289
  max_tokens=128000, max_input_tokens=128000, max_output_tokens=128000)
284
290
 
285
291
  # %% ../nbs/00_types.ipynb #5d3e4720
286
- for model in (haik45, sonn45, sonn46, sonn5, opus46, opus):
292
+ for model in (haik45, sonn45, sonn46, sonn5, opus46, opus48, opus5, fable5):
287
293
  register_model_info(model, 'claude_code', base=model, base_vendor_name='anthropic', **codex_pricing)
288
294
 
289
- # %% ../nbs/00_types.ipynb #60630540
290
- register_model_info(sonn5, base=sonn5, max_input_tokens=760_000)
291
-
292
295
  # %% ../nbs/00_types.ipynb #bb0c4c2a
293
296
  sol,terra,luna = gpt56s = 'gpt-5.6-sol gpt-5.6-terra gpt-5.6-luna'.split()
294
297
  for model in ['gpt-5.6']+gpt56s:
@@ -321,7 +324,7 @@ def is_deepseek_peak_hour(dt=None):
321
324
  @patch(as_prop=True)
322
325
  def cost(self:Completion):
323
326
  meta = dict2obj(get_model_info(self.model, self.vendor_name))
324
- api = api_registry.apis[self.api_name]
327
+ api = api_registry[self.api_name]
325
328
  if not hasattr(api, 'cost'): raise NotImplementedError(f"API: {self.api_name} doesn't have a registered `cost` function in ns")
326
329
  res = api.cost(self.usage, meta)
327
330
  return res*2 if self.vendor_name=='deepseek' and self.model.startswith('deepseek-v4') and is_deepseek_peak_hour() else res
@@ -15,7 +15,7 @@ classifiers = [
15
15
  "Programming Language :: Python :: 3",
16
16
  "Programming Language :: Python :: 3 :: Only",
17
17
  ]
18
- dependencies = ['fastcore>=2.1.11', 'aidialog>=0.0.3', 'fastspec>=0.0.11', 'toolslm', 'pillow']
18
+ dependencies = ['fastcore>=2.1.11', 'aidialog>=0.0.5', 'fastspec>=0.0.11', '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.32
3
+ Version: 0.0.34
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
@@ -10,7 +10,7 @@ Classifier: Programming Language :: Python :: 3 :: Only
10
10
  Requires-Python: >=3.10
11
11
  Description-Content-Type: text/markdown
12
12
  Requires-Dist: fastcore>=2.1.11
13
- Requires-Dist: aidialog>=0.0.3
13
+ Requires-Dist: aidialog>=0.0.5
14
14
  Requires-Dist: fastspec>=0.0.11
15
15
  Requires-Dist: toolslm
16
16
  Requires-Dist: pillow
@@ -1,5 +1,5 @@
1
1
  fastcore>=2.1.11
2
- aidialog>=0.0.3
2
+ aidialog>=0.0.5
3
3
  fastspec>=0.0.11
4
4
  toolslm
5
5
  pillow
@@ -1 +0,0 @@
1
- __version__ = "0.0.32"