返回提交历史
Modified
g4f/Provider/audio/MarkItDown.py
+5
-13
Modified
g4f/Provider/needs_auth/OpenaiChat.py
+11
-7
Modified
g4f/image/__init__.py
+3
-2
Modified
g4f/integration/markitdown/_youtube_converter.py
+0
-3
XFEstudio/gpt4free
Refactor MarkItDown and OpenaiChat classes for improved media handling and optional parameters; enhance is_data_an_media function to support binary/octet-stream return type for unsupported URLs.
2317bd5a
代码差异
4 个文件
+19
-25
@@ -2,7 +2,6 @@ from __future__ import annotations
2
2
3
3
import os
4
4
import asyncio
5
from typing import Any
6
5
7
6
try:
8
7
from ...integration.markitdown import MarkItDown as MaItDo, StreamInfo
@@ -23,7 +22,6 @@ class MarkItDown(AsyncGeneratorProvider, ProviderModelMixin):
23
22
model: str,
24
23
messages: Messages,
25
24
media: MediaListType = None,
26
llm_client: Any = None,
27
25
**kwargs
28
26
) -> AsyncResult:
29
27
if media is None:
@@ -34,12 +32,10 @@ class MarkItDown(AsyncGeneratorProvider, ProviderModelMixin):
34
32
for file, filename in media:
35
33
text = None
36
34
try:
37
result = md.convert(
38
file,
39
stream_info=StreamInfo(filename=filename) if filename else None,
40
llm_client=llm_client,
41
llm_model=model
42
)
35
if isinstance(file, str) and file.startswith(("http://", "https://")):
36
result = md.convert_url(file)
37
else:
38
result = md.convert(file, stream_info=StreamInfo(filename=filename) if filename else None)
43
39
if asyncio.iscoroutine(result.text_content):
44
40
text = await result.text_content
45
41
else:
@@ -47,11 +43,7 @@ class MarkItDown(AsyncGeneratorProvider, ProviderModelMixin):
47
43
except TypeError:
48
44
copyfile = get_tempfile(file, filename)
49
45
try:
50
result = md.convert(
51
copyfile,
52
llm_client=llm_client,
53
llm_model=model
54
)
46
result = md.convert(copyfile)
55
47
if asyncio.iscoroutine(result.text_content):
56
48
text = await result.text_content
57
49
else:
@@ -24,7 +24,7 @@ from ...requests import StreamSession
24
24
from ...requests import get_nodriver_session
25
25
from ...image import ImageRequest, to_image, to_bytes, is_accepted_format, detect_file_type
26
26
from ...errors import MissingAuthError, NoValidHarFileError, ModelNotFoundError
27
from ...providers.response import JsonConversation, FinishReason, SynthesizeData, AuthResult, ImageResponse, ImagePreview, ResponseType, format_link
27
from ...providers.response import JsonConversation, FinishReason, SynthesizeData, AuthResult, ImageResponse, ImagePreview, ResponseType, JsonRequest, format_link
28
28
from ...providers.response import TitleGeneration, RequestLogin, Reasoning
29
29
from ...tools.media import merge_media
30
30
from ..helper import format_cookies, format_media_prompt, to_string
@@ -330,14 +330,15 @@ class OpenaiChat(AsyncAuthedProvider, ProviderModelMixin):
330
330
proxy: str = None,
331
331
timeout: int = 360,
332
332
auto_continue: bool = False,
333
action: str = "next",
333
action: Optional[str] = None,
334
334
conversation: Conversation = None,
335
335
media: MediaListType = None,
336
336
return_conversation: bool = True,
337
337
web_search: bool = False,
338
338
prompt: str = None,
339
conversation_mode=None,
340
temporary=False,
339
conversation_mode: Optional[dict] = None,
340
temporary: Optional[bool] = None,
341
conversation_id: Optional[str] = None,
341
342
**kwargs
342
343
) -> AsyncResult:
343
344
"""
@@ -351,7 +352,6 @@ class OpenaiChat(AsyncAuthedProvider, ProviderModelMixin):
351
352
api_key (str): Access token for authentication.
352
353
auto_continue (bool): Flag to automatically continue the conversation.
353
354
action (str): Type of action ('next', 'continue', 'variant').
354
conversation_id (str): ID of the conversation.
355
355
media (MediaListType): Images to include in the conversation.
356
356
return_conversation (bool): Flag to include response fields in the output.
357
357
**kwargs: Additional keyword arguments.
@@ -362,6 +362,10 @@ class OpenaiChat(AsyncAuthedProvider, ProviderModelMixin):
362
362
Raises:
363
363
RuntimeError: If an error occurs during processing.
364
364
"""
365
if temporary is None:
366
temporary = action is not None and conversation_id is not None
367
if action is None:
368
action = "next"
365
369
async with StreamSession(
366
370
proxy=proxy,
367
371
impersonate="chrome",
@@ -431,7 +435,6 @@ class OpenaiChat(AsyncAuthedProvider, ProviderModelMixin):
431
435
}
432
436
if temporary:
433
437
data["history_and_training_disabled"] = True
434
435
438
async with session.post(
436
439
prepare_url,
437
440
json=data,
@@ -494,7 +497,7 @@ class OpenaiChat(AsyncAuthedProvider, ProviderModelMixin):
494
497
if temporary:
495
498
data["history_and_training_disabled"] = True
496
499
497
if conversation.conversation_id is not None:
500
if conversation.conversation_id is not None and not temporary:
498
501
data["conversation_id"] = conversation.conversation_id
499
502
debug.log(f"OpenaiChat: Use conversation: {conversation.conversation_id}")
500
503
prompt = conversation.prompt = format_media_prompt(messages, prompt)
@@ -510,6 +513,7 @@ class OpenaiChat(AsyncAuthedProvider, ProviderModelMixin):
510
513
else:
511
514
new_messages.append(message)
512
515
data["messages"] = cls.create_messages(new_messages, image_requests, ["search"] if web_search else None)
516
yield JsonRequest.from_dict(data)
513
517
headers = {
514
518
**cls._headers,
515
519
"accept": "text/event-stream",
@@ -107,11 +107,12 @@ def is_data_an_media(data, filename: str = None) -> str:
107
107
return content_type
108
108
if isinstance(data, bytes):
109
109
return is_accepted_format(data)
110
if isinstance(data, str) and data.startswith("http"):
110
if isinstance(data, str) and data.startswith(("http://", "https://")):
111
111
path = urlparse(data).path
112
112
extension = get_extension(path)
113
113
if extension is not None:
114
return EXTENSIONS_MAP[extension]
114
return EXTENSIONS_MAP[extension]
115
return "binary/octet-stream"
115
116
return is_data_uri_an_image(data)
116
117
117
118
def is_valid_media(data: ImageType = None, filename: str = None) -> str:
@@ -75,7 +75,6 @@ class YouTubeConverter(DocumentConverter):
75
75
) -> DocumentConverterResult:
76
76
# Parse the stream
77
77
encoding = "utf-8" if stream_info.charset is None else stream_info.charset
78
print(file_stream)
79
78
soup = bs4.BeautifulSoup(file_stream, "html.parser", from_encoding=encoding)
80
79
81
80
# Read the meta tags
@@ -95,8 +94,6 @@ class YouTubeConverter(DocumentConverter):
95
94
if key and content: # Only add non-empty content
96
95
metadata[key] = content
97
96
break
98
99
print(f"Extracted metadata keys: {list(metadata.keys())}")
100
97
101
98
# Try reading the description
102
99
try: