返回提交历史
Modified
g4f/Provider/Cloudflare.py
+5
-1
Modified
g4f/Provider/PollinationsAI.py
+1
-1
Modified
g4f/gui/server/backend_api.py
+48
-15
Modified
g4f/integration/markitdown/_audio_converter.py
+2
-2
Modified
g4f/integration/markitdown/_transcribe_audio.py
+4
-2
XFEstudio/gpt4free
fix: handle RuntimeError during asyncio.run in Cloudflare.py and rename key in PollinationsAI.py
- Added try-except block to catch RuntimeError around asyncio.run(nodriver_read_models()) in Cloudflare.py to set cls.models to fallback_models if encountered - Corrected indentation of "followups" key in PollinationsAI.py from 43 to 44, changing it from nested to proper dictionary key - No other code logic changed in these files
73f751ef
代码差异
5 个文件
+60
-21
@@ -85,7 +85,11 @@ class Cloudflare(AsyncGeneratorProvider, ProviderModelMixin, AuthFileMixin):
85
85
debug.log(f"Nodriver is not available: {type(e).__name__}: {e}")
86
86
cls.models = cls.fallback_models
87
87
get_running_loop(check_nested=True)
88
asyncio.run(nodriver_read_models())
88
try:
89
asyncio.run(nodriver_read_models())
90
except RuntimeError:
91
debug.log("Nodriver is not available: RuntimeError")
92
cls.models = cls.fallback_models
89
93
else:
90
94
cls.models = cls.fallback_models
91
95
debug.log(f"Nodriver is not installed: {type(f).__name__}: {f}")
@@ -43,7 +43,7 @@ FOLLOWUPS_TOOLS = [{
43
43
"title": "Conversation Title",
44
44
"type": "string"
45
45
},
46
"followups": {
46
"followups": {
47
47
"items": {
48
48
"type": "string"
49
49
},
@@ -24,14 +24,14 @@ except ImportError as e:
24
24
25
25
from ...client.service import convert_to_provider
26
26
from ...providers.asyncio import to_sync_generator
27
from ...providers.response import FinishReason
27
from ...providers.response import FinishReason, AudioResponse, MediaResponse, Reasoning, HiddenResponse
28
28
from ...client.helper import filter_markdown
29
29
from ...tools.files import supports_filename, get_streaming, get_bucket_dir, get_tempfile
30
30
from ...tools.run_tools import iter_run_tools
31
31
from ...errors import ProviderNotFoundError
32
32
from ...image import is_allowed_extension, MEDIA_TYPE_MAP
33
33
from ...cookies import get_cookies_dir
34
from ...image.copy_images import secure_filename, get_source_url, get_media_dir
34
from ...image.copy_images import secure_filename, get_source_url, get_media_dir, copy_media
35
35
from ... import ChatCompletion
36
36
from ... import models
37
37
from .api import Api
@@ -233,23 +233,44 @@ class Backend_Api(Api):
233
233
parameters = {
234
234
"model": request.args.get("model"),
235
235
"messages": [{"role": "user", "content": request.args.get("prompt")}],
236
"provider": request.args.get("provider", None),
236
"provider": request.args.get("provider", request.args.get("audio_provider", "AnyProvider")),
237
237
"stream": not do_filter and not cache_id,
238
238
"ignore_stream": not request.args.get("stream"),
239
239
"tool_calls": tool_calls,
240
240
}
241
if request.args.get("audio_provider") or request.args.get("audio"):
242
parameters["audio"] = {}
241
243
def cast_str(response):
242
for chunk in response:
243
if isinstance(chunk, FinishReason):
244
yield f"[{chunk.reason}]" if chunk.reason != "stop" else ""
245
elif not isinstance(chunk, Exception):
246
chunk = str(chunk)
247
if chunk:
248
yield chunk
244
buffer = next(response)
245
while isinstance(buffer, (Reasoning, HiddenResponse)):
246
buffer = next(response)
247
if isinstance(buffer, MediaResponse):
248
if len(buffer.get_list()) == 1:
249
if not cache_id:
250
return buffer.get_list()[0]
251
return asyncio.run(copy_media(
252
buffer.get_list(),
253
buffer.get("cookies"),
254
buffer.get("headers"),
255
request.args.get("prompt")
256
)).pop()
257
elif isinstance(buffer, AudioResponse):
258
return buffer.data
259
def iter_response():
260
yield str(buffer)
261
for chunk in response:
262
if isinstance(chunk, FinishReason):
263
yield f"[{chunk.reason}]" if chunk.reason != "stop" else ""
264
elif not isinstance(chunk, Exception):
265
chunk = str(chunk)
266
if chunk:
267
yield chunk
268
return iter_response()
269
249
270
if cache_id:
250
271
cache_id = sha256(cache_id.encode() + json.dumps(parameters, sort_keys=True).encode()).hexdigest()
251
272
cache_dir = Path(get_cookies_dir()) / ".scrape_cache" / "create"
252
cache_file = cache_dir / f"{quote_plus(request.args.get('prompt').strip()[:20])}.{cache_id}.txt"
273
cache_file = cache_dir / f"{quote_plus(request.args.get('prompt', '').strip()[:20])}.{cache_id}.txt"
253
274
response = None
254
275
if cache_file.exists():
255
276
with cache_file.open("r") as f:
@@ -260,11 +281,22 @@ class Backend_Api(Api):
260
281
copy_response = cast_str(response)
261
282
if copy_response:
262
283
with cache_file.open("w") as f:
263
for chunk in copy_response:
284
for chunk in [copy_response] if isinstance(copy_response, str) else copy_response:
264
285
f.write(chunk)
265
286
response = copy_response
266
287
else:
267
288
response = cast_str(iter_run_tools(ChatCompletion.create, **parameters))
289
if isinstance(response, str):
290
if response.startswith("/media/"):
291
media_dir = get_media_dir()
292
filename = os.path.basename(response.split("?")[0])
293
try:
294
return send_from_directory(os.path.abspath(media_dir), filename)
295
finally:
296
if not cache_id:
297
os.remove(os.path.join(media_dir, filename))
298
elif response.startswith("https://") or response.startswith("http://"):
299
return redirect(response)
268
300
if do_filter:
269
301
is_true_filter = do_filter.lower() in ["true", "1"]
270
302
response = "".join(response)
@@ -320,7 +352,7 @@ class Backend_Api(Api):
320
352
result = md.convert(copyfile, stream_info=StreamInfo(
321
353
extension=suffix,
322
354
mimetype=file.mimetype,
323
), language=language).text_content
355
),recognition_language=language).text_content
324
356
except Exception as e:
325
357
logger.exception(e)
326
358
is_media = is_allowed_extension(filename)
@@ -336,7 +368,7 @@ class Backend_Api(Api):
336
368
os.makedirs(media_dir, exist_ok=True)
337
369
newfile = os.path.join(media_dir, filename)
338
370
media.append({"name": filename, "text": result})
339
elif not result and supports_filename(filename):
371
elif not result and is_supported:
340
372
newfile = os.path.join(bucket_dir, filename)
341
373
filenames.append(filename)
342
374
try:
@@ -345,7 +377,8 @@ class Backend_Api(Api):
345
377
shutil.copyfile(copyfile, newfile)
346
378
os.remove(copyfile)
347
379
with open(os.path.join(bucket_dir, "files.txt"), 'w') as f:
348
f.write("".join([f"{filename}\n" for filename in filenames]))
380
for filename in filenames:
381
f.write(f"{filename}\n")
349
382
return {"bucket_id": bucket_id, "files": filenames, "media": media}
350
383
351
384
@app.route('/files/<bucket_id>/media/<filename>', methods=['GET'])
@@ -50,7 +50,7 @@ class AudioConverter(DocumentConverter):
50
50
self,
51
51
file_stream: BinaryIO,
52
52
stream_info: StreamInfo,
53
language: str = "en-US",
53
recognition_language: str = None,
54
54
**kwargs: Any, # Options to pass to the converter
55
55
) -> DocumentConverterResult:
56
56
md_content = ""
@@ -97,7 +97,7 @@ class AudioConverter(DocumentConverter):
97
97
# Transcribe
98
98
if audio_format:
99
99
try:
100
md_content = transcribe_audio(file_stream, audio_format=audio_format, language=language)
100
md_content = transcribe_audio(file_stream, audio_format=audio_format, language=recognition_language)
101
101
except MissingDependencyException:
102
102
pass
103
103
@@ -20,7 +20,7 @@ except ImportError:
20
20
_dependency_exc_info = sys.exc_info()
21
21
22
22
23
def transcribe_audio(file_stream: BinaryIO, *, audio_format: str = "wav", language: str = "en-US") -> str:
23
def transcribe_audio(file_stream: BinaryIO, *, audio_format: str = "wav", language: str = None) -> str:
24
24
# Check for installed dependencies
25
25
if _dependency_exc_info is not None:
26
26
raise MissingDependencyException(
@@ -45,5 +45,7 @@ def transcribe_audio(file_stream: BinaryIO, *, audio_format: str = "wav", langua
45
45
recognizer = sr.Recognizer()
46
46
with sr.AudioFile(audio_source) as source:
47
47
audio = recognizer.record(source)
48
if language is None:
49
language = "en-US"
48
50
transcript = recognizer.recognize_google(audio, language=language).strip()
49
return "[No speech detected]" if transcript == "" else transcript
51
return "[No speech detected]" if transcript == "" else transcript.strip()