返回提交历史
Modified
g4f/client/__init__.py
+27
-56
XFEstudio/gpt4free
fix: Remove unused BaseRetryProvider import and update provider_info handling in iter_response functions
12a86fae
代码差异
1 个文件
+27
-56
@@ -15,7 +15,7 @@ from typing import Union, AsyncIterator, Iterator, Awaitable, Optional, List, Di
15
15
16
16
from ..image.copy_images import copy_media, get_media_dir
17
17
from ..typing import Messages, ImageType
18
from ..providers.types import ProviderType, BaseRetryProvider, BaseProvider
18
from ..providers.types import ProviderType, BaseProvider
19
19
from ..providers.response import *
20
20
from ..errors import NoMediaResponseError, ProviderNotFoundError
21
21
from ..providers.retry_provider import IterListProvider
@@ -70,14 +70,15 @@ def iter_response(
70
70
stream: bool,
71
71
response_format: Optional[dict] = None,
72
72
max_tokens: Optional[int] = None,
73
stop: Optional[list[str]] = None
73
stop: Optional[list[str]] = None,
74
provider_info: Optional[ProviderInfo] = None
74
75
) -> ChatCompletionResponseType:
75
76
content = ""
76
77
reasoning = []
77
78
finish_reason = None
78
79
tool_calls = None
79
80
usage = None
80
provider: ProviderInfo = None
81
provider_info: ProviderInfo = None
81
82
conversation: JsonConversation = None
82
83
completion_id = ''.join(random.choices(string.ascii_letters + string.digits, k=28))
83
84
idx = 0
@@ -100,7 +101,7 @@ def iter_response(
100
101
usage = chunk
101
102
continue
102
103
elif isinstance(chunk, ProviderInfo):
103
provider = chunk
104
provider_info = chunk
104
105
continue
105
106
elif isinstance(chunk, Reasoning):
106
107
reasoning.append(chunk)
@@ -122,9 +123,9 @@ def iter_response(
122
123
123
124
if stream:
124
125
chunk = ChatCompletionChunk.model_construct(chunk, None, completion_id, int(time.time()))
125
if provider is not None:
126
chunk.provider = provider.name
127
chunk.model = provider.model
126
if provider_info is not None:
127
chunk.provider = provider_info.name
128
chunk.model = provider_info.model
128
129
yield chunk
129
130
130
131
if finish_reason is not None:
@@ -153,29 +154,18 @@ def iter_response(
153
154
conversation=None if conversation is None else conversation.get_dict(),
154
155
reasoning=reasoning if reasoning else None
155
156
)
156
if provider is not None:
157
chat_completion.provider = provider.name
158
chat_completion.model = provider.model
157
if provider_info is not None:
158
chat_completion.provider = provider_info.name
159
chat_completion.model = provider_info.model
159
160
yield chat_completion
160
161
161
# Synchronous iter_append_model_and_provider function
162
def iter_append_model_and_provider(response: ChatCompletionResponseType, last_model: str, last_provider: ProviderType) -> ChatCompletionResponseType:
163
if isinstance(last_provider, BaseRetryProvider):
164
yield from response
165
return
166
for chunk in response:
167
if isinstance(chunk, (ChatCompletion, ChatCompletionChunk)):
168
if chunk.provider is None and last_provider is not None:
169
chunk.model = getattr(last_provider, "last_model", last_model)
170
chunk.provider = last_provider.__name__
171
yield chunk
172
173
162
async def async_iter_response(
174
163
response: AsyncIterator[Union[str, ResponseType]],
175
164
stream: bool,
176
165
response_format: Optional[dict] = None,
177
166
max_tokens: Optional[int] = None,
178
stop: Optional[list[str]] = None
167
stop: Optional[list[str]] = None,
168
provider_info: Optional[ProviderInfo] = None
179
169
) -> AsyncChatCompletionResponseType:
180
170
content = ""
181
171
reasoning = []
@@ -184,7 +174,6 @@ async def async_iter_response(
184
174
idx = 0
185
175
tool_calls = None
186
176
usage = None
187
provider: ProviderInfo = None
188
177
conversation: JsonConversation = None
189
178
190
179
try:
@@ -203,7 +192,7 @@ async def async_iter_response(
203
192
usage = chunk
204
193
continue
205
194
elif isinstance(chunk, ProviderInfo):
206
provider = chunk
195
provider_info = chunk
207
196
continue
208
197
elif isinstance(chunk, Reasoning) and not stream:
209
198
reasoning.append(chunk)
@@ -225,9 +214,9 @@ async def async_iter_response(
225
214
226
215
if stream:
227
216
chunk = ChatCompletionChunk.model_construct(chunk, None, completion_id, int(time.time()))
228
if provider is not None:
229
chunk.provider = provider.name
230
chunk.model = provider.model
217
if provider_info is not None:
218
chunk.provider = provider_info.name
219
chunk.model = provider_info.model
231
220
yield chunk
232
221
233
222
if finish_reason is not None:
@@ -256,32 +245,13 @@ async def async_iter_response(
256
245
conversation=conversation,
257
246
reasoning=reasoning if reasoning else None
258
247
)
259
if provider is not None:
260
chat_completion.provider = provider.name
261
chat_completion.model = provider.model
248
if provider_info is not None:
249
chat_completion.provider = provider_info.name
250
chat_completion.model = provider_info.model
262
251
yield chat_completion
263
252
finally:
264
253
await safe_aclose(response)
265
254
266
async def async_iter_append_model_and_provider(
267
response: AsyncChatCompletionResponseType,
268
last_model: str,
269
last_provider: ProviderType
270
) -> AsyncChatCompletionResponseType:
271
try:
272
if isinstance(last_provider, BaseRetryProvider):
273
async for chunk in response:
274
yield chunk
275
return
276
async for chunk in response:
277
if isinstance(chunk, (ChatCompletion, ChatCompletionChunk)):
278
if chunk.provider is None and last_provider is not None:
279
chunk.model = getattr(last_provider, "last_model", last_model)
280
chunk.provider = last_provider.__name__
281
yield chunk
282
finally:
283
await safe_aclose(response)
284
285
255
class Client(BaseClient):
286
256
def __init__(
287
257
self,
@@ -350,9 +320,10 @@ class Completions:
350
320
**kwargs
351
321
)
352
322
323
provider_info = ProviderInfo(**provider.get_dict(), model=model)
324
353
325
def fallback(response):
354
response = iter_response(response, stream, response_format, max_tokens, stop)
355
return iter_append_model_and_provider(response, model, provider)
326
return iter_response(response, stream, response_format, max_tokens, stop, provider_info)
356
327
357
328
if raw:
358
329
def raw_response(response):
@@ -689,8 +660,8 @@ class AsyncCompletions:
689
660
)
690
661
691
662
def fallback(response):
692
response = async_iter_response(response, stream, response_format, max_tokens, stop)
693
return async_iter_append_model_and_provider(response, model, provider)
663
provider_info = ProviderInfo(**provider.get_dict(), model=model)
664
return async_iter_response(response, stream, response_format, max_tokens, stop, provider_info)
694
665
695
666
if raw:
696
667
async def raw_response(response):
@@ -816,7 +787,7 @@ class ClientFactory:
816
787
)
817
788
818
789
# Create async client
819
async_client = ClientFactory.createAsyncClient("PollinationsAI")
790
async_client = ClientFactory.create_async_client("PollinationsAI")
820
791
"""
821
792
822
793
# Registry of live/custom providers
@@ -850,7 +821,7 @@ class ClientFactory:
850
821
elif provider.startswith("custom:"):
851
822
if provider.startswith("custom:"):
852
823
serverId = provider[7:]
853
base_url = f"https://g4f.dev/custom/{serverId}"
824
base_url = f"https://api.gpt4free.workers.dev/custom/{serverId}"
854
825
if not base_url:
855
826
raise ValueError("base_url is required for custom providers")
856
827
provider = create_custom_provider(base_url, api_key, name=name, **kwargs)