python-fastllm 0.0.60__tar.gz → 0.0.62__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.60 → python_fastllm-0.0.62}/PKG-INFO +16 -29
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/README.md +15 -28
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/fastllm/__init__.py +1 -1
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/fastllm/acomplete.py +8 -4
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/fastllm/chat.py +4 -0
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/fastllm/model_prices.json +6517 -470
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/fastllm/openai_chat.py +1 -1
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/fastllm/openai_responses.py +1 -0
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/fastllm/responses.py +10 -7
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/fastllm/types.py +28 -31
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/python_fastllm.egg-info/PKG-INFO +16 -29
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/fastllm/_modidx.py +0 -0
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/fastllm/anthropic.py +0 -0
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/fastllm/codex.py +0 -0
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/fastllm/gemini.py +0 -0
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/fastllm/streaming.py +0 -0
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/pyproject.toml +0 -0
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/python_fastllm.egg-info/SOURCES.txt +0 -0
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/python_fastllm.egg-info/dependency_links.txt +0 -0
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/python_fastllm.egg-info/entry_points.txt +0 -0
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/python_fastllm.egg-info/requires.txt +0 -0
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/python_fastllm.egg-info/top_level.txt +0 -0
- {python_fastllm-0.0.60 → python_fastllm-0.0.62}/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.62
|
|
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
|
|
@@ -61,15 +61,11 @@ mtok = 1024
|
|
|
61
61
|
Use the same `acomplete` interface with Claude, GPT, Gemini, or Kimi. Set `model` and any provider-specific routing arguments:
|
|
62
62
|
|
|
63
63
|
``` python
|
|
64
|
-
models = [
|
|
65
|
-
('
|
|
66
|
-
('gpt-4o-mini', {}),
|
|
67
|
-
('models/gemini-3-flash-preview', {}),
|
|
68
|
-
('accounts/fireworks/models/kimi-k3', dict(vendor_name='fireworks_ai'))
|
|
69
|
-
]
|
|
64
|
+
models = [('claude-sonnet-5', {}), ('gpt-4o-mini', {}), ('models/gemini-3-flash-preview', {}),
|
|
65
|
+
('accounts/fireworks/models/kimi-k3', dict(vendor_name='fireworks_ai'))]
|
|
70
66
|
for name, kw in models:
|
|
71
67
|
r = await acomplete([user("Translate 'hello' into French. Return only the translation.")],
|
|
72
|
-
|
|
68
|
+
model=name, max_tokens=mtok, **kw)
|
|
73
69
|
text = ''.join(p.text for p in r.message.content if isinstance(p, Text))
|
|
74
70
|
print(f"{name}: {text.strip()}")
|
|
75
71
|
```
|
|
@@ -101,11 +97,8 @@ r = await stream([user("What should I do today?")], model='models/gemini-3-flash
|
|
|
101
97
|
Define tools in the shared schema. `fastllm` translates it to the provider’s tool format. This example handles a tool request, adds the result to the history, and continues the conversation:
|
|
102
98
|
|
|
103
99
|
``` python
|
|
104
|
-
tools = [{"type": "function", "function":
|
|
105
|
-
"
|
|
106
|
-
"description": "Get current weather for a city",
|
|
107
|
-
"parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}
|
|
108
|
-
}}]
|
|
100
|
+
tools = [{"type": "function", "function": dict(name="get_weather", description="Get current weather for a city",
|
|
101
|
+
parameters=dict(type="object", properties={"city": {"type": "string"}}, required=["city"]))}]
|
|
109
102
|
|
|
110
103
|
msgs = [user("What's the weather in Paris?")]
|
|
111
104
|
r1 = await stream(msgs, model='claude-sonnet-5', tools=tools, max_tokens=mtok)
|
|
@@ -118,7 +111,7 @@ print("Tool calls:", r1.tool_calls)
|
|
|
118
111
|
|
|
119
112
|
``` python
|
|
120
113
|
msgs += [r1.message, mk_tool_res_msg(r1.tool_calls, ['22°C, sunny with light clouds']),
|
|
121
|
-
|
|
114
|
+
user("Should I bring a jacket? Answer in one short sentence.")]
|
|
122
115
|
r2 = await stream(msgs, model='claude-sonnet-5', tools=tools, max_tokens=mtok)
|
|
123
116
|
```
|
|
124
117
|
|
|
@@ -129,12 +122,10 @@ r2 = await stream(msgs, model='claude-sonnet-5', tools=tools, max_tokens=mtok)
|
|
|
129
122
|
Control whether the model must use tools, can’t use tools, or decides on its own:
|
|
130
123
|
|
|
131
124
|
``` python
|
|
132
|
-
r = await acomplete([user(
|
|
133
|
-
tools=tools, tool_choice='required', max_tokens=mtok)
|
|
125
|
+
r = await acomplete([user('Hello there!')], model='claude-sonnet-5', tools=tools, tool_choice='required', max_tokens=mtok)
|
|
134
126
|
print("Required:", [tc.name for tc in r.tool_calls])
|
|
135
127
|
|
|
136
|
-
r = await acomplete([user("What's the weather?")], model='claude-sonnet-5',
|
|
137
|
-
tools=tools, tool_choice='none', max_tokens=mtok)
|
|
128
|
+
r = await acomplete([user("What's the weather?")], model='claude-sonnet-5', tools=tools, tool_choice='none', max_tokens=mtok)
|
|
138
129
|
print("None:", r.tool_calls)
|
|
139
130
|
```
|
|
140
131
|
|
|
@@ -148,14 +139,13 @@ Set `reasoning_effort` to `low`, `medium`, or `high` for supported models. The a
|
|
|
148
139
|
``` python
|
|
149
140
|
print("Claude: ", end='')
|
|
150
141
|
r = await stream([user("What is 127 × 849? Return just the number.")], model='claude-sonnet-4-6',
|
|
151
|
-
|
|
142
|
+
reasoning_effort='low', max_tokens=8192)
|
|
152
143
|
for p in r.message.content:
|
|
153
144
|
if isinstance(p, Thinking): print(f"Thinking excerpt: {p.text[:150]}...")
|
|
154
145
|
|
|
155
146
|
print("Kimi: ", end='')
|
|
156
|
-
r = await stream([user(
|
|
157
|
-
|
|
158
|
-
reasoning_effort='low', max_tokens=8192)
|
|
147
|
+
r = await stream([user('What is 127 × 849? Return just the number.')], model='accounts/fireworks/models/kimi-k3',
|
|
148
|
+
vendor_name='fireworks_ai', reasoning_effort='low', max_tokens=8192)
|
|
159
149
|
for p in r.message.content:
|
|
160
150
|
if isinstance(p, Thinking): print(f"Thinking excerpt: {p.text[:150]}...")
|
|
161
151
|
```
|
|
@@ -172,7 +162,7 @@ OpenAI’s Responses API supports server-side web search. Server tool calls are
|
|
|
172
162
|
``` python
|
|
173
163
|
ws_tools = [{"type": "web_search_preview"}]
|
|
174
164
|
r = await acomplete([user("What is the latest Python release? Reply with the version number only.")],
|
|
175
|
-
|
|
165
|
+
model='gpt-4o-mini', tools=ws_tools, max_tokens=512)
|
|
176
166
|
print("Server tools used:", [tc.name for tc in r.tool_calls if tc.server])
|
|
177
167
|
```
|
|
178
168
|
|
|
@@ -187,11 +177,11 @@ long_ctx = "You are an expert on the solar system. " * 200
|
|
|
187
177
|
system = Text(long_ctx, cache_control={'type': 'ephemeral'})
|
|
188
178
|
|
|
189
179
|
r1 = await acomplete([user("What is Jupiter's mass? Answer in one sentence.")],
|
|
190
|
-
|
|
180
|
+
model='claude-sonnet-5', system=system, max_tokens=mtok)
|
|
191
181
|
print("First call: cache creation tokens", r1.usage.cache_creation_tokens)
|
|
192
182
|
|
|
193
183
|
r2 = await acomplete([user("What is Saturn's mass? Answer in one sentence.")],
|
|
194
|
-
|
|
184
|
+
model='claude-sonnet-5', system=system, max_tokens=mtok)
|
|
195
185
|
print("Second call: cache read tokens", r2.usage.cached_tokens)
|
|
196
186
|
```
|
|
197
187
|
|
|
@@ -203,10 +193,7 @@ print("Second call: cache read tokens", r2.usage.cached_tokens)
|
|
|
203
193
|
Use `InputImage` with a model that supports images. The example sends the same image message to three providers:
|
|
204
194
|
|
|
205
195
|
``` python
|
|
206
|
-
img_msg = Msg(role='user', content=[
|
|
207
|
-
InputImage(sample_img_url),
|
|
208
|
-
Text("List three visible objects, using nouns only.")
|
|
209
|
-
])
|
|
196
|
+
img_msg = Msg(role='user', content=[InputImage(sample_img_url), Text('List three visible objects, using nouns only.')])
|
|
210
197
|
|
|
211
198
|
for name, kw in [('claude-sonnet-5', {}), ('gpt-4o-mini', {}), ('models/gemini-3-flash-preview', {})]:
|
|
212
199
|
print(f"{name}: ", end='')
|
|
@@ -45,15 +45,11 @@ mtok = 1024
|
|
|
45
45
|
Use the same `acomplete` interface with Claude, GPT, Gemini, or Kimi. Set `model` and any provider-specific routing arguments:
|
|
46
46
|
|
|
47
47
|
``` python
|
|
48
|
-
models = [
|
|
49
|
-
('
|
|
50
|
-
('gpt-4o-mini', {}),
|
|
51
|
-
('models/gemini-3-flash-preview', {}),
|
|
52
|
-
('accounts/fireworks/models/kimi-k3', dict(vendor_name='fireworks_ai'))
|
|
53
|
-
]
|
|
48
|
+
models = [('claude-sonnet-5', {}), ('gpt-4o-mini', {}), ('models/gemini-3-flash-preview', {}),
|
|
49
|
+
('accounts/fireworks/models/kimi-k3', dict(vendor_name='fireworks_ai'))]
|
|
54
50
|
for name, kw in models:
|
|
55
51
|
r = await acomplete([user("Translate 'hello' into French. Return only the translation.")],
|
|
56
|
-
|
|
52
|
+
model=name, max_tokens=mtok, **kw)
|
|
57
53
|
text = ''.join(p.text for p in r.message.content if isinstance(p, Text))
|
|
58
54
|
print(f"{name}: {text.strip()}")
|
|
59
55
|
```
|
|
@@ -85,11 +81,8 @@ r = await stream([user("What should I do today?")], model='models/gemini-3-flash
|
|
|
85
81
|
Define tools in the shared schema. `fastllm` translates it to the provider’s tool format. This example handles a tool request, adds the result to the history, and continues the conversation:
|
|
86
82
|
|
|
87
83
|
``` python
|
|
88
|
-
tools = [{"type": "function", "function":
|
|
89
|
-
"
|
|
90
|
-
"description": "Get current weather for a city",
|
|
91
|
-
"parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}
|
|
92
|
-
}}]
|
|
84
|
+
tools = [{"type": "function", "function": dict(name="get_weather", description="Get current weather for a city",
|
|
85
|
+
parameters=dict(type="object", properties={"city": {"type": "string"}}, required=["city"]))}]
|
|
93
86
|
|
|
94
87
|
msgs = [user("What's the weather in Paris?")]
|
|
95
88
|
r1 = await stream(msgs, model='claude-sonnet-5', tools=tools, max_tokens=mtok)
|
|
@@ -102,7 +95,7 @@ print("Tool calls:", r1.tool_calls)
|
|
|
102
95
|
|
|
103
96
|
``` python
|
|
104
97
|
msgs += [r1.message, mk_tool_res_msg(r1.tool_calls, ['22°C, sunny with light clouds']),
|
|
105
|
-
|
|
98
|
+
user("Should I bring a jacket? Answer in one short sentence.")]
|
|
106
99
|
r2 = await stream(msgs, model='claude-sonnet-5', tools=tools, max_tokens=mtok)
|
|
107
100
|
```
|
|
108
101
|
|
|
@@ -113,12 +106,10 @@ r2 = await stream(msgs, model='claude-sonnet-5', tools=tools, max_tokens=mtok)
|
|
|
113
106
|
Control whether the model must use tools, can’t use tools, or decides on its own:
|
|
114
107
|
|
|
115
108
|
``` python
|
|
116
|
-
r = await acomplete([user(
|
|
117
|
-
tools=tools, tool_choice='required', max_tokens=mtok)
|
|
109
|
+
r = await acomplete([user('Hello there!')], model='claude-sonnet-5', tools=tools, tool_choice='required', max_tokens=mtok)
|
|
118
110
|
print("Required:", [tc.name for tc in r.tool_calls])
|
|
119
111
|
|
|
120
|
-
r = await acomplete([user("What's the weather?")], model='claude-sonnet-5',
|
|
121
|
-
tools=tools, tool_choice='none', max_tokens=mtok)
|
|
112
|
+
r = await acomplete([user("What's the weather?")], model='claude-sonnet-5', tools=tools, tool_choice='none', max_tokens=mtok)
|
|
122
113
|
print("None:", r.tool_calls)
|
|
123
114
|
```
|
|
124
115
|
|
|
@@ -132,14 +123,13 @@ Set `reasoning_effort` to `low`, `medium`, or `high` for supported models. The a
|
|
|
132
123
|
``` python
|
|
133
124
|
print("Claude: ", end='')
|
|
134
125
|
r = await stream([user("What is 127 × 849? Return just the number.")], model='claude-sonnet-4-6',
|
|
135
|
-
|
|
126
|
+
reasoning_effort='low', max_tokens=8192)
|
|
136
127
|
for p in r.message.content:
|
|
137
128
|
if isinstance(p, Thinking): print(f"Thinking excerpt: {p.text[:150]}...")
|
|
138
129
|
|
|
139
130
|
print("Kimi: ", end='')
|
|
140
|
-
r = await stream([user(
|
|
141
|
-
|
|
142
|
-
reasoning_effort='low', max_tokens=8192)
|
|
131
|
+
r = await stream([user('What is 127 × 849? Return just the number.')], model='accounts/fireworks/models/kimi-k3',
|
|
132
|
+
vendor_name='fireworks_ai', reasoning_effort='low', max_tokens=8192)
|
|
143
133
|
for p in r.message.content:
|
|
144
134
|
if isinstance(p, Thinking): print(f"Thinking excerpt: {p.text[:150]}...")
|
|
145
135
|
```
|
|
@@ -156,7 +146,7 @@ OpenAI’s Responses API supports server-side web search. Server tool calls are
|
|
|
156
146
|
``` python
|
|
157
147
|
ws_tools = [{"type": "web_search_preview"}]
|
|
158
148
|
r = await acomplete([user("What is the latest Python release? Reply with the version number only.")],
|
|
159
|
-
|
|
149
|
+
model='gpt-4o-mini', tools=ws_tools, max_tokens=512)
|
|
160
150
|
print("Server tools used:", [tc.name for tc in r.tool_calls if tc.server])
|
|
161
151
|
```
|
|
162
152
|
|
|
@@ -171,11 +161,11 @@ long_ctx = "You are an expert on the solar system. " * 200
|
|
|
171
161
|
system = Text(long_ctx, cache_control={'type': 'ephemeral'})
|
|
172
162
|
|
|
173
163
|
r1 = await acomplete([user("What is Jupiter's mass? Answer in one sentence.")],
|
|
174
|
-
|
|
164
|
+
model='claude-sonnet-5', system=system, max_tokens=mtok)
|
|
175
165
|
print("First call: cache creation tokens", r1.usage.cache_creation_tokens)
|
|
176
166
|
|
|
177
167
|
r2 = await acomplete([user("What is Saturn's mass? Answer in one sentence.")],
|
|
178
|
-
|
|
168
|
+
model='claude-sonnet-5', system=system, max_tokens=mtok)
|
|
179
169
|
print("Second call: cache read tokens", r2.usage.cached_tokens)
|
|
180
170
|
```
|
|
181
171
|
|
|
@@ -187,10 +177,7 @@ print("Second call: cache read tokens", r2.usage.cached_tokens)
|
|
|
187
177
|
Use `InputImage` with a model that supports images. The example sends the same image message to three providers:
|
|
188
178
|
|
|
189
179
|
``` python
|
|
190
|
-
img_msg = Msg(role='user', content=[
|
|
191
|
-
InputImage(sample_img_url),
|
|
192
|
-
Text("List three visible objects, using nouns only.")
|
|
193
|
-
])
|
|
180
|
+
img_msg = Msg(role='user', content=[InputImage(sample_img_url), Text('List three visible objects, using nouns only.')])
|
|
194
181
|
|
|
195
182
|
for name, kw in [('claude-sonnet-5', {}), ('gpt-4o-mini', {}), ('models/gemini-3-flash-preview', {})]:
|
|
196
183
|
print(f"{name}: ", end='')
|
|
@@ -33,6 +33,7 @@ vendor_mapping = {
|
|
|
33
33
|
"codex": ('openai', 'https://chatgpt.com/backend-api/codex', 'CODEX_AUTH_TOKEN', _codex_json),
|
|
34
34
|
"moonshot": ('openai_chat', "https://api.moonshot.ai/v1", "MOONSHOT_API_KEY"),
|
|
35
35
|
"deepseek": ('openai_chat', "https://api.deepseek.com/v1", "DEEPSEEK_API_KEY"),
|
|
36
|
+
"inception": ('openai_chat', "https://api.inceptionlabs.ai/v1", "INCEPTION_API_KEY"),
|
|
36
37
|
"mimo": ('anthropic', "https://api.xiaomimimo.com/anthropic", "MIMO_API_KEY"),
|
|
37
38
|
"openrouter": ('openai_chat', "https://openrouter.ai/api/v1", "OPENROUTER_API_KEY"),
|
|
38
39
|
"together": ('openai_chat', "https://api.together.xyz/v1", "TOGETHER_API_KEY"),
|
|
@@ -167,20 +168,23 @@ async def acomplete(msgs, model, api_name=None, vendor_name=None, api_key=None,
|
|
|
167
168
|
if own:
|
|
168
169
|
vendor_name = ifnone(vendor_name, api_name) # an own-transport api: no HTTP client to build
|
|
169
170
|
if oauth_token: kwargs['oauth_token'] = oauth_token # its `mk_payload` applies the user's token itself
|
|
170
|
-
else: cli, api_name, vendor_name = mk_client(model=model, vendor_name=vendor_name, api_name=api_name, api_key=api_key, oauth_token=oauth_token, base_url=base_url
|
|
171
|
+
else: cli, api_name, vendor_name = mk_client(model=model, vendor_name=vendor_name, api_name=api_name, api_key=api_key, oauth_token=oauth_token, base_url=base_url)
|
|
171
172
|
api = api_registry[api_name]
|
|
172
173
|
if previous_response_id is not None:
|
|
173
174
|
if not getattr(api, 'supports_previous_response_id', False):
|
|
174
175
|
raise ValueError('previous_response_id is not supported by this transport')
|
|
175
176
|
kwargs['previous_response_id'] = previous_response_id
|
|
176
177
|
payload = api.mk_payload(msgs, model, stream=stream, **kwargs)
|
|
177
|
-
xtra_body = ifnone(xtra_body, {})
|
|
178
178
|
if fix := getattr(api, 'fix_payload', None): fix(payload, model, vendor_name)
|
|
179
|
+
body = payload | ifnone(xtra_body, {})
|
|
179
180
|
if not own:
|
|
181
|
+
headers = xtra_hdrs or {}
|
|
182
|
+
if vendor_name == 'codex' and (key := body.get('prompt_cache_key')):
|
|
183
|
+
if not any(k.lower() == 'session-id' for k in headers): headers = {**headers, 'session-id':key}
|
|
180
184
|
ep = endpoint or api.endpoint
|
|
181
185
|
path,params = ep(model, stream) if callable(ep) else (ep, None)
|
|
182
|
-
if defaults.debug_mode: _debug_print(model, api_name, vendor_name,
|
|
183
|
-
async def _call(): return await provider_req(cli, path,
|
|
186
|
+
if defaults.debug_mode: _debug_print(model, api_name, vendor_name, body, None if own else cli._url(path))
|
|
187
|
+
async def _call(): return await provider_req(cli, path, body, params=params, stream=stream, headers=headers)
|
|
184
188
|
async def _mk_gen():
|
|
185
189
|
resp = payload if own else await _call() # an own-transport api's `acollect_stream` makes the request itself, from the payload
|
|
186
190
|
async for o in api.acollect_stream(resp, model=model, vendor_name=vendor_name, stop_callables=stop_callables): yield o
|
|
@@ -9,6 +9,7 @@ __all__ = ['effort', 'contents', 'stop_reason', 'cite_footnote', 'postproc', 'Re
|
|
|
9
9
|
'StopSequencesCallback', 'StreamAccum', 'adisplay_stream']
|
|
10
10
|
|
|
11
11
|
# %% ../nbs/07_chat.ipynb #d5a3bc1f
|
|
12
|
+
import secrets
|
|
12
13
|
from typing import Optional,Callable
|
|
13
14
|
from fastcore.funccall import mk_ns, call_func, call_func_async, get_schema
|
|
14
15
|
from fastcore.utils import *
|
|
@@ -168,6 +169,7 @@ class AsyncChat:
|
|
|
168
169
|
cache=False, # Anthropic prompt caching
|
|
169
170
|
cache_idxs:list=[-1], # Anthropic cache breakpoint idxs, use `0` for sys prompt if provided
|
|
170
171
|
ttl=None, # Anthropic prompt caching ttl
|
|
172
|
+
prompt_cache_key=None, # Stable conversation key for OpenAI Responses; generated once if omitted
|
|
171
173
|
api_name=None, # API to use, one of ApiName: openai (responses), openai_chat, anthropic, gemini
|
|
172
174
|
vendor_name=None, # Vendor name, one of vendor_mapping which resolves api_base/api_key automatically
|
|
173
175
|
api_key=None, # API key when model can't be resolved or vendor_name is not known or codex
|
|
@@ -195,6 +197,7 @@ class AsyncChat:
|
|
|
195
197
|
self.response_id,self._response_hist_idx = None,0
|
|
196
198
|
self._turn_start = 0 # index into `hist` where the current turn began, for `full`
|
|
197
199
|
self.last_req_use = None # usage of the latest request only; `use` accumulates across a turn's tool-call steps
|
|
200
|
+
if prompt_cache_key is None: prompt_cache_key = secrets.token_hex(16)
|
|
198
201
|
store_attr(but='cbs')
|
|
199
202
|
self.cbs = L()
|
|
200
203
|
if default_cbs: self.add_cbs(defaults.chat_callbacks)
|
|
@@ -256,6 +259,7 @@ def _prep_call(self:AsyncChat, search, max_tokens, kwargs, stream=False, think=N
|
|
|
256
259
|
if self.base_url: kwargs['base_url'] = self.base_url
|
|
257
260
|
if self.endpoint: kwargs['endpoint'] = self.endpoint
|
|
258
261
|
if self.extra_headers: kwargs['xtra_hdrs'] = self.extra_headers
|
|
262
|
+
kwargs.setdefault('prompt_cache_key', self.prompt_cache_key)
|
|
259
263
|
kwargs.update(_think_kw(self.model, think, self.vendor_name))
|
|
260
264
|
return max_tokens
|
|
261
265
|
|